ecere/com/instance: Added strspn, strcspn, strpbrk built-in definitions
[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       if((_class = eSystem_FindClass(module, name)))
2382       {
2383          if(!_class.internalDecl)
2384          {
2385             if(declMode != baseSystemAccess)
2386                // i18n in instance.ec is more trouble than it's worth.
2387                printf("error: Redefinition of class %s\n", name);
2388             else
2389             {
2390                _class.comRedefinition = true;
2391                return _class;
2392             }
2393             return null;
2394          }
2395
2396          FreeTemplatesDerivatives(_class);
2397
2398          classLink = (BTNamedLink)_class.nameSpace->classes.FindString(name + start);
2399          _class.nameSpace->classes.Delete((BTNode)classLink);
2400          {
2401             OldLink t;
2402             for(t = _class.templatized.first; t; t = t.next)
2403             {
2404                Class template = t.data;
2405                classLink = (BTNamedLink)_class.nameSpace->classes.FindString(template.name);
2406
2407                _class.nameSpace->classes.Delete((BTNode)classLink);
2408             }
2409          }
2410          {
2411             NameSpace * ns = _class.nameSpace;
2412             while(ns->parent &&
2413                !ns->classes.first &&
2414                !ns->functions.first &&
2415                !ns->defines.first &&
2416                !ns->nameSpaces.first)
2417             {
2418                NameSpace * parent = ns->parent;
2419                NameSpace_Free(ns);
2420                parent->nameSpaces.Delete((BTNode)ns);
2421                ns = parent;
2422             }
2423          }
2424          refine = true;
2425       }
2426       else
2427       {
2428          classLink = SearchNameSpace(module.application.privateNameSpace, name, &((NameSpace *)0)->classes);
2429          if(!classLink)
2430             classLink = SearchNameSpace(module.application.publicNameSpace, name, &((NameSpace *)0)->classes);
2431
2432          if(!classLink)
2433             classLink = SearchNameSpace(module.application.privateNameSpace, name + start, &((NameSpace *)0)->classes);
2434          if(!classLink)
2435             classLink = SearchNameSpace(module.application.publicNameSpace, name + start, &((NameSpace *)0)->classes);
2436
2437          if(classLink)
2438             _class = classLink.data;
2439          if(_class && _class.internalDecl)
2440          {
2441             FreeTemplatesDerivatives(_class);
2442
2443             _class.nameSpace->classes.Delete((BTNode)classLink);
2444             {
2445                OldLink t;
2446                for(t = _class.templatized.first; t; t = t.next)
2447                {
2448                   Class template = t.data;
2449                   classLink = (BTNamedLink)_class.nameSpace->classes.FindString(template.name);
2450                   _class.nameSpace->classes.Delete((BTNode)classLink);
2451
2452                }
2453             }
2454
2455             refine = true;
2456             delete _class.fullName;
2457             _class.fullName = CopyString(name);
2458          }
2459          else
2460          {
2461             _class = _calloc(1, sizeof(class Class));
2462             _class.methods.CompareKey = (void *)BinaryTree::CompareString;
2463             _class.members.CompareKey = (void *)BinaryTree::CompareString;
2464             _class.prop.CompareKey = (void *)BinaryTree::CompareString;
2465             _class.classProperties.CompareKey = (void *)BinaryTree::CompareString;
2466
2467             _class.name = CopyString(name + start);
2468             _class.fullName = CopyString(name);
2469          }
2470       }
2471       if(nameSpace)
2472       {
2473          nameSpace->classes.Add((BTNode)BTNamedLink { name = _class.name, data = _class });
2474          {
2475             OldLink t;
2476             for(t = _class.templatized.first; t; t = t.next)
2477             {
2478                Class template = t.data;
2479                nameSpace->classes.Add((BTNode)BTNamedLink { name = template.name, data = template });
2480             }
2481          }
2482
2483       }
2484
2485       if(_class)
2486       {
2487          if(!base && baseName && strcmp(baseName, name))
2488          {
2489             // Undefined base
2490             if(strchr(baseName, '<'))
2491             {
2492                char templateClassName[1024];
2493                Class templateBase;
2494                strcpy(templateClassName, baseName);
2495                *strchr(templateClassName, '<') = '\0';
2496                templateBase = eSystem_FindClass(module, templateClassName);
2497                if(!templateBase)
2498                {
2499                   templateBase = eSystem_RegisterClass(0, templateClassName, null, 0,0, null, null, module, declMode, publicAccess);
2500                   templateBase.internalDecl = true;
2501                }
2502                base = eSystem_FindClass(module, baseName);
2503             }
2504             else
2505             {
2506                base = eSystem_RegisterClass(0, baseName, null, 0,0, null, null, module, declMode, publicAccess);
2507                base.internalDecl = true;
2508             }
2509             /*
2510             base.size = 0;
2511             base.offset = 0;
2512             base.memberOffset = 0;
2513             */
2514          }
2515          else
2516             _class.internalDecl = false;
2517
2518          if(totalSizeClass)
2519          {
2520             _class.data = renew _class.data byte[totalSizeClass];
2521             // Class Data is often not inherited... e.g. Window::pureVtbl problem
2522             // memset(_class.data, 0, totalSizeClass);
2523             if(base && base.type != systemClass && base.type != enumClass)
2524                memcpy(_class.data, base.data, offsetClass);
2525             else
2526                memset(_class.data, 0, offsetClass);
2527             memset((byte *)_class.data + offsetClass, 0, sizeClass);
2528          }
2529
2530          delete _class.dataTypeString;
2531          _class.dataTypeString = CopyString(dataTypeString);
2532          _class.defaultAlignment = base ? base.defaultAlignment : 0;
2533
2534          // Dereference the class in previous module the classed belonged to
2535          if(_class.module)
2536          {
2537             _class.module.classes.Remove(_class);
2538          }
2539
2540          if(_class.base)
2541          {
2542             //Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
2543             Class base = _class.base;
2544             OldLink deriv = base.derivatives.FindLink(_class);
2545             base.derivatives.Delete(deriv);
2546          }
2547
2548          // Reference the class in the module
2549          if(module)
2550          {
2551             module.classes.Add(_class);
2552          }
2553
2554          _class.nameSpace = nameSpace;
2555          {
2556             OldLink t;
2557             for(t = _class.templatized.first; t; t = t.next)
2558             {
2559                Class template = t.data;
2560                template.nameSpace = nameSpace;
2561             }
2562          }
2563
2564          _class.module = module;
2565          prevBase = _class.base;
2566          _class.base = base;
2567          if(base)
2568          {
2569             int numParams = 0;
2570             Class sClass;
2571             for(sClass = base; sClass; sClass = sClass.base)
2572             {
2573                if(sClass.templateClass) sClass = sClass.templateClass;
2574                numParams += sClass.templateParams.count;
2575             }
2576             if(numParams)
2577             {
2578                if(_class.templateArgs)
2579                {
2580                   FreeTemplateArgs(_class);
2581                }
2582                delete _class.templateArgs;
2583                _class.templateArgs = new0 ClassTemplateArgument[numParams];
2584                _class.numParams = numParams;
2585
2586                for(sClass = _class; sClass; sClass = sClass.base)
2587                {
2588                   Class prevClass;
2589                   ClassTemplateParameter param;
2590                   int id = 0;
2591                   if(sClass.templateClass) sClass = sClass.templateClass;
2592                   for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
2593                   {
2594                      if(prevClass.templateClass) prevClass = prevClass.templateClass;
2595                      id += prevClass.templateParams.count;
2596                   }
2597
2598                   if(base.templateArgs)   // Add numParams test here?
2599                   {
2600                      for(param = sClass.templateParams.first; param; param = param.next)
2601                      {
2602                         _class.templateArgs[id] = base.templateArgs[id];
2603                         CopyTemplateArg(param, _class.templateArgs[id]);
2604                         id++;
2605                      }
2606                   }
2607                }
2608             }
2609          }
2610          _class.memberID = _class.startMemberID = (base && (type == normalClass || type == noHeadClass || type == structClass)) ? base.memberID : 0;
2611          if(type == normalClass || type == noHeadClass)
2612             _class.offset = (base && base.structSize && base.type != systemClass) ? base.structSize : ((type == noHeadClass) ? 0 : ((force64Bits && inCompiler && fixed) ? 24 : (force32Bits && inCompiler && fixed) ? 12 : sizeof(class Instance)));
2613
2614          // For cross-bitness-compiling
2615          if(crossBits)
2616          {
2617             // The GNOSIS runtime will use 'offset' to point to the object during compile executation
2618             // Need to rethink through our cross-bitness compiling to have a distinct 'offset' (e.g. runtimeOffset)
2619             // used by the runtime library vs. 'offset' used by the compiler to hardcode compilation results (or avoid those altogether)
2620             if(!strcmp(name, "GNOSISSystem") ||
2621                !strcmp(name, "LineStyle") ||
2622                !strcmp(name, "FillStyle") ||
2623                !strcmp(name, "FontObject") ||
2624                !strcmp(name, "SymbolStyle"))
2625             {
2626                _class.offset = force32Bits ? 24 : 12;
2627             }
2628             // 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
2629             else if(strstr(name, "ecere::sys::EARHeader") ||
2630                strstr(name, "AnchorValue") ||
2631                !strcmp(name, "ecere::com::CustomAVLTree") ||
2632                !strcmp(name, "ecere::com::Array") ||
2633                !strcmp(name, "ecere::gui::Window") ||
2634                !strcmp(name, "ecere::sys::Mutex"));   // Never recompute these, they're always problematic (errors, crashes)
2635             else
2636             {
2637                if(!strcmp(name, "ecere::sys::FileListing"))
2638                {
2639                   size = 3*(force32Bits ? 4 : 8);
2640                   _class.structAlignment = force32Bits ? 4 : 8;   // FileListing is problematic because it is a struct with private data that the user allocates
2641                }
2642                // These we want to recompute inside the IDE to help the debugger
2643                else if(!strcmp(name, "ecere::com::Class"))           size = 0; // 616
2644                else if(!strcmp(name, "ecere::com::ClassProperty"))   size = 0; // 80
2645                else if(!strcmp(name, "ecere::com::NameSpace"))       size = 0; // 176
2646                else if(!strcmp(name, "ecere::sys::BufferedFile"))    size = 0;
2647                else if(!strcmp(name, "ecere::sys::BTNode"))          size = 0;
2648                else if(!strcmp(name, "ecere::sys::StringBTNode"))    size = 0;
2649                else if(!strcmp(name, "ecere::sys::OldList"))         size = 0; // 32
2650                else if(!strcmp(name, "ecere::sys::Item"))            size = 0;
2651                else if(!strcmp(name, "ecere::sys::NamedLink"))       size = 0;
2652                else if(!strcmp(name, "ecere::sys::OldLink"))         size = 0;
2653                else if(!strcmp(name, "ecere::sys::NamedItem"))       size = 0;
2654                else if(!strcmp(name, "ecere::sys::NamedItem64"))     size = 0;
2655                else if(!strcmp(name, "ecere::sys::BinaryTree"))      size = 0;
2656                else if(module != module.application && inCompiler)
2657                {
2658                   // These we only want to recompute inside the compiler
2659                   if(fixed || type == structClass)
2660                      size = 0;
2661                }
2662             }
2663          }
2664          if(type == structClass)
2665          {
2666             _class.memberOffset = (base && base.structSize && base.type != systemClass) ? base.structSize : 0;
2667             // THIS IS NEW...
2668             _class.typeSize = _class.structSize = _class.memberOffset + size;
2669          }
2670          else if(type == bitClass || type == enumClass || type == unitClass)
2671          {
2672             Class dataTypeClass = eSystem_FindClass(_class.module, dataTypeString);
2673             if(dataTypeClass)
2674                _class.typeSize = dataTypeClass.typeSize;
2675             _class.structSize = 0;
2676          }
2677          else if(type == normalClass || type == noHeadClass)
2678          {
2679             _class.structSize = _class.offset + size;
2680             _class.typeSize = sizeof(void *);
2681          }
2682          _class.offsetClass = offsetClass;
2683          _class.sizeClass = totalSizeClass;
2684          _class.Constructor = (void *)Constructor;
2685          _class.Destructor = Destructor;
2686          if(_class.type != systemClass)
2687             _class.type = type;
2688          if(!size)
2689             _class.computeSize = true;
2690          else
2691             _class.computeSize = false;
2692          _class.inheritanceAccess = inheritanceAccess;
2693
2694          /*if(type == bitClass)
2695             _class.size = 0;*/
2696          if(type == enumClass)
2697          {
2698             if(enumBase)
2699                _class.base = base = enumBase;
2700             //else
2701             {
2702                EnumClassData data = (EnumClassData)_class.data;
2703                // TOCHECK: Trying this (if specifiers specified, no class found...)
2704                // What about bit classes, unit classes...
2705                if(base && base.type != enumClass)
2706                   data.largest = -1;//_class.base = null;
2707                else
2708                   data.largest = ((EnumClassData)(base.data)).largest;
2709             }
2710          }
2711          if(base)
2712          {
2713             int i;
2714             uint oldSize = _class.vTblSize;
2715             if(base.vTblSize && _class.vTblSize < base.vTblSize)
2716             {
2717                _class.vTblSize = base.vTblSize;
2718                // OK to scrap existing virtual table?
2719                //delete _class._vTbl;
2720                //_class._vTbl = _malloc(sizeof(int(*)()) * _class.vTblSize);
2721                // memcpy(_class._vTbl, base._vTbl, sizeof(int(*)()) * _class.vTblSize);
2722                _class._vTbl = _realloc(_class._vTbl, sizeof(int(*)()) * _class.vTblSize);
2723             }
2724             if(!prevBase)
2725             {
2726                if(_class.type == normalClass && strcmp(_class.name, "ecere::com::Instance") && strcmp(_class.name, "enum") && strcmp(_class.name, "struct"))
2727                   prevBase = eSystem_FindClass(module, "ecere::com::Instance");
2728                else
2729                   prevBase = eSystem_FindClass(module, "class");
2730             }
2731             for(i = 0; i < base.vTblSize; i++)
2732             {
2733                if(i >= oldSize || _class._vTbl[i] == prevBase._vTbl[i])
2734                   _class._vTbl[i] = base._vTbl[i];
2735             }
2736          }
2737
2738          if(_class.base)
2739          {
2740             OldLink link { data = _class };
2741             /*(_class.base.templateClass ? _class.base.templateClass : _class.base)*/_class.base.derivatives.Add(link);
2742          }
2743
2744          FixDerivativesBase(_class, _class);
2745
2746          return _class;
2747       }
2748    }
2749    return null;
2750 }
2751
2752 static void DataMember_Free(DataMember parentMember)
2753 {
2754    DataMember member;
2755    BTNamedLink namedLink;
2756    delete parentMember.name;
2757    delete parentMember.dataTypeString;
2758
2759    while((member = parentMember.members.first))
2760    {
2761       DataMember_Free(member);
2762       parentMember.members.Delete(member);
2763    }
2764
2765    while((namedLink = (BTNamedLink)parentMember.membersAlpha.first))
2766    {
2767       parentMember.membersAlpha.Delete((BTNode)namedLink);
2768    }
2769 }
2770
2771 static void FreeEnumValue(NamedLink value)
2772 {
2773    delete value.name;
2774 }
2775
2776 static void FreeTemplateArg(Class template, ClassTemplateParameter param, int id)
2777 {
2778    switch(param.type)
2779    {
2780       case type:
2781          delete template.templateArgs[id].dataTypeString;
2782          break;
2783       case identifier:
2784          delete template.templateArgs[id].memberString;
2785          break;
2786       case expression:
2787
2788          break;
2789    }
2790 }
2791
2792 static void FreeTemplateArgs(Class template)
2793 {
2794    if(template.templateArgs)
2795    {
2796       Class _class;
2797       for(_class = template; _class; _class = _class.base)
2798       {
2799          Class prevClass;
2800          ClassTemplateParameter param;
2801          int id = 0;
2802          if(_class.templateClass) _class = _class.templateClass;
2803          for(prevClass = _class.base; prevClass; prevClass = prevClass.base)
2804          {
2805             if(prevClass.templateClass) prevClass = prevClass.templateClass;
2806             id += prevClass.templateParams.count;
2807          }
2808          if(id < template.numParams)
2809          {
2810             for(param = _class.templateParams.first; param; param = param.next)
2811             {
2812                switch(param.type)
2813                {
2814                   case type:
2815                      delete template.templateArgs[id].dataTypeString;
2816                      break;
2817                   case identifier:
2818                      delete template.templateArgs[id].memberString;
2819                      break;
2820                   case expression:
2821                      // delete template.templateArgs[id].dataTypeString;
2822                      break;
2823                }
2824                id++;
2825             }
2826          }
2827       }
2828    }
2829 }
2830
2831 static void FreeTemplate(Class template)
2832 {
2833    OldLink deriv;
2834
2835    if(template.nameSpace)
2836    {
2837       BTNamedLink link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
2838       template.nameSpace->classes.Delete((BTNode)link);
2839    }
2840    FreeTemplateArgs(template);
2841
2842    delete template.fullName;
2843    delete template.name;
2844    delete template.templateArgs;
2845    delete template.dataTypeString;
2846
2847    while((deriv = template.derivatives.first))
2848    {
2849       ((Class)deriv.data).base = null;
2850       template.derivatives.Delete(deriv);
2851    }
2852
2853    _free(template);
2854 }
2855
2856 static void FreeTemplates(Class _class)
2857 {
2858    OldLink deriv, template;
2859
2860    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
2861    {
2862       FreeTemplates(deriv.data);
2863    }
2864
2865    FreeTemplateArgs(_class);
2866    //if(_class.templateArgs)
2867       //printf("Deleting  Template args for %s\n", _class.name);
2868    delete _class.templateArgs;
2869    delete _class.dataTypeString;
2870
2871    while((template = _class.templatized.first))
2872    {
2873       FreeTemplates(template.data);
2874       FreeTemplate(template.data);
2875       _class.templatized.Delete(template);
2876    }
2877 }
2878
2879 public dllexport void eClass_Unregister(Class _class)
2880 {
2881    BTNamedLink namedLink;
2882    DataMember member;
2883    Method method;
2884    OldLink deriv, template;
2885    ClassProperty classProp;
2886    ClassTemplateParameter param;
2887
2888    delete _class._vTbl;
2889
2890    FreeTemplates(_class);
2891
2892    FreeTemplateArgs(_class);
2893    delete _class.templateArgs;
2894
2895    while((template = _class.templatized.first))
2896    {
2897       FreeTemplate(template.data);
2898       _class.templatized.Delete(template);
2899    }
2900
2901    while((member = _class.membersAndProperties.first))
2902    {
2903       if(!member.isProperty && (member.type == unionMember || member.type == structMember))
2904          DataMember_Free(member);
2905       delete member.name;
2906       delete member.dataTypeString;
2907       _class.membersAndProperties.Delete(member);
2908    }
2909
2910    while((member = _class.conversions.first))
2911    {
2912       delete member.name;
2913       delete member.dataTypeString;
2914       _class.conversions.Delete(member);
2915    }
2916
2917    while((namedLink = (BTNamedLink)_class.prop.first))
2918    {
2919       _class.prop.Delete((BTNode)namedLink);
2920    }
2921
2922    while((namedLink = (BTNamedLink)_class.members.first))
2923    {
2924       _class.members.Delete((BTNode)namedLink);
2925    }
2926
2927    while((classProp = (ClassProperty)_class.classProperties.first))
2928    {
2929       delete classProp.name;
2930       delete classProp.dataTypeString;
2931       _class.classProperties.Delete((BTNode)classProp);
2932    }
2933
2934    while((method = (Method)_class.methods.first))
2935    {
2936       delete method.name;
2937       delete method.dataTypeString;
2938       _class.methods.Delete((BTNode)method);
2939    }
2940
2941    if(_class.type == enumClass)
2942    {
2943       EnumClassData data = (EnumClassData)_class.data;
2944
2945       data.values.Free((void *)FreeEnumValue);
2946    }
2947    _class.delayedCPValues.Free(null);
2948
2949    _class.selfWatchers.Free(null);
2950
2951    if(_class.base)
2952    {
2953       // Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
2954       Class base = _class.base;
2955       for(deriv = base.derivatives.first; deriv; deriv = deriv.next)
2956       {
2957          if(deriv.data == _class)
2958             break;
2959       }
2960       if(deriv)
2961          base.derivatives.Delete(deriv);
2962    }
2963    while((deriv = _class.derivatives.first))
2964    {
2965       ((Class)deriv.data).base = null;
2966       _class.derivatives.Delete(deriv);
2967    }
2968
2969    if(_class.nameSpace)
2970    {
2971       BTNamedLink link = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
2972       _class.nameSpace->classes.Delete((BTNode)link);
2973    }
2974
2975    delete _class.name;
2976    delete _class.fullName;
2977
2978    delete _class.dataTypeString;
2979
2980    delete _class.data;
2981
2982    while((param = _class.templateParams.first))
2983    {
2984       switch(param.type)
2985       {
2986          case type:
2987             delete param.defaultArg.dataTypeString;
2988             break;
2989          case identifier:
2990             delete param.defaultArg.memberString;
2991             break;
2992          case expression:
2993
2994             break;
2995       }
2996       if(param.type != identifier) delete param.dataTypeString;
2997       delete param.name;
2998
2999       _class.templateParams.Delete(param);
3000    }
3001
3002    //_class.nameSpace->classes.Delete(_class);
3003    _free(_class);
3004 }
3005
3006 static BTNamedLink ScanNameSpace(NameSpace nameSpace, char * name, void * listOffset)
3007 {
3008    BinaryTree * tree = (BinaryTree *)((byte *)nameSpace + (uint)listOffset);
3009    BTNamedLink link = (BTNamedLink)tree->Find((uintptr)name);
3010    NameSpace * child;
3011    if(!link)
3012    {
3013       for(child = (NameSpace *)nameSpace.nameSpaces.first; child; child = (NameSpace *)((BTNode)child).next)
3014       {
3015          link = ScanNameSpace(child, name, listOffset);
3016          if(link)
3017             break;
3018       }
3019    }
3020    return link;
3021 }
3022
3023 static BTNamedLink SearchNameSpace(NameSpace nameSpace, char * name, void * listOffset)
3024 {
3025    int start = 0, c;
3026    char ch;
3027    int level = 0;
3028    for(c = 0; (ch = name[c]); c++)
3029    {
3030       if(ch == '<') level++;
3031       if(ch == '>') level--;
3032       if(level == 0 && (ch == '.' || (ch == ':' && name[c+1] == ':')))
3033       {
3034          NameSpace * newSpace;
3035          char * spaceName = _malloc(c - start + 1);
3036          memcpy(spaceName, name + start, c - start);
3037          spaceName[c-start] = '\0';
3038          newSpace = (NameSpace *)nameSpace.nameSpaces.FindString(spaceName);
3039          _free(spaceName);
3040          if(!newSpace)
3041             return null;
3042          nameSpace = newSpace;
3043          if(level == 0 && ch == ':') c++;
3044          start = c+1;
3045       }
3046    }
3047    if(c - start)
3048    {
3049       return ScanNameSpace(nameSpace, name + start, listOffset);
3050    }
3051    return null;
3052 }
3053
3054 static BTNamedLink SearchModule(Module module, char * name, void * listOffset, bool searchPrivate)
3055 {
3056    SubModule subModule;
3057    BTNamedLink link;
3058
3059    if(searchPrivate)
3060    {
3061       link = SearchNameSpace(&module.privateNameSpace, name, listOffset);
3062       if(link) return link;
3063    }
3064    link = SearchNameSpace(&module.publicNameSpace, name, listOffset);
3065    if(link) return link;
3066
3067    for(subModule = module.modules.first; subModule; subModule = subModule.next)
3068    {
3069       if(searchPrivate || subModule.importMode == publicAccess)
3070       {
3071          // TOCHECK: Reverting to false to test what we were trying to fix by passing searchPrivate
3072          // Passing searchPrivate finds ALL classes private or not and thus classes clash
3073          // SearchModule here is called mainly from eSystem_FindClass, and also for Functions and Defines
3074
3075          link = SearchModule(subModule.module, name, listOffset, false);
3076          //link = SearchModule(subModule.module, name, listOffset, searchPrivate /*false*/);
3077          if(link) return link;
3078       }
3079    }
3080    return null;
3081 }
3082
3083 public int64 _strtoi64(char * string, char ** endString, int base)
3084 {
3085    int64 value = 0;
3086    int sign = 1;
3087    int c;
3088    char ch;
3089    for(c = 0; (ch = string[c]) && isspace(ch); c++);
3090    if(ch =='+') c++;
3091    else if(ch == '-') { sign = -1; c++; };
3092    if(!base)
3093    {
3094       if(ch == '0' && string[c+1] == 'x')
3095       {
3096          base = 16;
3097          c+=2;
3098       }
3099       else if(ch == '0')
3100       {
3101          base = 8;
3102          c++;
3103       }
3104       else
3105          base = 10;
3106    }
3107    for( ;(ch = string[c]); c++)
3108    {
3109       if(ch >= '0' && ch <= '9')
3110          ch -= '0';
3111       else if(ch >= 'a' && ch <= 'z')
3112          ch -= ('a' - 10);
3113       else if(ch >= 'A' && ch <= 'Z')
3114          ch -= ('A'- 10);
3115       else
3116       {
3117          if(endString)
3118             *endString = string + c;
3119          // Invalid character
3120          break;
3121       }
3122       if(ch < base)
3123       {
3124          value *= base;
3125          value += ch;
3126       }
3127       else
3128       {
3129          if(endString)
3130             *endString = string + c;
3131          // Invalid character
3132          break;
3133       }
3134    }
3135    return sign*value;
3136 }
3137
3138 public uint64 _strtoui64(char * string, char ** endString, int base)
3139 {
3140    uint64 value = 0;
3141    int sign = 1;
3142    int c;
3143    char ch;
3144    for(c = 0; (ch = string[c]) && isspace(ch); c++);
3145    if(ch =='+') c++;
3146    else if(ch == '-') { sign = -1; c++; };
3147    if(!base)
3148    {
3149       if(ch == '0' && string[c+1] == 'x')
3150       {
3151          base = 16;
3152          c+=2;
3153       }
3154       else if(ch == '0')
3155       {
3156          base = 8;
3157          c++;
3158       }
3159       else
3160          base = 10;
3161    }
3162    for( ;(ch = string[c]); c++)
3163    {
3164       if(ch >= '0' && ch <= '9')
3165          ch -= '0';
3166       else if(ch >= 'a' && ch <= 'z')
3167          ch -= ('a' - 10);
3168       else if(ch >= 'A' && ch <= 'Z')
3169          ch -= ('A' - 10);
3170       else
3171       {
3172          if(endString)
3173             *endString = string + c;
3174          // Invalid character
3175          break;
3176       }
3177       if(ch < base)
3178       {
3179          value *= base;
3180          value += ch;
3181       }
3182       else
3183       {
3184          if(endString)
3185             *endString = string + c;
3186          // Invalid character
3187          break;
3188       }
3189    }
3190    return sign*value;
3191 }
3192
3193 public dllexport Class eSystem_FindClass(Module module, char * name)
3194 {
3195    if(name && module)
3196    {
3197       BTNamedLink link;
3198       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->classes);
3199       if(link) return link.data;
3200
3201       link = SearchModule(module, name, &((NameSpace *)0)->classes, true);
3202       if(link) return link.data;
3203
3204       {
3205          char noTemplateName[1024];
3206          char * templateParams = strchr(name, '<');
3207
3208          if(templateParams)
3209          {
3210             strncpy(noTemplateName, name, templateParams - name);
3211             noTemplateName[templateParams - name] = '\0';
3212          }
3213          else
3214             strcpy(noTemplateName, name);
3215
3216          link = SearchNameSpace(&module.application.systemNameSpace, noTemplateName, &((NameSpace *)0)->classes);
3217          if(!link)
3218             link = SearchModule(module, noTemplateName, &((NameSpace *)0)->classes, true);
3219          if(link)
3220          {
3221             Class _class = link.data;
3222             Class templatedClass = null;
3223             char className[1024];
3224             strcpy(className, _class.fullName);
3225             strcat(className, templateParams);
3226
3227             link = SearchNameSpace(&module.application.systemNameSpace, className, &((NameSpace *)0)->classes);
3228             if(link)
3229                return link.data;
3230
3231             link = SearchModule(module, className, &((NameSpace *)0)->classes, true);
3232             if(link)
3233                return link.data;
3234
3235             if(_class && templateParams)
3236             {
3237                // if(!numParams) return null;
3238
3239                templatedClass = Class { };
3240                *templatedClass = *_class;
3241                templatedClass.templateClass = _class;
3242                //templatedClass.fullName = CopyString(name);
3243                templatedClass.fullName = CopyString(className);
3244                templatedClass.dataTypeString = CopyString(_class.dataTypeString);
3245                templatedClass.name = CopyString(templatedClass.fullName + strlen(_class.fullName) - strlen(_class.name));
3246                templatedClass.nameSpace->classes.Add((BTNode)BTNamedLink { name = templatedClass.name, data = templatedClass });
3247                templatedClass.templateArgs = null;
3248                templatedClass.numParams = 0;
3249                templatedClass.derivatives = { };
3250                templatedClass.templatized = { };
3251
3252                ComputeClassParameters(templatedClass, templateParams, module);
3253
3254                _class.templatized.Add(OldLink { data = templatedClass });
3255             }
3256             return templatedClass;
3257          }
3258       }
3259    }
3260    return null;
3261 }
3262
3263 static void CopyTemplateArg(ClassTemplateParameter param, ClassTemplateArgument arg)
3264 {
3265    switch(param.type)
3266    {
3267       case type:
3268          arg.dataTypeString = CopyString(arg.dataTypeString);
3269          break;
3270       case expression:
3271
3272          break;
3273       case identifier:
3274          arg.memberString = CopyString(arg.memberString);
3275          break;
3276    }
3277 }
3278
3279 static void ComputeClassParameters(Class templatedClass, char * templateParams, Module findModule)
3280 {
3281    char ch;
3282    char * nextParamStart = templateParams ? (templateParams + 1) : null;
3283    ClassTemplateParameter curParam = null;
3284    Class lastClass = null, sClass;
3285    int curParamID = 0;
3286    int numParams = 0;
3287    Class _class = templatedClass.templateClass ? templatedClass.templateClass : templatedClass;
3288
3289    for(sClass = _class; sClass; sClass = sClass.base)
3290    {
3291       if(sClass.templateClass) sClass = sClass.templateClass;
3292       numParams += sClass.templateParams.count;
3293    }
3294
3295    if(templatedClass.templateArgs)
3296       FreeTemplateArgs(templatedClass);
3297    delete templatedClass.templateArgs;
3298    templatedClass.templateArgs = new0 ClassTemplateArgument[numParams];
3299    templatedClass.numParams = numParams;
3300
3301    if(_class != templatedClass)
3302    {
3303       /*int c;
3304       Class sClass;
3305       memcpy(templatedClass.templateArgs, _class.templateArgs, numParams * sizeof(ClassTemplateArgument));
3306       for(sClass = _class; sClass; sClass = sClass.base)
3307       {
3308          ClassTemplateParameter param;
3309          Class prevClass;
3310          int id = 0;
3311          if(sClass.templateClass) sClass = sClass.templateClass;
3312          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3313          {
3314             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3315             id += prevClass.templateParams.count;
3316          }
3317          for(param = sClass.templateParams.first; param; param = param.next)
3318            CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3319       }*/
3320    }
3321
3322    if(templatedClass.base && templatedClass.base.templateArgs && _class == templatedClass)
3323    {
3324       Class sClass;
3325       memcpy(templatedClass.templateArgs, templatedClass.base.templateArgs,
3326          sizeof(ClassTemplateArgument) * (numParams - templatedClass.templateParams.count));
3327       for(sClass = templatedClass.base; sClass; sClass = sClass.base)
3328       {
3329          ClassTemplateParameter param;
3330          Class prevClass;
3331          int id = 0;
3332          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3333          {
3334             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3335             id += prevClass.templateParams.count;
3336          }
3337
3338          if(sClass.templateClass) sClass = sClass.templateClass;
3339          for(param = sClass.templateParams.first; param; param = param.next)
3340             CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3341       }
3342    }
3343
3344    while(nextParamStart)
3345    {
3346       char * paramStart = nextParamStart;
3347       char * paramEnd;
3348       int level = 0;
3349       while(*paramStart == ' ') paramStart++;
3350       paramEnd = paramStart;
3351       while((ch = *paramEnd, ch && (level > 0 || (ch != '>' && ch != ','))))
3352       {
3353          if(ch == '<') level++;
3354          if(ch == '>') level--;
3355
3356          paramEnd++;
3357       }
3358       nextParamStart = (ch == ',') ? (paramEnd + 1) : null;
3359       while(*paramEnd == ' ') paramEnd--;
3360       if(paramEnd > paramStart)
3361       {
3362          char * ptr, * equal = null;
3363          for(ptr = paramStart; ptr <= paramEnd; ptr++)
3364          {
3365             if(*ptr == '=')
3366             {
3367                equal = ptr;
3368                break;
3369             }
3370          }
3371          if(equal)
3372          {
3373             char * end = equal - 1;
3374             char ident[1024];
3375
3376             while(*end == ' ') end--;
3377             strncpy(ident, paramStart, end + 1 - paramStart);
3378             ident[end + 1 - paramStart] = 0;
3379
3380             for(sClass = _class; sClass; sClass = sClass.base)
3381             {
3382                if(sClass.templateClass) sClass = sClass.templateClass;
3383                for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
3384                {
3385                   if(!strcmp(curParam.name, ident))
3386                      break;
3387                }
3388                if(curParam)
3389                {
3390                   Class nextClass;
3391                   ClassTemplateParameter prevParam;
3392                   curParamID = 0;
3393                   for(prevParam = curParam.prev; prevParam; prevParam = prevParam.prev) curParamID++;
3394                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3395                   {
3396                      if(nextClass.templateClass) nextClass = nextClass.templateClass;
3397                      curParamID += nextClass.templateParams.count;
3398                   }
3399                   break;
3400                }
3401             }
3402             lastClass = sClass;
3403          }
3404          else
3405          {
3406             if(curParam)
3407             {
3408                curParam = curParam.next;
3409                curParamID++;
3410             }
3411
3412             if(!curParam)
3413             {
3414                for(sClass = lastClass ? lastClass.base : _class; sClass; sClass = sClass.base)
3415                {
3416                   ClassTemplateParameter param;
3417                   curParamID = 0;
3418                   if(sClass.templateClass) sClass = sClass.templateClass;
3419                   for(param = sClass.templateParams.first; param; param = param.next, curParamID++)
3420                   {
3421                      curParam = param;
3422                      break;
3423                   }
3424                   if(curParam)
3425                   {
3426                      Class nextClass;
3427                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3428                      {
3429                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
3430                         curParamID += nextClass.templateParams.count;
3431                      }
3432                      lastClass = sClass;
3433                      break;
3434                   }
3435                }
3436                /*
3437                for(sClass = _class; sClass; sClass = sClass.base)
3438                {
3439                   if(sClass.templateParams.first)
3440                   {
3441                      Class nextClass;
3442                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3443                         if(nextClass.templateParams.first)
3444                            break;
3445                      if(nextClass != lastClass) continue;
3446
3447                      curParam = sClass.templateParams.first;
3448                      lastClass = sClass;
3449
3450                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3451                         if(nextClass.templateParams.first)
3452                         {
3453                            curParamID += nextClass.templateParams.count;
3454                            break;
3455                         }
3456                      break;
3457                   }
3458                }
3459                */
3460             }
3461          }
3462
3463          if(curParam)
3464          {
3465             ClassTemplateArgument argument { };
3466             char value[1024];
3467             if(equal)
3468             {
3469                equal++;
3470                while(*equal == ' ') equal++;
3471                memcpy(value, equal, paramEnd - equal);
3472                value[paramEnd - equal] = 0;
3473             }
3474             else
3475             {
3476                memcpy(value, paramStart, paramEnd - paramStart);
3477                value[paramEnd - paramStart] = 0;
3478             }
3479             TrimRSpaces(value, value);
3480
3481             switch(curParam.type)
3482             {
3483                case type:
3484                   argument.dataTypeString = CopyString(value);
3485                   argument.dataTypeClass = eSystem_FindClass(_class.module, value);
3486                   if(!argument.dataTypeClass) argument.dataTypeClass = eSystem_FindClass(_class.module.application, value);
3487                   if(!argument.dataTypeClass) argument.dataTypeClass = eSystem_FindClass(findModule, value);
3488                   break;
3489                case expression:
3490                {
3491                   Class expClass = eSystem_FindClass(_class.module, curParam.dataTypeString);
3492                   if(!expClass) expClass = eSystem_FindClass(_class.module.application, curParam.dataTypeString);
3493                   if(expClass)
3494                   {
3495                      //if(expClass.type ==
3496                      ((bool (*)(void *, void *, const char *))(void *)expClass._vTbl[__ecereVMethodID_class_OnGetDataFromString])(expClass, &argument.expression, value);
3497                   }
3498                   // Expression should be pre simplified here
3499                   else if(value[0] == '\"')
3500                   {
3501                      char * endQuote = value + strlen(value) - 1;
3502                      if(*endQuote != '\"') endQuote++;
3503                      *endQuote = '\0';
3504                      argument.expression.p = CopyString(value + 1);
3505                   }
3506                   else if(value[0] == '\'')
3507                   {
3508                      int nb;
3509                      unichar ch = UTF8GetChar(value + 1, &nb);
3510                      argument.expression.ui = ch;
3511                   }
3512                   else if(!strcmp(curParam.dataTypeString, "uint"))
3513                   {
3514                      argument.expression.ui = (uint)strtoul(value, null, 0);
3515                   }
3516                   else if(!strcmp(curParam.dataTypeString, "char"))
3517                   {
3518                      argument.expression.c = (char)strtol(value, null, 0);
3519                   }
3520                   else if(!strcmp(curParam.dataTypeString, "byte"))
3521                   {
3522                      argument.expression.uc = (unsigned char)strtoul(value, null, 0);
3523                   }
3524                   else if(!strcmp(curParam.dataTypeString, "short"))
3525                   {
3526                      argument.expression.s = (short)strtol(value, null, 0);
3527                   }
3528                   else if(!strcmp(curParam.dataTypeString, "uint16"))
3529                   {
3530                      argument.expression.us = (unsigned short)strtoul(value, null, 0);
3531                   }
3532                   else if(!strcmp(curParam.dataTypeString, "int64"))
3533                   {
3534                      argument.expression.i64 = _strtoi64(value, null, 0);
3535                   }
3536                   else if(!strcmp(curParam.dataTypeString, "uint64"))
3537                   {
3538                      argument.expression.ui64 = _strtoui64(value, null, 0);
3539                   }
3540                   else if(!strcmp(curParam.dataTypeString, "float"))
3541                   {
3542                      argument.expression.f = (float)strtod(value, null);
3543                   }
3544                   else if(!strcmp(curParam.dataTypeString, "double"))
3545                   {
3546                      argument.expression.d = strtod(value, null);
3547                   }
3548                   else // if(!strcmp(curParam.dataTypeString, "int"))
3549                   {
3550                      argument.expression.i = (int)strtol(value, null, 0);
3551                   }
3552                   break;
3553                }
3554                case identifier:
3555                   argument.memberString = CopyString(value);
3556                   break;
3557             }
3558             FreeTemplateArg(templatedClass, curParam, curParamID);
3559             templatedClass.templateArgs[curParamID] = argument;
3560          }
3561       }
3562    }
3563
3564    // TESTING THIS BEFORE...
3565    if(templatedClass == _class)
3566    {
3567       Class sClass = _class;
3568       int curParamID = 0;
3569       Class nextClass;
3570       ClassTemplateParameter param;
3571       for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3572       {
3573          if(nextClass.templateClass) nextClass = nextClass.templateClass;
3574          curParamID += nextClass.templateParams.count;
3575       }
3576
3577       for(param = sClass.templateParams.first; param; param = param.next)
3578       {
3579          if(!templatedClass.templateArgs[curParamID].dataTypeString)
3580          {
3581             templatedClass.templateArgs[curParamID] = param.defaultArg;
3582             CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3583             if(param.type == type && param.defaultArg.dataTypeString)
3584             {
3585                templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3586                if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3587                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3588                if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3589                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3590             }
3591          }
3592          curParamID++;
3593       }
3594    }
3595
3596    if(templatedClass.base && templatedClass.base.templateArgs && numParams - _class.templateParams.count)
3597    {
3598       int c = numParams - _class.templateParams.count-1;
3599
3600       for(sClass = _class.base; sClass; sClass = sClass.base)
3601       {
3602          ClassTemplateParameter param;
3603          if(sClass.templateClass) sClass = sClass.templateClass;
3604          for(param = sClass.templateParams.last; param; param = param.prev)
3605          {
3606             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3607             ClassTemplateArgument * baseArg = &templatedClass.base.templateArgs[c];
3608             if(!arg->dataTypeString)
3609             {
3610                *arg = templatedClass.base.templateArgs[c];
3611                CopyTemplateArg(param, arg);
3612                if(param.type == type)
3613                {
3614                   if(arg->dataTypeClass && strchr(arg->dataTypeString, '<') && arg->dataTypeClass.templateArgs)
3615                   {
3616                      Class expClass = arg->dataTypeClass;
3617                      Class cClass = null;
3618                      int paramCount = 0;
3619                      int lastParam = -1;
3620
3621                      char templateString[1024];
3622                      sprintf(templateString, "%s<", expClass.templateClass.fullName);
3623                      for(cClass = expClass; cClass; cClass = cClass.base)
3624                      {
3625                         int p = 0;
3626                         ClassTemplateParameter param;
3627                         for(param = cClass.templateParams.first; param; param = param.next)
3628                         {
3629                            int id = p;
3630                            Class sClass;
3631                            ClassTemplateArgument arg;
3632                            for(sClass = expClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
3633                            arg = expClass.templateArgs[id];
3634
3635                            {
3636                               ClassTemplateParameter cParam;
3637                               int p = numParams - _class.templateParams.count;
3638                               for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3639                               {
3640                                  if(cParam.type == type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
3641                                  {
3642                                     arg.dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3643                                     arg.dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3644                                     break;
3645                                  }
3646                               }
3647                            }
3648
3649                            {
3650                               char argument[256];
3651                               argument[0] = '\0';
3652                               switch(param.type)
3653                               {
3654                                  case expression:
3655                                  {
3656                                     // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
3657                                     /*
3658                                     char expString[1024];
3659                                     OldList * specs = MkList();
3660                                     Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
3661                                     Expression exp;
3662                                     char * string = PrintHexUInt64(arg.expression.ui64);
3663                                     exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
3664
3665                                     ProcessExpressionType(exp);
3666                                     ComputeExpression(exp);
3667                                     expString[0] = '\0';
3668                                     PrintExpression(exp, expString);
3669                                     strcat(argument, expString);
3670                                     //delete exp;
3671                                     FreeExpression(exp);
3672                                     */
3673                                     break;
3674                                  }
3675                                  case identifier:
3676                                  {
3677                                     strcat(argument, arg.member.name);
3678                                     break;
3679                                  }
3680                                  case TemplateParameterType::type:
3681                                  {
3682                                     if(arg.dataTypeString)
3683                                        strcat(argument, arg.dataTypeString);
3684                                     break;
3685                                  }
3686                               }
3687                               if(argument[0])
3688                               {
3689                                  if(paramCount) strcat(templateString, ", ");
3690                                  if(lastParam != p - 1)
3691                                  {
3692                                     strcat(templateString, param.name);
3693                                     strcat(templateString, " = ");
3694                                  }
3695                                  strcat(templateString, argument);
3696                                  paramCount++;
3697                                  lastParam = p;
3698                               }
3699                            }
3700                            p++;
3701                         }
3702                      }
3703                      {
3704                         int len = (int)strlen(templateString);
3705                         if(templateString[len-1] == '>') templateString[len++] = ' ';
3706                         templateString[len++] = '>';
3707                         templateString[len++] = '\0';
3708                      }
3709
3710                      FreeTemplateArg(templatedClass, param, c);
3711
3712                      arg->dataTypeString = CopyString(templateString);
3713                      arg->dataTypeClass = eSystem_FindClass(templatedClass.module, templateString);
3714                      if(!arg->dataTypeClass)
3715                         arg->dataTypeClass = eSystem_FindClass(templatedClass.module.application, templateString);
3716                   }
3717                   else
3718                   {
3719                      ClassTemplateParameter cParam;
3720                      int p = numParams - _class.templateParams.count;
3721                      for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3722                      {
3723                         // if(cParam.type == type && !strcmp(cParam.name, param.name))
3724                         if(cParam.type == type && baseArg->dataTypeString && !strcmp(cParam.name, baseArg->dataTypeString))
3725                         {
3726                            FreeTemplateArg(templatedClass, param, c);
3727
3728                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3729                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3730                            CopyTemplateArg(cParam, arg);
3731                            break;
3732                         }
3733                      }
3734                   }
3735                }
3736             }
3737             c--;
3738          }
3739       }
3740    }
3741
3742    {
3743       Class sClass;
3744       for(sClass = _class; sClass; sClass = sClass.base)
3745       {
3746          int curParamID = 0;
3747          Class nextClass;
3748          ClassTemplateParameter param;
3749          if(sClass.templateClass) sClass = sClass.templateClass;
3750
3751          for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3752          {
3753             if(nextClass.templateClass) nextClass = nextClass.templateClass;
3754             curParamID += nextClass.templateParams.count;
3755          }
3756
3757          for(param = sClass.templateParams.first; param; param = param.next)
3758          {
3759             if(!templatedClass.templateArgs[curParamID].dataTypeString)
3760             {
3761                templatedClass.templateArgs[curParamID] = param.defaultArg;
3762                CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3763                if(param.type == type && param.defaultArg.dataTypeString)
3764                {
3765                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3766                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3767                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3768                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3769                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3770                }
3771             }
3772             curParamID++;
3773          }
3774       }
3775    }
3776
3777    {
3778       int c = numParams - 1;
3779       for(sClass = _class; sClass; sClass = sClass.base)
3780       {
3781          ClassTemplateParameter param;
3782          if(sClass.templateClass) sClass = sClass.templateClass;
3783          for(param = sClass.templateParams.last; param; param = param.prev)
3784          {
3785             if(param.type == type)
3786             {
3787                ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3788                ClassTemplateParameter cParam;
3789                Class dClass;
3790                int p = numParams - 1;
3791                for(dClass = _class; dClass; dClass = dClass.base)
3792                {
3793                   if(dClass.templateClass) dClass = dClass.templateClass;
3794                   for(cParam = dClass.templateParams.last; cParam; cParam = cParam.prev, p--)
3795                   {
3796                      if(cParam.type == type && arg->dataTypeString && !strcmp(cParam.name, arg->dataTypeString))
3797                      {
3798                         if(templatedClass.templateArgs[p].dataTypeString && c != p)
3799                         {
3800                            FreeTemplateArg(templatedClass, param, c);
3801
3802                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3803                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3804                            CopyTemplateArg(cParam, arg);
3805                         }
3806                      }
3807                   }
3808                }
3809             }
3810             c--;
3811          }
3812       }
3813    }
3814
3815    {
3816       Class tClass;
3817       int c = numParams - 1;
3818       for(tClass = _class; tClass; tClass = tClass.base)
3819       {
3820          ClassTemplateParameter param;
3821          if(tClass.templateClass) tClass = tClass.templateClass;
3822          for(param = tClass.templateParams.last; param; param = param.prev)
3823          {
3824             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3825             if(param.type == identifier && arg->memberString)
3826             {
3827                Class memberClass = templatedClass;
3828                char * memberString = arg->memberString;
3829                char * colon = strstr(memberString, "::");
3830                char * memberName = memberString;
3831                if(colon) memberName = colon + 2;
3832                if(!colon)
3833                {
3834                   memberString = param.defaultArg.memberString;
3835                   colon = memberString ? strstr(memberString, "::") : null;
3836                }
3837
3838                if(colon)
3839                {
3840                   char className[1024];
3841                   Class sClass;
3842
3843                   memcpy(className, memberString, colon - memberString);
3844                   className[colon - memberString] = '\0';
3845
3846                   for(sClass = _class; sClass; sClass = sClass.base)
3847                   {
3848                      ClassTemplateParameter cParam;
3849                      Class nextClass;
3850                      int id = 0;
3851
3852                      if(sClass.templateClass) sClass = sClass.templateClass;
3853                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3854                      {
3855                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
3856                         id += nextClass.templateParams.count;
3857                      }
3858                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
3859                      {
3860                         if(cParam.type == type && !strcmp(cParam.name, className) && templatedClass.templateArgs[id].dataTypeString)
3861                         {
3862                            strcpy(className, templatedClass.templateArgs[id].dataTypeString);
3863                         }
3864                         id++;
3865                      }
3866                   }
3867                   memberClass = eSystem_FindClass(templatedClass.module, className);
3868                   // TESTING: Added this here...
3869                   if(!memberClass)
3870                      memberClass = eSystem_FindClass(findModule, className);
3871                   if(!memberClass)
3872                      memberClass = eSystem_FindClass(templatedClass.module.application, className);
3873                }
3874
3875                if(memberClass)
3876                {
3877                   switch(param.memberType)
3878                   {
3879                      case dataMember:
3880                         arg->member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
3881                         break;
3882                      case method:
3883                         arg->method = eClass_FindMethod(memberClass, memberName, memberClass.module);
3884                         break;
3885                      case prop:
3886                         arg->prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
3887                         break;
3888                   }
3889                }
3890             }
3891             c--;
3892          }
3893       }
3894    }
3895 }
3896
3897 /*static */bool DefaultFunction()
3898 {
3899    return true;
3900 }
3901
3902 public dllexport bool eClass_IsDerived(Class _class, Class from)
3903 {
3904    if(!_class && !from)
3905       return true;
3906
3907    if(_class && from && (_class.templateClass || from.templateClass))
3908    {
3909       if(eClass_IsDerived(_class.templateClass ? _class.templateClass : _class, from.templateClass ? from.templateClass : from))
3910       {
3911          if(!from.templateClass)
3912             return true;
3913          else if(!_class.templateClass && _class == from.templateClass)
3914             return false;
3915          else
3916          {
3917             Class sClass;
3918             for(sClass = from; sClass; sClass = sClass.base)
3919             {
3920                if(sClass.templateParams.first)
3921                {
3922                   ClassTemplateParameter param;
3923                   Class nextClass;
3924                   int p = 0;
3925                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;
3926                   for(param = sClass.templateParams.first; param; param = param.next, p++)
3927                   {
3928                      ClassTemplateArgument * arg = &_class.templateArgs[p];
3929                      ClassTemplateArgument * fArg = &from.templateArgs[p];
3930                      if(param.type == type)
3931                      {
3932                         if(arg->dataTypeString != fArg->dataTypeString && arg->dataTypeString && fArg->dataTypeString &&
3933                           strcmp(arg->dataTypeString, fArg->dataTypeString))
3934                            break;
3935                      }
3936                      else if(param.type == identifier)
3937                      {
3938                         if(arg->member != fArg->member)
3939                            break;
3940                      }
3941                      else if(param.type == expression)
3942                      {
3943                         if(arg->expression.ui64 != fArg->expression.ui64)
3944                            break;
3945                      }
3946                   }
3947                   if(param)
3948                      return false;
3949                }
3950             }
3951             return true;
3952          }
3953       }
3954    }
3955    else
3956    {
3957       for(; _class && from; _class = _class.base)
3958       {
3959          if(_class == from || _class.templateClass == from || ((_class.type == systemClass || (_class.type == normalClass && _class.isInstanceClass)) && from.name && !strcmp(_class.name, from.name)))
3960             return true;
3961       }
3962    }
3963    return false;
3964 }
3965
3966 static void FixDerivativeVirtualMethod(Class base, char * name, int vid, void * origFunction, char * type)
3967 {
3968    OldLink derivative;
3969    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
3970    {
3971       Class _class = derivative.data;
3972       Method method, next;
3973       void * function = origFunction;
3974
3975       _class.vTblSize++;
3976       _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
3977       memmove(_class._vTbl + vid + 1, _class._vTbl + vid, (_class.vTblSize - vid - 1) * sizeof(void *));
3978
3979       method = (Method) _class.methods.FindString(name);
3980       if(method)
3981       {
3982          if(method.function) function = method.function;
3983
3984          if(!method.symbol)
3985          {
3986             delete method.name;
3987             delete method.dataTypeString;
3988             _class.methods.Delete((BTNode)method);
3989          }
3990          else
3991          {
3992             delete method.dataTypeString;
3993             method.type = virtualMethod;
3994             method.dataTypeString = CopyString(type);
3995             method._class = base;
3996          }
3997       }
3998       for(method = (Method)_class.methods.first; method; method = next)
3999       {
4000          next = (Method)((BTNode)method).next;
4001          if(method.type == virtualMethod)
4002             method.vid++;
4003       }
4004       _class._vTbl[vid] = function;
4005
4006       {
4007          OldLink templateLink;
4008          for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4009          {
4010             Class template = templateLink.data;
4011             template._vTbl = _class._vTbl;
4012          }
4013       }
4014       if(_class.derivatives.first || _class.templatized.first)
4015          FixDerivativeVirtualMethod(_class, name, vid, function, type);
4016    }
4017    {
4018       OldLink templateLink;
4019       for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
4020       {
4021          Class template = templateLink.data;
4022          template._vTbl = base._vTbl;
4023          FixDerivativeVirtualMethod(template, name, vid, origFunction, type);
4024       }
4025    }
4026 }
4027
4028 public dllexport Method eClass_AddMethod(Class _class, char * name, char * type, void * function, AccessMode declMode)
4029 {
4030    if(_class && !_class.comRedefinition && name)
4031    {
4032       Class base;
4033       for(base = _class; base; base = base.base)
4034       {
4035          Method method = (Method)base.methods.FindString(name);
4036          if(method)
4037          {
4038             // If this overides a virtual method
4039             if(method.type == virtualMethod)
4040             {
4041                OldLink deriv;
4042                void * oldFunction = _class._vTbl[method.vid];
4043                if(method.vid >= _class.vTblSize)
4044                   printf("error: virtual methods overriding failure\n");
4045                else
4046                   _class._vTbl[method.vid] = function ? function : DefaultFunction;
4047                for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4048                {
4049                   Class derivClass = deriv.data;
4050                   if(derivClass._vTbl[method.vid] == oldFunction)
4051                      eClass_AddMethod(derivClass, name, type, function, declMode);
4052                }
4053                {
4054                   OldLink templateLink;
4055                   for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4056                   {
4057                      Class template = templateLink.data;
4058                      for(deriv = template.derivatives.first; deriv; deriv = deriv.next)
4059                      {
4060                         Class derivClass = deriv.data;
4061                         if(derivClass._vTbl[method.vid] == oldFunction)
4062                            eClass_AddMethod(derivClass, name, type, function, declMode);
4063                      }
4064                   }
4065                }
4066
4067             }
4068             else
4069             {
4070                if(base == _class)
4071                {
4072                   // printf("error: Redefinition of method %s in class %s\n", name, _class.name);
4073                   break;
4074                }
4075                base = null;
4076                break;
4077             }
4078             return method;
4079          }
4080       }
4081
4082       if(!base)
4083       {
4084          Method method
4085          {
4086             name = CopyString(name),
4087             function = function ? function : DefaultFunction;
4088             _class = _class;
4089             dataTypeString = CopyString(type);
4090             memberAccess = declMode;
4091          };
4092          _class.methods.Add((BTNode)method);
4093          return method;
4094       }
4095    }
4096    return null;
4097 }
4098
4099 public dllexport Method eClass_AddVirtualMethod(Class _class, char * name, char * type, void * function, AccessMode declMode)
4100 {
4101    if(_class && !_class.comRedefinition && name)
4102    {
4103       Class base;
4104       for(base = _class; base; base = base.base)
4105       {
4106          Method method = (Method)base.methods.FindString(name);
4107          if(method)
4108          {
4109             // If this overides a virtual method
4110             if(method.type == virtualMethod)
4111             {
4112                if(method.vid >= _class.vTblSize)
4113                   printf("error: virtual methods overriding failure\n");
4114                else
4115                   _class._vTbl[method.vid] = function ? function : DefaultFunction;
4116             }
4117             else
4118                base = null;
4119             return method;
4120          }
4121       }
4122
4123       if(!base)
4124       {
4125          Method method
4126          {
4127             name = CopyString(name);
4128             function = function ? function : DefaultFunction;
4129             type = virtualMethod;
4130             _class = _class;
4131             vid = _class.vTblSize++;
4132             dataTypeString = CopyString(type);
4133             memberAccess = declMode;
4134          };
4135          _class.methods.Add((BTNode)method);
4136          _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
4137          _class._vTbl[method.vid] = function ? function : DefaultFunction;
4138
4139          // TODO: Fix derived classes
4140          if(_class.derivatives.first || _class.templatized.first)
4141             FixDerivativeVirtualMethod(_class, name, method.vid, function ? function : (void *)DefaultFunction, type);
4142          return method;
4143       }
4144    }
4145    return null;
4146 }
4147
4148 static void FixDerivativeProperty(Class base, Property _property)
4149 {
4150    OldLink derivative;
4151    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
4152    {
4153       Class _class = derivative.data;
4154       Property prop;
4155       BTNamedLink link = (BTNamedLink)_class.prop.FindString(_property.name);
4156       if(link)
4157       {
4158          prop = link.data;
4159          if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
4160          {
4161             SelfWatcher watcher;
4162             for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
4163             {
4164                if(watcher._property == prop)
4165                   watcher._property = _property;
4166             }
4167             _property.selfWatchable = true;
4168
4169             delete prop.name;
4170             delete prop.dataTypeString;
4171             _class.membersAndProperties.Delete(prop);
4172             _class.prop.Delete((BTNode)link);
4173          }
4174       }
4175
4176       for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
4177          prop.id++;
4178       _class.memberID++;
4179       _class.startMemberID++;
4180
4181       FixDerivativeProperty(_class, _property);
4182    }
4183 }
4184
4185 public dllexport Property eClass_AddProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt, AccessMode declMode)
4186 {
4187    Property _property = null;
4188    if(_class)
4189    {
4190       BTNamedLink link = (BTNamedLink)_class.prop.FindString(name ? name : dataType);
4191       if(link)
4192          _property = link.data;
4193       if(!_property)
4194       {
4195          _property =
4196          {
4197             isProperty = true;
4198             name = CopyString(name ? name : dataType);
4199             id = (name && (setStmt || getStmt || dataType)) ? _class.memberID++ : 0;
4200             Set = setStmt;
4201             Get = getStmt;
4202             dataTypeString = CopyString(dataType);
4203             _class = _class;
4204             compiled = true;
4205             conversion = name ? false : true;
4206             memberAccess = declMode;
4207          };
4208          if(name)
4209             _class.membersAndProperties.Add(_property);
4210          else
4211             _class.conversions.Add(_property);
4212          _class.prop.Add((BTNode)BTNamedLink { name = _property.name, data = _property });
4213
4214          if(!_property.conversion)
4215          {
4216             FixDerivativeProperty(_class, _property);
4217          }
4218       }
4219    }
4220    return _property;
4221 }
4222
4223 static void SetDelayedCPValues(Class _class, ClassProperty _property)
4224 {
4225    OldLink deriv;
4226    NamedLink64 value, next;
4227
4228    for(value = _class.delayedCPValues.first; value; value = next)
4229    {
4230       next = value.next;
4231       if(!strcmp(value.name, _property.name))
4232       {
4233          // eClass_SetProperty(_class, _property.name, value.data);
4234          _property.Set(_class, value.data);
4235          _class.delayedCPValues.Delete(value);
4236       }
4237    }
4238
4239    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4240    {
4241       SetDelayedCPValues(deriv.data, _property);
4242    }
4243 }
4244
4245 public dllexport ClassProperty eClass_AddClassProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt)
4246 {
4247    if(name && !_class.classProperties.FindString(name))
4248    {
4249       ClassProperty _property
4250       {
4251          name = CopyString(name);
4252          Set = setStmt;
4253          Get = getStmt;
4254          dataTypeString = CopyString(dataType);
4255       };
4256       _class.classProperties.Add((BTNode)_property);
4257       SetDelayedCPValues(_class, _property);
4258       return _property;
4259    }
4260    return null;
4261 }
4262
4263 /*import "Time"
4264
4265 Time classFindTotalTime;
4266
4267 public dllexport void ResetClassFindTime()
4268 {
4269    classFindTotalTime = 0;
4270 }
4271
4272 public dllexport Time GetClassFindTime()
4273 {
4274    return classFindTotalTime;
4275 }
4276 */
4277 public dllexport ClassProperty eClass_FindClassProperty(Class _class, char * name)
4278 {
4279    //Time startTime = GetTime();
4280    ClassProperty _property = null;
4281    if(name && _class)
4282    {
4283       Class origClass = _class;
4284       for(; _class; _class = _class.base)
4285       {
4286          _property = (ClassProperty)_class.classProperties.FindString(name);
4287          if(_property)
4288             break;
4289       }
4290       // For enum class deriving off something else than enum to find enumSize...
4291       if(!_property && origClass.type == enumClass)
4292       {
4293          Class enumClass = eSystem_FindClass(origClass.module, "enum");
4294          _property = eClass_FindClassProperty(enumClass, name);
4295       }
4296    }
4297    /*if(!_property)
4298       eSystem_Logf("No such property (%s) for class %s\n", name, _class.name);*/
4299    //classFindTotalTime += GetTime() - startTime;
4300    return _property;
4301 }
4302
4303 public dllexport int64 eClass_GetProperty(Class _class, char * name)
4304 {
4305    ClassProperty _property = eClass_FindClassProperty(_class, name);
4306    if(_property && _property.Get && _property.Get != (void *)1)
4307    {
4308       int64 result = _property.Get(_class);
4309       return result;
4310    }
4311    return 0;
4312 }
4313
4314 public dllexport void eClass_SetProperty(Class _class, char * name, int64 value)
4315 {
4316    ClassProperty _property = eClass_FindClassProperty(_class, name);
4317    if(_property)
4318    {
4319       if(_property.Set)
4320          ((void(*)(void *, int64))_property.Set)(_class, value);
4321    }
4322    else
4323    {
4324       _class.delayedCPValues.Add(NamedLink64 { name = name, value });
4325    }
4326 }
4327
4328 public dllexport Method eClass_FindMethod(Class _class, char * name, Module module)
4329 {
4330    //Time startTime = GetTime();
4331    if(_class && name)
4332    {
4333       for(; _class; _class = _class.base)
4334       {
4335          Method method;
4336          if(_class.templateClass) _class = _class.templateClass;
4337          method = (Method)_class.methods.FindString(name);
4338          if(method && (method.memberAccess == publicAccess || _class.module == module || !method.dataTypeString))
4339          {
4340             if(!method.dataTypeString)
4341             {
4342                if(_class.module != module)
4343                {
4344                   if(method.memberAccess == publicAccess)
4345                      module = _class.module;
4346                   else
4347                   {
4348                      //classFindTotalTime += GetTime() - startTime;
4349                      return null;
4350                   }
4351                }
4352             }
4353             else
4354             {
4355                //classFindTotalTime += GetTime() - startTime;
4356                return method;
4357             }
4358          }
4359          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4360       }
4361    }
4362    //classFindTotalTime += GetTime() - startTime;
4363    return null;
4364 }
4365
4366 // Construct an instance
4367 static bool ConstructInstance(void * instance, Class _class, Class from)
4368 {
4369    if(_class.templateClass) _class = _class.templateClass;
4370    if(_class.base && from != _class.base)
4371    {
4372       if(!ConstructInstance(instance, _class.base, from))
4373          return false;
4374    }
4375    if(_class.Initialize)
4376    {
4377       void (* Initialize)(Module module) = (void *)_class.Initialize;
4378       _class.Initialize = null;
4379       Initialize(_class.module);
4380    }
4381    if(_class.Constructor)
4382    {
4383       if(!_class.Constructor(instance))
4384       {
4385          for(; _class; _class = _class.base)
4386          {
4387             if(_class.templateClass) _class = _class.templateClass;
4388             if(_class.Destructor)
4389                _class.Destructor(instance);
4390          }
4391          return false;
4392       }
4393    }
4394    (_class.templateClass ? _class.templateClass : _class).count++;
4395    return true;
4396 }
4397
4398 public dllexport void * eInstance_New(Class _class)
4399 {
4400    Instance instance = null;
4401    if(_class)
4402    {
4403       // instance = _malloc(_class.size);
4404 #ifdef MEMINFO
4405
4406 #undef malloc
4407    memMutex.Wait();
4408       //allocateClass = _class;
4409       allocateClass = malloc(strlen(_class.name)+1);
4410       allocateInternal = _class.module == __thisModule;
4411       strcpy(allocateClass, _class.name);
4412 #ifndef MEMINFO
4413 #define malloc _mymalloc
4414 #endif
4415
4416 #endif
4417       {
4418          int size = _class.structSize;
4419          int flags = _class.module.application.isGUIApp;
4420          bool inCompiler = (flags & 8) ? true : false;
4421          bool force32Bits = (flags & 4) ? true : false;
4422          if(force32Bits && inCompiler)
4423          {
4424             // Allocate 64 bit sizes for these when cross-compiling for 32 bit to allow loaded libraries to work properly
4425             if(!strcmp(_class.name, "Module"))
4426                size = 560;
4427             else if(_class.templateClass && !strcmp(_class.templateClass.name, "Map"))
4428                size = 40;
4429             else
4430                size *= 3;
4431          }
4432          instance = _calloc(1, size);
4433       }
4434 #ifdef MEMINFO
4435       allocateClass = null;
4436    memMutex.Release();
4437 #endif
4438       if(_class.type == normalClass)
4439       {
4440          instance._class = _class;
4441          // Copy the virtual table initially
4442          instance._vTbl = _class._vTbl;
4443       }
4444       if(!ConstructInstance(instance, _class, null))
4445       {
4446          _free(instance);
4447          instance = null;
4448       }
4449       /*if(_class.type == normalClass && _class.count > 1000)
4450          printf("%s: %d instances\n", _class.name, _class.count);*/
4451    }
4452    return instance;
4453 }
4454
4455 public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
4456 {
4457    if(_class && instancePtr && *instancePtr)
4458    {
4459       bool wasApp = false, wasGuiApp = false;
4460       Instance instance = (Instance)renew *instancePtr byte[_class.structSize];
4461       Class fromClass = instance._class;
4462       *instancePtr = instance;
4463       memset(((byte *)instance) + instance._class.structSize, 0, _class.structSize - instance._class.structSize);
4464       // Fix pointers to application
4465       if((wasApp = !strcmp(instance._class.name, "Application")) ||
4466          (wasGuiApp = !strcmp(instance._class.name, "GuiApplication")))
4467       {
4468          Module module;
4469          Application app = (Application) instance;
4470          BTNamedLink link;
4471          Class _class;
4472          NameSpace * nameSpace;
4473          for(module = app.allModules.first; module; module = module.next)
4474             module.application = app;
4475
4476          for(link = (BTNamedLink)app.privateNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4477          {
4478             OldLink t;
4479             ((Class)link.data).nameSpace = &app.privateNameSpace;
4480             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4481          }
4482          for(link = (BTNamedLink)app.publicNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4483          {
4484             OldLink t;
4485             ((Class)link.data).nameSpace = &app.publicNameSpace;
4486             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4487          }
4488
4489          for(link = (BTNamedLink)app.privateNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4490             ((DefinedExpression)link.data).nameSpace = &app.privateNameSpace;
4491          for(link = (BTNamedLink)app.publicNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4492             ((DefinedExpression)link.data).nameSpace = &app.publicNameSpace;
4493
4494          for(link = (BTNamedLink)app.privateNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4495             ((GlobalFunction)link.data).nameSpace = &app.privateNameSpace;
4496          for(link = (BTNamedLink)app.publicNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4497             ((GlobalFunction)link.data).nameSpace = &app.publicNameSpace;
4498
4499          for(nameSpace = (NameSpace *)app.privateNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4500             nameSpace->parent = &app.privateNameSpace;
4501          for(nameSpace = (NameSpace *)app.publicNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4502             nameSpace->parent = &app.publicNameSpace;
4503
4504          // --------------------------------------------------
4505          for(link = (BTNamedLink)app.systemNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4506          {
4507             OldLink t;
4508             ((Class)link.data).nameSpace = &app.systemNameSpace;
4509             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4510          }
4511          for(link = (BTNamedLink)app.systemNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4512             ((DefinedExpression)link.data).nameSpace = &app.systemNameSpace;
4513          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4514             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4515          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4516             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4517          for(nameSpace = (NameSpace *)app.systemNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4518             nameSpace->parent = &app.systemNameSpace;
4519          // --------------------------------------------------
4520
4521          for(_class = app.classes.first; _class; _class = _class.next)
4522          {
4523             OldLink templateLink;
4524             _class.module = (Module) app;
4525             for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4526             {
4527                Class template = templateLink.data;
4528                template.module = _class.module;
4529             }
4530          }
4531
4532          for(module = app.allModules.first; module; module = module.next)
4533          {
4534             for(_class = module.classes.first; _class; _class = _class.next)
4535             {
4536                OldLink templateLink;
4537                _class.module = module;
4538                for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4539                {
4540                   Class template = templateLink.data;
4541                   template.module = _class.module;
4542                }
4543             }
4544          }
4545
4546          app.application = app;
4547       }
4548
4549       {
4550          Class base;
4551          for(base = instance._class; base && base.type == normalClass && base.count; base = base.base)
4552             (base.templateClass ? base.templateClass : base).count--;
4553       }
4554
4555       instance._class = _class;
4556       // Copy the virtual table initially
4557       instance._vTbl = _class._vTbl;
4558
4559       // We don't want to reconstruct the portion already constructed...
4560       if(!ConstructInstance(instance, _class, fromClass))
4561       {
4562          _free(instance);
4563          *instancePtr = null;
4564       }
4565    }
4566 }
4567
4568 public dllexport void eInstance_Delete(Instance instance)
4569 {
4570 #ifdef MEMINFO
4571    bool checkMemory = false;
4572 #endif
4573    if(instance)
4574    {
4575       Class _class, base;
4576       bool ownVtbl;
4577
4578 #ifdef MEMINFO
4579 #if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
4580       if(instance._class == (void *)0xecececececececec)
4581 #else
4582       if(instance._class == (void *)0xecececec)
4583 #endif
4584          _free(instance);
4585 #endif
4586
4587       ownVtbl = instance._vTbl != instance._class._vTbl;
4588
4589       for(_class = instance._class; _class; _class = base)
4590       {
4591          if(_class.templateClass) _class = _class.templateClass;
4592          if(_class.destructionWatchOffset)
4593          {
4594             OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
4595             Watcher watcher, next;
4596
4597             for(watcher = watchers->first; watcher; watcher = next)
4598             {
4599                next = watcher.next;
4600                watchers->Remove(watcher);
4601                watcher.callback(watcher.object, instance);
4602                watchers->Delete(watcher);
4603             }
4604          }
4605
4606          /*// Loop through properties to delete all watchers? Might slow down destruction...
4607          {
4608             Property _property;
4609             for(_property = _class.membersAndProperties.first; _property; _property = _property.next)
4610             {
4611                if(_property.isProperty && _property.isWatchable)
4612                {
4613                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
4614                   Watcher watcher, next;
4615                   for(watcher = watchers->first; watcher; watcher = next)
4616                   {
4617                      next = watcher.next;
4618                      watchers->Delete(watcher);
4619                   }
4620                }
4621             }
4622          }*/
4623
4624
4625          base = _class.base;
4626          if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
4627          if(_class.Destructor)
4628             _class.Destructor(instance);
4629 #ifdef MEMINFO
4630          if(_class == class(Application))
4631             checkMemory = true;
4632 #endif
4633       }
4634
4635       for(_class = instance._class; _class; _class = base)
4636       {
4637          if(_class.templateClass) _class = _class.templateClass;
4638
4639          base = _class.base;
4640          (_class.templateClass ? _class.templateClass : _class).count--;
4641          if(_class.type == normalClass && !_class.count && !_class.module)
4642          {
4643 #ifdef MEMINFO
4644             // printf("Now Destructing class %s\n", _class.name);
4645 #endif
4646             eClass_Unregister(_class);
4647          }
4648       }
4649
4650       if(ownVtbl)
4651       {
4652          delete instance._vTbl;
4653       }
4654       //instance.prop.Free(null);
4655       _free(instance);
4656 #ifdef MEMINFO
4657       if(checkMemory) CheckMemory();
4658 #endif
4659    }
4660 }
4661
4662 public dllexport Property eClass_FindProperty(Class _class, char * name, Module module)
4663 {
4664    //Time startTime = GetTime();
4665    if(_class && name)
4666    {
4667       for(; _class; _class = _class.base)
4668       {
4669          BTNamedLink link;
4670          if(_class.templateClass) _class = _class.templateClass;
4671          link = (BTNamedLink)_class.prop.FindString(name);
4672          if(link)
4673          {
4674             Property _property = (Property)link.data;
4675             if(_property.memberAccess == publicAccess || _class.module == module || !_property.dataTypeString)
4676             {
4677                if(!_property.dataTypeString)
4678                {
4679                   if(_class.module != module)
4680                   {
4681                      if(_property.memberAccess == publicAccess)
4682                         module = _class.module;
4683                      else
4684                      {
4685                         //classFindTotalTime += GetTime() - startTime;
4686                         return null;
4687                      }
4688                   }
4689                }
4690                else
4691                {
4692                   //classFindTotalTime += GetTime() - startTime;
4693                   return _property;
4694                }
4695             }
4696          }
4697          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4698       }
4699    }
4700    //classFindTotalTime += GetTime() - startTime;
4701    return null;
4702 }
4703
4704 static DataMember FindDataMember(OldList list, BinaryTree alist, char * name, uint * offset, int * id, bool searchPrivate, DataMember * subMemberStack, int * subMemberStackPos)
4705 {
4706    BTNamedLink link;
4707    DataMember dataMember;
4708
4709    link = (BTNamedLink)alist.FindString(name);
4710    if(link)
4711    {
4712       dataMember = link.data;
4713       if(dataMember.type == normalMember && (dataMember.memberAccess == publicAccess || searchPrivate || !dataMember.dataTypeString))
4714       {
4715          if(offset)
4716             *offset += dataMember.offset;
4717          if(id) *id = dataMember.id;
4718          return dataMember;
4719       }
4720       return null;
4721    }
4722    for(dataMember = list.first; dataMember; dataMember = dataMember.next)
4723    {
4724       if(!dataMember.isProperty && (dataMember.memberAccess == publicAccess || searchPrivate) && !dataMember.name && (dataMember.type == unionMember || dataMember.type == structMember))
4725       {
4726          DataMember childMember;
4727          if(subMemberStackPos) subMemberStack[(*subMemberStackPos)++] = dataMember;
4728          childMember = FindDataMember(dataMember.members, dataMember.membersAlpha, name, offset, id, searchPrivate, subMemberStack, subMemberStackPos);
4729          if(childMember)
4730          {
4731             if(offset)
4732                *offset += dataMember.offset;
4733             if(id) *id += dataMember.id;
4734             return childMember;
4735          }
4736          if(subMemberStackPos) (*subMemberStackPos)--;
4737       }
4738    }
4739    return null;
4740 }
4741
4742 public dllexport DataMember eClass_FindDataMember(Class _class, char * name, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4743 {
4744    //Time startTime = GetTime();
4745    DataMember dataMember = null;
4746    if(subMemberStackPos) *subMemberStackPos = 0;
4747    if(_class && name)
4748    {
4749       for(; _class; _class = _class.base)
4750       {
4751          if(_class.templateClass) _class = _class.templateClass;
4752          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, null, _class.module == module, subMemberStack, subMemberStackPos);
4753          if(dataMember)
4754          {
4755             if(!dataMember.dataTypeString)
4756             {
4757                if(_class.module != module)
4758                {
4759                   if(dataMember.memberAccess == publicAccess)
4760                      module = _class.module;
4761                   else
4762                   {
4763                      //classFindTotalTime += GetTime() - startTime;
4764                      return null;
4765                   }
4766                }
4767                dataMember = null;
4768             }
4769             else
4770             {
4771                // HACK: Is this good enough? avoiding setting it when adding...
4772                dataMember._class = _class.templateClass ? _class.templateClass : _class;
4773                //classFindTotalTime += GetTime() - startTime;
4774                return dataMember;
4775             }
4776          }
4777          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4778       }
4779    }
4780    //classFindTotalTime += GetTime() - startTime;
4781    return dataMember;
4782 }
4783
4784 public dllexport DataMember eClass_FindDataMemberAndOffset(Class _class, char * name, uint * offset, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4785 {
4786    //Time startTime = GetTime();
4787    DataMember dataMember = null;
4788    if(subMemberStackPos) *subMemberStackPos = 0;
4789    if(offset) *offset = 0;
4790    if(_class)
4791    {
4792       for(; _class; _class = _class.base)
4793       {
4794          if(_class.templateClass) _class = _class.templateClass;
4795          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, offset, null, _class.module == module, subMemberStack, subMemberStackPos);
4796          if(dataMember)
4797          {
4798             if(!dataMember.dataTypeString)
4799             {
4800                if(_class.module != module)
4801                {
4802                   if(dataMember.memberAccess == publicAccess)
4803                      module = _class.module;
4804                   else
4805                   {
4806                      //classFindTotalTime += GetTime() - startTime;
4807                      return null;
4808                   }
4809                }
4810                dataMember = null;
4811             }
4812             else
4813             {
4814                // HACK: Is this good enouh? avoiding setting it when adding...
4815                dataMember._class = _class;
4816                //classFindTotalTime += GetTime() - startTime;
4817                return dataMember;
4818             }
4819          }
4820          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4821       }
4822    }
4823    //classFindTotalTime += GetTime() - startTime;
4824    return dataMember;
4825 }
4826
4827 public dllexport DataMember eClass_FindDataMemberAndId(Class _class, char * name, int * id, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4828 {
4829    //Time startTime = GetTime();
4830    DataMember dataMember = null;
4831    if(subMemberStackPos) *subMemberStackPos = 0;
4832    if(_class)
4833    {
4834       for(; _class; _class = _class.base)
4835       {
4836          if(_class.templateClass) _class = _class.templateClass;
4837          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, id, _class.module == module, subMemberStack, subMemberStackPos);  // TOCHECK: Why was this null? null, null);
4838          if(dataMember)
4839          {
4840             if(!dataMember.dataTypeString)
4841             {
4842                if(_class.module != module)
4843                {
4844                   if(dataMember.memberAccess == publicAccess)
4845                      module = _class.module;
4846                   else
4847                   {
4848                      //classFindTotalTime += GetTime() - startTime;
4849                      return null;
4850                   }
4851                }
4852                dataMember = null;
4853             }
4854             else
4855             {
4856                // HACK: Is this good enouh? avoiding setting it when adding...
4857                dataMember._class = _class;
4858                //classFindTotalTime += GetTime() - startTime;
4859                return dataMember;
4860             }
4861          }
4862          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4863       }
4864    }
4865    //classFindTotalTime += GetTime() - startTime;
4866    return dataMember;
4867 }
4868
4869 public dllexport void eClass_FindNextMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
4870 {
4871    // THIS CODE WILL FIND NEXT MEMBER... (PUBLIC MEMBERS ONLY)
4872    if(*curMember)
4873    {
4874       *curMember = (*curMember).next;
4875
4876       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
4877       {
4878          *curMember = subMemberStack[--(*subMemberStackPos)];
4879          *curMember = (*curMember).next;
4880       }
4881
4882       if(subMemberStackPos && *subMemberStackPos > 0)
4883       {
4884          while(*curMember && ((*curMember).memberAccess == privateAccess))
4885             *curMember = (*curMember).next;
4886       }
4887       else
4888          while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4889          {
4890             DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4891             if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4892             if(dataMember && dataMember.memberAccess != privateAccess)
4893             {
4894                *curMember = dataMember;
4895                break;
4896             }
4897             else
4898                *curMember = (*curMember).next;
4899          }
4900
4901       if(subMemberStackPos)
4902       {
4903          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4904          {
4905             subMemberStack[(*subMemberStackPos)++] = *curMember;
4906
4907             *curMember = (*curMember).members.first;
4908             while(*curMember && ((*curMember).memberAccess == privateAccess))
4909                *curMember = (*curMember).next;
4910          }
4911       }
4912    }
4913    while(!*curMember)
4914    {
4915       if(!*curMember)
4916       {
4917          if(subMemberStackPos && *subMemberStackPos)
4918          {
4919             *curMember = subMemberStack[--(*subMemberStackPos)];
4920             *curMember = (*curMember).next;
4921          }
4922          else
4923          {
4924             Class lastCurClass = *curClass;
4925
4926             if(*curClass == _class) break;     // REACHED THE END
4927
4928             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass && (*curClass).inheritanceAccess != privateAccess; *curClass = (*curClass).base);
4929             *curMember = (*curClass).membersAndProperties.first;
4930          }
4931
4932          if(subMemberStackPos && *subMemberStackPos > 0)
4933          {
4934             while(*curMember && ((*curMember).memberAccess == privateAccess))
4935                *curMember = (*curMember).next;
4936          }
4937          else
4938             while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4939             {
4940                DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4941                if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4942                if(dataMember && dataMember.memberAccess != privateAccess && dataMember.id >= 0) // Skip _vTbl, _refCount and _class in Instance
4943                {
4944                   *curMember = dataMember;
4945                   break;
4946                }
4947                else
4948                   *curMember = (*curMember).next;
4949             }
4950
4951          if(subMemberStackPos)
4952          {
4953             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4954             {
4955                subMemberStack[(*subMemberStackPos)++] = *curMember;
4956
4957                *curMember = (*curMember).members.first;
4958                while(*curMember && (*curMember).memberAccess == privateAccess)
4959                   *curMember = (*curMember).next;
4960             }
4961          }
4962       }
4963    }
4964 }
4965
4966 public dllexport void eInstance_SetMethod(Instance instance, char * name, void * function)     // YET TO BE DECIDED:   , Module module)
4967 {
4968    if(instance && name)
4969    {
4970       Class _class;
4971       for(_class = instance._class; _class; _class = _class.base)
4972       {
4973          Method method = (Method)_class.methods.FindString(name);
4974          if(method && method.type == virtualMethod)
4975          {
4976             if(instance._vTbl == instance._class._vTbl)
4977             {
4978                instance._vTbl = _malloc(sizeof(void *) * instance._class.vTblSize);
4979                memcpy(instance._vTbl, instance._class._vTbl,
4980                   sizeof(int(*)()) * instance._class.vTblSize);
4981             }
4982             instance._vTbl[method.vid] = function ? function : DefaultFunction;
4983          }
4984       }
4985    }
4986 }
4987
4988 public dllexport bool eInstance_IsDerived(Instance instance, Class from)
4989 {
4990    if(instance)
4991    {
4992       Class _class = instance._class;
4993       for(; _class; _class = _class.base)
4994       {
4995          if(_class == from)
4996             return true;
4997       }
4998    }
4999    return false;
5000 }
5001
5002 public dllexport void eInstance_IncRef(Instance instance)
5003 {
5004    if(instance)
5005       instance._refCount++;
5006 }
5007
5008 public dllexport void eInstance_DecRef(Instance instance)
5009 {
5010    if(instance)
5011    {
5012       instance._refCount--;
5013       //if(!instance._refCount)
5014       if(instance._refCount <= 0)
5015       {
5016          eInstance_Delete(instance);
5017       }
5018    }
5019 }
5020
5021 static void FixOffsets(Class _class)
5022 {
5023    OldLink deriv;
5024    _class.structSize += _class.base.structSize - _class.offset;
5025
5026    _class.offset = _class.base.structSize;
5027
5028    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
5029       FixOffsets(deriv.data);
5030 }
5031
5032 public dllexport void eClass_Resize(Class _class, int newSize)
5033 {
5034    OldLink deriv;
5035    _class.structSize = newSize;
5036    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
5037       FixOffsets(deriv.data);
5038 }
5039
5040 public dllexport DataMember eClass_AddDataMember(Class _class, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5041 {
5042    if(_class && name)
5043    {
5044       if(!_class.members.FindString(name))
5045       {
5046          DataMember dataMember;
5047
5048          if(alignment)
5049          {
5050             _class.structAlignment = Max(_class.structAlignment, alignment);
5051
5052             if(_class.memberOffset % alignment)
5053                _class.memberOffset += alignment - (_class.memberOffset % alignment);
5054          }
5055
5056          dataMember = DataMember {
5057             name = CopyString(name);
5058             dataTypeString = CopyString(type);
5059             id = _class.memberID++;
5060             _class = _class;
5061             offset = _class.memberOffset;
5062             memberOffset = size;
5063             memberAccess = declMode;
5064             membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5065          };
5066          _class.membersAndProperties.Add(dataMember);
5067          _class.memberOffset += size;
5068
5069          _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5070          return dataMember;
5071       }
5072    }
5073    return null;
5074 }
5075
5076 public dllexport DataMember eMember_AddDataMember(DataMember member, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5077 {
5078    if(name && !member.membersAlpha.FindString(name))
5079    {
5080       DataMember dataMember;
5081
5082       if(alignment)
5083       {
5084          member.structAlignment = Max(member.structAlignment, alignment);
5085
5086          if(member.memberOffset % alignment)
5087             member.memberOffset += alignment - (member.memberOffset % alignment);
5088       }
5089       dataMember = DataMember {
5090          name = CopyString(name);
5091          _class = member._class;
5092          dataTypeString = CopyString(type);
5093          id = member.memberID++;
5094          offset = (member.type == unionMember) ? 0 : member.memberOffset;
5095          memberAccess = declMode;
5096          membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5097       };
5098       member.members.Add(dataMember);
5099       if(member.type == unionMember)
5100       {
5101          if(size > member.memberOffset)
5102             member.memberOffset = size;
5103       }
5104       else
5105          member.memberOffset += size;
5106       member.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5107       return dataMember;
5108    }
5109    return null;
5110 }
5111
5112 public dllexport DataMember eMember_New(DataMemberType type, AccessMode declMode)
5113 {
5114    return DataMember { type = type, memberAccess = declMode, membersAlpha.CompareKey = (void *)BinaryTree::CompareString };
5115 }
5116
5117 static void SetMemberClass(DataMember member, Class _class)
5118 {
5119    DataMember dataMember;
5120    member._class = _class;
5121    for(dataMember = member.members.first; dataMember; dataMember = dataMember.next)
5122       SetMemberClass(dataMember, _class);
5123 }
5124
5125 public dllexport bool eMember_AddMember(DataMember addTo, DataMember dataMember)
5126 {
5127    if(dataMember.name && addTo.membersAlpha.FindString(dataMember.name))
5128    {
5129       DataMember_Free(dataMember);
5130       delete dataMember;
5131       return false;
5132    }
5133    addTo.members.Add(dataMember);
5134
5135    if(dataMember.name)
5136       addTo.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5137
5138    dataMember._class = addTo._class;
5139    // ? SetMemberClass(dataMember, addTo._class);
5140
5141    //dataMember.id = addTo.memberID++;
5142    dataMember.id = addTo.memberID;
5143    if(dataMember.type == unionMember)
5144       addTo.memberID += 1;
5145    else
5146       addTo.memberID += dataMember.memberID;
5147
5148    addTo.structAlignment = Max(addTo.structAlignment, dataMember.structAlignment);
5149    dataMember.offset = (addTo.type == unionMember) ? 0 : addTo.memberOffset;
5150    if(addTo.type == unionMember)
5151    {
5152       if(dataMember.memberOffset > addTo.memberOffset)
5153          addTo.memberOffset = dataMember.memberOffset;
5154    }
5155    else
5156       addTo.memberOffset += dataMember.memberOffset;
5157    return true;
5158 }
5159
5160 public dllexport bool eClass_AddMember(Class _class, DataMember dataMember)
5161 {
5162    if(!_class || _class.comRedefinition || (dataMember.name && _class.members.FindString(dataMember.name)))
5163    {
5164       DataMember_Free(dataMember);
5165       delete dataMember;
5166       return false;
5167    }
5168    _class.membersAndProperties.Add(dataMember);
5169
5170    if(dataMember.name)
5171       _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5172
5173    //dataMember._class = _class;
5174    SetMemberClass(dataMember, _class);
5175
5176    //dataMember.id = _class.memberID++;
5177    dataMember.id = _class.memberID;
5178
5179    _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
5180    if(dataMember.type == unionMember)
5181       _class.memberID += 1;
5182    else
5183       _class.memberID += dataMember.memberID;
5184    dataMember.offset = _class.memberOffset;
5185    _class.memberOffset += dataMember.memberOffset;
5186    return true;
5187 }
5188
5189 public dllexport BitMember eClass_AddBitMember(Class _class, char * name, char * type, int bitSize, int bitPos, AccessMode declMode)
5190 {
5191    if(_class && name && !_class.members.FindString(name))
5192    {
5193       uint64 mask = 0;
5194       int c;
5195       BitMember bitMember
5196       {
5197          name = CopyString(name);
5198          _class = _class;
5199          dataTypeString = CopyString(type);
5200          id = _class.memberID++;
5201          memberAccess = declMode;
5202       };
5203       _class.membersAndProperties.Add(bitMember);
5204       if(bitSize)
5205       {
5206          bitMember.pos = (bitPos == -1) ? _class.memberOffset : bitPos;
5207          bitMember.size = bitSize;
5208          _class.memberOffset = bitMember.pos + bitMember.size;
5209          for(c = 0; c<bitSize; c++)
5210          {
5211             if(c)
5212                mask <<= 1;
5213             mask |= 1;
5214          }
5215          bitMember.mask = mask << bitMember.pos;
5216       }
5217
5218      _class.members.Add((BTNode)BTNamedLink { name = bitMember.name, data = bitMember });
5219       return bitMember;
5220    }
5221    return null;
5222 }
5223
5224 static Module Module_Load(Module fromModule, char * name, AccessMode importAccess, bool ensureCOM)
5225 {
5226    bool (stdcall * Load)(Module module) = null;
5227    bool (stdcall * Unload)(Module module) = null;
5228    Module module;
5229
5230    for(module = fromModule.application.allModules.first; module; module = module.next)
5231    {
5232       if(!strcmp(module.name, name))
5233          break;
5234    }
5235    if(ensureCOM && (!strcmp(name, "ecereCOM") || !strcmp(name, "ecere")))
5236    {
5237       for(module = fromModule.application.allModules.first; module; module = module.next)
5238       {
5239          if(!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM"))
5240             break;
5241       }
5242    }
5243    if(!module)
5244    {
5245       void * library = null;
5246
5247       if(ensureCOM && !strcmp(name, "ecereCOM"))
5248       {
5249          Load = COM_LOAD_FUNCTION;
5250          Unload = COM_UNLOAD_FUNCTION;
5251       }
5252       else
5253       {
5254          char * libLocation = null;
5255 #if defined(__ANDROID__)
5256          libLocation = AndroidInterface_GetLibLocation();
5257 #endif
5258          library = Instance_Module_Load(libLocation, name, &Load, &Unload);
5259       }
5260       if(Load)
5261       {
5262          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5263          module.application = fromModule.application;
5264          module.library = library;
5265          {
5266             char moduleName[MAX_FILENAME];
5267             char ext[MAX_EXTENSION];
5268             GetLastDirectory(name, moduleName);
5269             GetExtension(moduleName, ext);
5270             StripExtension(moduleName);
5271             if((!strcmpi(ext, "dylib") || !strcmpi(ext, "so")) && strstr(moduleName, "lib") == moduleName)
5272             {
5273                int len = (int)strlen(moduleName) - 3;
5274                memmove(moduleName, moduleName + 3, len);
5275                moduleName[len] = 0;
5276             }
5277             module.name = CopyString(moduleName);
5278          }
5279          module.Unload = Unload;
5280          module.origImportType = normalImport;
5281
5282          if(!Load(module))
5283          {
5284             eInstance_Delete((Instance)module);
5285             module = null;
5286          }
5287       }
5288       fromModule.application.allModules.Add(module);
5289    }
5290    if(ensureCOM && !strcmp(name, "ecere") && module)
5291    {
5292       name = !strcmp(module.name, "ecereCOM") ? "ecere" : "ecereCOM";
5293       if((!Load && !strcmp(module.name, "ecereCOM")) ||
5294          (Load && (!__thisModule || !__thisModule.name || !strcmp(__thisModule.name, "ecereCOM")) && Load != COM_LOAD_FUNCTION))
5295       {
5296          Module module;
5297          for(module = fromModule.application.allModules.first; module; module = module.next)
5298          {
5299             if(!strcmp(module.name, name))
5300                break;
5301          }
5302          if(!module)
5303          {
5304             Load = COM_LOAD_FUNCTION;
5305             Unload = COM_UNLOAD_FUNCTION;
5306
5307             module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5308             module.application = fromModule.application;
5309             module.library = null;
5310             module.name = CopyString(name);
5311             module.Unload = Unload;
5312
5313             if(!Load(module))
5314             {
5315                eInstance_Delete((Instance)module);
5316                module = null;
5317             }
5318
5319             fromModule.application.allModules.Add(module);
5320          }
5321          if(module)
5322          {
5323             if(fromModule)
5324             {
5325                fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5326             }
5327             incref module;
5328          }
5329       }
5330    }
5331    if(module)
5332    {
5333       if(fromModule)
5334       {
5335          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5336       }
5337       incref module;
5338    }
5339 #if defined(_DEBUG)
5340    InternalModuleLoadBreakpoint();
5341 #endif
5342    return module;
5343 }
5344
5345 public dllexport Module eModule_Load(Module fromModule, char * name, AccessMode importAccess)
5346 {
5347    return Module_Load(fromModule, name, importAccess, true);
5348 }
5349
5350 public dllexport Module eModule_LoadStrict(Module fromModule, char * name, AccessMode importAccess)
5351 {
5352    return Module_Load(fromModule, name, importAccess, false);
5353 }
5354
5355 public dllexport Module eModule_LoadStatic(Module fromModule, char * name, AccessMode importAccess, bool (* Load)(Module module), bool (* Unload)(Module module))
5356 {
5357    Module module;
5358    for(module = fromModule.application.allModules.first; module; module = module.next)
5359    {
5360       if(!strcmp(module.name, name))
5361          break;
5362    }
5363    if(!module)
5364    {
5365       if(Load)
5366       {
5367          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5368          module.application = fromModule.application;
5369          module.name = CopyString(name);
5370          module.origImportType = staticImport;
5371          module.Unload = (void *)Unload;
5372          if(!Load(module))
5373          {
5374             eInstance_Delete((Instance)module);
5375             module = null;
5376          }
5377       }
5378       fromModule.application.allModules.Add(module);
5379    }
5380    if(module)
5381    {
5382       if(fromModule)
5383       {
5384          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5385       }
5386       incref module;
5387    }
5388    return module;
5389 }
5390
5391 public dllexport void eModule_Unload(Module fromModule, Module module)
5392 {
5393    OldLink m;
5394    for(m = fromModule.modules.first; m; m = m.next)
5395    {
5396       if(m.data == module)
5397          break;
5398    }
5399    if(m)
5400    {
5401       fromModule.modules.Delete(m);
5402       delete module;
5403    }
5404 }
5405
5406 public dllexport void eEnum_AddFixedValue(Class _class, char * string, int value)
5407 {
5408    if(_class && _class.type == enumClass)
5409    {
5410       EnumClassData data = (EnumClassData)_class.data;
5411       NamedLink item;
5412
5413       for(item = data.values.first; item; item = item.next)
5414          if(!strcmp(item.name, string))
5415             break;
5416       if(!item)
5417       {
5418          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5419          if(value > data.largest)
5420             data.largest = value;
5421       }
5422    }
5423 }
5424
5425 public dllexport int eEnum_AddValue(Class _class, char * string)
5426 {
5427    if(_class && _class.type == enumClass)
5428    {
5429       EnumClassData data = (EnumClassData)_class.data;
5430       int value = ((int) data.largest) + 1;
5431       NamedLink item;
5432       for(item = data.values.first; item; item = item.next)
5433          if(!strcmp(item.name, string))
5434             break;
5435       if(!item)
5436       {
5437          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5438          if(value > data.largest)
5439             data.largest = value;
5440          return value;
5441       }
5442    }
5443    return -1;
5444 }
5445
5446 static void NameSpace_Free(NameSpace parentNameSpace)
5447 {
5448    NameSpace * nameSpace;
5449    delete parentNameSpace.name;
5450
5451    while((nameSpace = (NameSpace *)parentNameSpace.nameSpaces.first))
5452    {
5453       NameSpace_Free(nameSpace);
5454       parentNameSpace.nameSpaces.Delete((BTNode)nameSpace);
5455    }
5456 }
5457
5458 static void Application_Destructor(Application app)
5459 {
5460    if(app.parsedCommand)
5461    {
5462       delete app.argv;
5463       delete app.parsedCommand;
5464    }
5465 }
5466
5467 static bool Module_Constructor(Module module)
5468 {
5469    module.privateNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5470    module.privateNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5471    module.privateNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5472    module.privateNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5473
5474    module.publicNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5475    module.publicNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5476    module.publicNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5477    module.publicNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5478    return true;
5479 }
5480
5481 static void Module_Destructor(Module module)
5482 {
5483    Class _class;
5484    DefinedExpression def;
5485    GlobalFunction function;
5486    Module m;
5487    SubModule handle;
5488
5489    // printf("Destructing module %s\n", module.name);
5490
5491    // Take out references from all modules
5492    for(m = module.application.allModules.first; m; m = m.next)
5493    {
5494       SubModule next;
5495       for(handle = m.modules.first; handle; handle = next)
5496       {
5497          next = handle.next;
5498          if(handle.module == module)
5499             m.modules.Delete(handle);
5500       }
5501    }
5502
5503    if(module.Unload)
5504    {
5505       if(module.origImportType == staticImport)
5506       {
5507          bool (* Unload)(Module module) = (void *)module.Unload;
5508          Unload(module);
5509       }
5510       else
5511       {
5512          bool (stdcall * Unload)(Module module) = (void *)module.Unload;
5513          Unload(module);
5514       }
5515    }
5516
5517    // Unload dependencies
5518    {
5519       Module ourWorld = class(Class).module;
5520       void * ourHandle = null;
5521       while((handle = module.modules.last))  // STARTING WITH LAST SO THAT ecereCOM IS UNLOADED LAST...
5522       {
5523          Module depModule = handle.module;
5524          if(depModule == ourWorld)
5525          {
5526             module.modules.Remove(handle);
5527             ourHandle = handle;
5528          }
5529          else
5530          {
5531             module.modules.Delete(handle);
5532             delete depModule;
5533          }
5534       }
5535       if(ourHandle)
5536       {
5537          delete ourHandle;
5538          delete ourWorld;
5539       }
5540    }
5541
5542    // Unload classes
5543    for(;(_class = module.classes.first);)
5544    {
5545       if(_class.nameSpace)
5546       {
5547          BTNamedLink classLink = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
5548          OldLink t;
5549          for(t = _class.templatized.first; t; t = t.next)
5550          {
5551             Class template = t.data;
5552             BTNamedLink link;
5553             link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
5554
5555             template.nameSpace->classes.Delete((BTNode)link);
5556             template.nameSpace = null;
5557          }
5558          _class.nameSpace->classes.Delete((BTNode)classLink);
5559          _class.nameSpace = null;
5560       }
5561       _class.module = null;
5562       module.classes.Remove(_class);
5563       if(_class.count <= 0 || _class.type != normalClass || _class.isInstanceClass)
5564          eClass_Unregister(_class);
5565       else
5566       {
5567 #ifdef MEMINFO
5568          // printf("Delayed destruction of class %s\n", _class.name);
5569 #endif
5570       }
5571    }
5572
5573    // Unload defines
5574    for(;(def = module.defines.first);)
5575    {
5576       if(def.nameSpace)
5577       {
5578          BTNamedLink defLink;
5579          for(defLink = (BTNamedLink)def.nameSpace->defines.first; defLink; defLink = (BTNamedLink)((BTNode)defLink).next)
5580             if(defLink.data == def)
5581             {
5582                def.nameSpace->defines.Delete((BTNode)defLink);
5583                break;
5584             }
5585       }
5586       delete def.name;
5587       delete def.value;
5588       module.defines.Delete(def);
5589    }
5590
5591    // Unload functions
5592    for(;(function = module.functions.first);)
5593    {
5594       if(function.nameSpace)
5595       {
5596          BTNamedLink functionLink;
5597          for(functionLink = (BTNamedLink)function.nameSpace->functions.first; functionLink; functionLink = (BTNamedLink)((BTNode)functionLink).next)
5598             if(functionLink.data == function)
5599             {
5600                function.nameSpace->functions.Delete((BTNode)functionLink);
5601                break;
5602             }
5603       }
5604       delete function.name;
5605       delete function.dataTypeString;
5606       module.functions.Delete(function);
5607    }
5608
5609    delete module.name;
5610
5611    NameSpace_Free(module.privateNameSpace);
5612    NameSpace_Free(module.publicNameSpace);
5613
5614    if(module != module.application)
5615       module.application.allModules.Remove(module);
5616    else
5617       NameSpace_Free(module.application.systemNameSpace);
5618
5619 #ifndef MEMINFO
5620    Instance_Module_Free(module.library);
5621 #endif
5622 }
5623
5624 static int64 GetEnumSize(Class _class)
5625 {
5626    EnumClassData data = (EnumClassData)_class.data;
5627    return data.largest+1;
5628 }
5629
5630 #if defined(__GNUC__)
5631 #define strcmpi strcasecmp
5632 #define strnicmp strncasecmp
5633 #endif
5634
5635 #if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__))
5636 #undef strlwr
5637 #undef strupr
5638 default dllexport char * strlwr(char *string)
5639 {
5640    int c;
5641    for(c=0; string[c]; c++)
5642       if(string[c]>='A' && string[c]<='Z')
5643          string[c]+='a'-'A';
5644    return string;
5645 }
5646 default dllexport char * strupr(char *string)
5647 {
5648    int c;
5649    for(c=0; string[c]; c++)
5650       if(string[c]>='a' && string[c]<='z')
5651          string[c]-='a'-'A';
5652    return string;
5653 }
5654 #endif
5655
5656 public dllexport DefinedExpression eSystem_RegisterDefine(char * name, char * value, Module module, AccessMode declMode)
5657 {
5658    NameSpace * nameSpace = null;
5659
5660    int start = 0, c;
5661
5662    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5663    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5664
5665    if(declMode != staticAccess)
5666    {
5667       for(c = 0; name[c]; c++)
5668       {
5669          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5670          {
5671             NameSpace * newSpace;
5672
5673             char * spaceName = _malloc(c - start + 1);
5674             strncpy(spaceName, name + start, c - start);
5675             spaceName[c-start] = '\0';
5676
5677             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5678             if(!newSpace)
5679             {
5680                newSpace = new0 NameSpace[1];
5681                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5682                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5683                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5684                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5685                newSpace->name = spaceName;
5686                newSpace->parent = nameSpace;
5687                nameSpace->nameSpaces.Add((BTNode)newSpace);
5688             }
5689             else
5690                delete spaceName;
5691             nameSpace = newSpace;
5692             if(name[c] == ':') c++;
5693             start = c+1;
5694          }
5695       }
5696    }
5697    else
5698       c = (int)strlen(name);
5699
5700    if(c - start && !nameSpace->defines.FindString(name + start))
5701    {
5702       DefinedExpression def
5703       {
5704          name = CopyString(name);
5705          nameSpace = nameSpace;
5706          value = CopyString(value);
5707       };
5708       nameSpace->defines.Add((BTNode)BTNamedLink { name = def.name + start, data = def });
5709       // Reference the definition in the module
5710       module.defines.Add(def);
5711       return def;
5712    }
5713    return null;
5714 }
5715
5716 public dllexport GlobalFunction eSystem_RegisterFunction(char * name, char * type, void * func, Module module, AccessMode declMode)
5717 {
5718    NameSpace * nameSpace = null;
5719    int start = 0, c;
5720
5721    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5722    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5723
5724    if(declMode != staticAccess)
5725    {
5726       for(c = 0; name[c]; c++)
5727       {
5728          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5729          {
5730             NameSpace * newSpace;
5731
5732             char * spaceName = _malloc(c - start + 1);
5733             strncpy(spaceName, name + start, c - start);
5734             spaceName[c-start] = '\0';
5735
5736             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5737             if(!newSpace)
5738             {
5739                newSpace = new0 NameSpace[1];
5740                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5741                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5742                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5743                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5744                newSpace->name = spaceName;
5745                newSpace->parent = nameSpace;
5746                nameSpace->nameSpaces.Add((BTNode)newSpace);
5747             }
5748             else
5749                delete spaceName;
5750             nameSpace = newSpace;
5751             if(name[c] == ':') c++;
5752             start = c+1;
5753          }
5754       }
5755    }
5756    else
5757       c = (int)strlen(name);
5758
5759    if(c - start && !nameSpace->functions.FindString(name + start))
5760    {
5761       GlobalFunction function
5762       {
5763          name = CopyString(name);
5764          nameSpace = nameSpace;
5765          dataTypeString = CopyString(type);
5766          function = func;
5767          module = module;
5768       };
5769       nameSpace->functions.Add((BTNode)BTNamedLink { name = function.name + start, data = function });
5770       // Reference the definition in the module
5771       module.functions.Add(function);
5772       return function;
5773    }
5774    return null;
5775 }
5776
5777 public dllexport DefinedExpression eSystem_FindDefine(Module module, char * name)
5778 {
5779    if(name && module)
5780    {
5781       BTNamedLink link;
5782       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->defines);
5783       if(link) return link.data;
5784
5785       link = SearchModule(module, name, &((NameSpace *)0)->defines, true);
5786       if(link) return link.data;
5787    }
5788    return null;
5789 }
5790
5791 public dllexport GlobalFunction eSystem_FindFunction(Module module, char * name)
5792 {
5793    if(name && module)
5794    {
5795       BTNamedLink link;
5796       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->functions);
5797       if(link) return link.data;
5798
5799       link = SearchModule(module, name, &((NameSpace *)0)->functions, true);
5800       if(link) return link.data;
5801    }
5802    return null;
5803 }
5804
5805 public dllexport void * eSystem_Renew(void * memory, unsigned int size)
5806 {
5807    return _realloc(memory, size);
5808 }
5809
5810 public dllexport void * eSystem_Renew0(void * memory, unsigned int size)
5811 {
5812    return _crealloc(memory, size);
5813 }
5814
5815 public dllexport void * eSystem_New(unsigned int size)
5816 {
5817 /*#ifdef _DEBUG
5818    void * pointer = _malloc(size);
5819    memset(pointer, 0xec, size);
5820    return pointer;
5821 #else*/
5822    return _malloc(size);
5823 //#endif
5824 }
5825
5826 public dllexport void * eSystem_New0(unsigned int size)
5827 {
5828    return _calloc(1,size);
5829 }
5830
5831 public dllexport void eSystem_Delete(void * memory)
5832 {
5833    if(memory)
5834       _free(memory);
5835 }
5836
5837 // Properties
5838 public dllexport void eInstance_FireSelfWatchers(Instance instance, Property _property)
5839 {
5840    if(instance && _property && _property.selfWatchable)
5841    {
5842       Class _class;
5843       for(_class = instance._class; _class; _class = _class.base)
5844       {
5845          SelfWatcher selfWatcher, next;
5846          for(selfWatcher = _class.selfWatchers.first; selfWatcher; selfWatcher = next)
5847          {
5848             next = selfWatcher.next;
5849             if(selfWatcher._property == _property)
5850                selfWatcher.callback(instance);
5851          }
5852       }
5853    }
5854 }
5855
5856 public dllexport void eInstance_FireWatchers(Instance instance, Property _property)
5857 {
5858    if(instance && _property && _property.isWatchable)
5859    {
5860       Module module = instance._class ? instance._class.module : null;
5861       Application application = module ? module.application : null;
5862       int flags = application ? application.isGUIApp : 0;
5863       bool inCompiler = (flags & 8) ? true : false;
5864       bool force32Bits = (flags & 4) ? true : false;
5865       if(!force32Bits || !inCompiler)
5866       {
5867          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5868          Watcher watcher, next;
5869
5870          for(watcher = watchers->first; watcher; watcher = next)
5871          {
5872             next = watcher.next;
5873             watcher.callback(watcher.object, instance);
5874          }
5875       }
5876    }
5877 }
5878
5879 public dllexport void eProperty_Watchable(Property _property)
5880 {
5881    if(!_property.isWatchable)
5882    {
5883       Class _class = _property._class;
5884       if(!_class.computeSize)
5885       {
5886          _property.watcherOffset = _class.structSize;
5887          _class.structSize += sizeof(OldList);
5888
5889          // highly inefficient
5890          FixDerivativesBase(_class, _class);
5891       }
5892       _property.isWatchable = true;
5893    }
5894 }
5895
5896 public dllexport void eClass_DestructionWatchable(Class _class)
5897 {
5898    if(!_class.destructionWatchOffset)
5899    {
5900       _class.destructionWatchOffset = _class.structSize;
5901       _class.structSize += sizeof(OldList);
5902       // highly inefficient
5903       FixDerivativesBase(_class, _class);
5904    }
5905 }
5906
5907 public dllexport void eProperty_SelfWatch(Class _class, char * name, void (*callback)(void *))
5908 {
5909    if(_class)
5910    {
5911       Property _property = eClass_FindProperty(_class, name, _class.module);
5912
5913       if(!_property)
5914          _property = eClass_AddProperty(_class, name, null, null, null, baseSystemAccess /*privateAccess*/);
5915       _class.selfWatchers.Add(SelfWatcher { _property = _property, callback = callback });
5916       _property.selfWatchable = true;
5917    }
5918 }
5919
5920 public dllexport void eInstance_Watch(void * instance, Property _property, void * object, void (*callback)(void *, void *))
5921 {
5922    if(_property.isWatchable)
5923    {
5924       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5925       watchers->Add(Watcher { callback = callback, object = object });
5926    }
5927 }
5928
5929 public dllexport void eInstance_WatchDestruction(Instance instance, Instance object, void (*callback)(Instance, Instance))
5930 {
5931    OldList * watchers = (OldList *)((byte *)instance + instance._class.destructionWatchOffset);
5932    watchers->Add(Watcher { callback = callback, object = object });
5933 }
5934
5935 public dllexport void eInstance_StopWatching(Instance instance, Property _property, Instance object)
5936 {
5937    if(instance && (!_property || _property.isWatchable))
5938    {
5939       if(_property)
5940       {
5941          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5942          Watcher watcher;
5943          for(watcher = watchers->first; watcher; watcher = watcher.next)
5944             if(watcher.object == object)
5945             {
5946                watchers->Delete(watcher);
5947                break;
5948             }
5949       }
5950       else
5951       {
5952          // Stop watching all properties as well as destruction
5953          Class _class, base;
5954          for(_class = instance._class; _class; _class = base)
5955          {
5956             if(_class.destructionWatchOffset)
5957             {
5958                OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
5959                Watcher watcher;
5960
5961                for(watcher = watchers->first; watcher; watcher = watcher.next)
5962                {
5963                   watchers->Delete(watcher);
5964                   break;
5965                }
5966             }
5967             for(_property = (Property)_class.membersAndProperties.first; _property; _property = _property.next)
5968             {
5969                if(_property.isProperty && _property.isWatchable)
5970                {
5971                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5972                   Watcher watcher;
5973                   for(watcher = watchers->first; watcher; watcher = watcher.next)
5974                      if(watcher.object == object)
5975                      {
5976                         watchers->Delete(watcher);
5977                         break;
5978                      }
5979                }
5980             }
5981             base = _class.base;
5982             if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
5983          }
5984       }
5985    }
5986 }
5987
5988 public dllexport subclass(ClassDesignerBase) eClass_GetDesigner(Class _class)
5989 {
5990    for(;_class;_class = _class.base)
5991    {
5992       if(_class.designerClass)
5993          return (subclass(ClassDesignerBase))eSystem_FindClass(_class.module, _class.designerClass);
5994    }
5995    return null;
5996 }
5997
5998
5999 public dllexport subclass(ClassDesignerBase) eInstance_GetDesigner(Instance instance)
6000 {
6001    if(instance)
6002       return eClass_GetDesigner(instance._class);
6003    return null;
6004 }
6005
6006 public bool LocateModule(char * name, char * fileName)
6007 {
6008    return Instance_LocateModule(name, fileName);
6009 }
6010
6011 static void LoadCOM(Module module)
6012 {
6013    bool force64Bits = (module.application.isGUIApp & 2) ? true : false;
6014    bool force32Bits = (module.application.isGUIApp & 4) ? true : false;
6015    bool inCompiler = (module.application.isGUIApp & 8) ? true : false;
6016    int pointerSize = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
6017    Class applicationClass;
6018    Class enumClass, structClass, boolClass;
6019    Class moduleClass;
6020
6021    // Create Base Class
6022    Class baseClass = eSystem_RegisterClass(normalClass, "class", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6023    baseClass.type = systemClass;
6024    baseClass.memberOffset = 0;
6025    baseClass.offset = 0;
6026    baseClass.structSize = 0;
6027    baseClass.typeSize = 0;
6028
6029    {
6030       Class instanceClass = eSystem_RegisterClass(normalClass, "ecere::com::Instance", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6031       instanceClass.type = normalClass;
6032       instanceClass.isInstanceClass = true;
6033       instanceClass.fixed = true;
6034       instanceClass.memberOffset = 0;
6035       instanceClass.offset = 0;
6036
6037       instanceClass.memberID = -3;
6038       instanceClass.startMemberID = -3;
6039
6040       eClass_AddDataMember(instanceClass, "_vTbl", "int (**)()", pointerSize, pointerSize, publicAccess);
6041       eClass_AddDataMember(instanceClass, "_class", "ecere::com::Class", pointerSize, pointerSize, publicAccess);
6042       eClass_AddDataMember(instanceClass, "_refCount", "int", sizeof(int), sizeof(int), publicAccess);
6043    }
6044
6045    InitializeDataTypes1(module);
6046
6047    // Create Enum class
6048    enumClass = eSystem_RegisterClass(normalClass, "enum", null, 0, force64Bits ? 40 : sizeof(class EnumClassData), null, null, module, baseSystemAccess, publicAccess);
6049    eClass_AddClassProperty(enumClass, "enumSize", "int", null, GetEnumSize).constant = true;
6050    enumClass.type = systemClass;
6051
6052    delete enumClass.dataTypeString;
6053    enumClass.dataTypeString = CopyString(/*"unsigned int"*/"int");
6054
6055    // Create Struct (simple) class
6056    //structClass = eSystem_RegisterClass(structClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6057    structClass = eSystem_RegisterClass(normalClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6058    structClass.type = systemClass;
6059    structClass.memberOffset = 0;
6060    structClass.offset = 0;
6061    structClass.structSize = 0;
6062    structClass.typeSize = 0;
6063
6064    //eClass_AddMethod(enumClass, "AddValue", "int()", eEnum_AddValue);
6065    //eClass_AddMethod(enumClass, "AddFixedValue", "void()", eEnum_AddFixedValue);
6066
6067    InitializeDataTypes(module);
6068
6069    // Create bool class
6070    boolClass = eSystem_RegisterClass(ClassType::enumClass, "bool", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
6071    eEnum_AddFixedValue(boolClass, "true",  bool::true);
6072    eEnum_AddFixedValue(boolClass, "false", bool::false);
6073
6074    // Create Module class
6075    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) :
6076                                                                                 sizeof(struct Module), 0, (void *)Module_Constructor, (void *)Module_Destructor, module, baseSystemAccess, publicAccess);
6077    eClass_AddVirtualMethod(moduleClass, "OnLoad", "bool()", null, publicAccess);
6078    eClass_AddVirtualMethod(moduleClass, "OnUnload", "void()", null, publicAccess);
6079    eClass_AddMethod(moduleClass, "Load", "Module(char * name, AccessMode importAccess)", eModule_Load, publicAccess);
6080    eClass_AddMethod(moduleClass, "Unload", "void(Module module)", eModule_Unload, publicAccess);
6081    eClass_AddDataMember(moduleClass, "application", "Application", pointerSize, pointerSize, publicAccess);
6082    eClass_AddDataMember(moduleClass, "classes", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6083    eClass_AddDataMember(moduleClass, "defines", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6084    eClass_AddDataMember(moduleClass, "functions", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6085    eClass_AddDataMember(moduleClass, "modules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6086    eClass_AddDataMember(moduleClass, "prev", "Module", pointerSize, pointerSize, publicAccess);
6087    eClass_AddDataMember(moduleClass, "next", "Module", pointerSize, pointerSize, publicAccess);
6088    eClass_AddDataMember(moduleClass, "name", "char *", pointerSize, pointerSize, publicAccess);
6089    eClass_AddDataMember(moduleClass, "library", "void *", pointerSize, pointerSize, publicAccess);
6090    eClass_AddDataMember(moduleClass, "Unload", "void *", pointerSize, pointerSize, publicAccess);
6091    eClass_AddDataMember(moduleClass, "importType", "ImportType", sizeof(ImportType), 4, publicAccess);
6092    eClass_AddDataMember(moduleClass, "origImportType", "ImportType", sizeof(ImportType), 4, publicAccess);
6093    eClass_AddDataMember(moduleClass, "privateNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6094    eClass_AddDataMember(moduleClass, "publicNameSpace", "NameSpace",  force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6095    moduleClass.fixed = true;
6096    moduleClass.count++;
6097    if(inCompiler && force32Bits)
6098       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);
6099
6100    // Create Application class
6101    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);
6102    if(inCompiler && force32Bits)
6103    {
6104       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);
6105       applicationClass.structSize = applicationClass.offset + (4+4+4+4 + 20 + 4 + 88);
6106    }
6107    eClass_AddVirtualMethod(applicationClass, "Main", "void()", null, publicAccess);
6108    eClass_AddDataMember(applicationClass, "argc", "int", sizeof(int), 4, publicAccess);
6109    eClass_AddDataMember(applicationClass, "argv", "char **", pointerSize, pointerSize, publicAccess);
6110    eClass_AddDataMember(applicationClass, "exitCode", "int", sizeof(int), 4, publicAccess);
6111    eClass_AddDataMember(applicationClass, "isGUIApp", "bool", sizeof(bool), 4, publicAccess);
6112    eClass_AddDataMember(applicationClass, "allModules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6113    eClass_AddDataMember(applicationClass, "parsedCommand", "char *", pointerSize, pointerSize, publicAccess);
6114    eClass_AddDataMember(applicationClass, "systemNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6115    applicationClass.fixed = true;
6116    applicationClass.count++;
6117
6118    //AttachConsole(-1);
6119    //AllocConsole();
6120
6121    // --- Math ---
6122    eSystem_RegisterFunction("sin", "double sin(Angle number)", sin, module, baseSystemAccess);
6123    eSystem_RegisterFunction("sinh", "double sinh(Angle number)", sinh, module, baseSystemAccess);
6124    eSystem_RegisterFunction("cosh", "double cosh(Angle number)", cosh, module, baseSystemAccess);
6125    eSystem_RegisterFunction("tanh", "double tanh(Angle number)", tanh, module, baseSystemAccess);
6126    eSystem_RegisterFunction("sqrt", "double sqrt(double number)", sqrt, module, baseSystemAccess);
6127    eSystem_RegisterFunction("cos", "double cos(Angle number)", cos, module, baseSystemAccess);
6128    eSystem_RegisterFunction("tan", "double tan(Angle number)", tan, module, baseSystemAccess);
6129    eSystem_RegisterFunction("atan2", "Angle atan2(double y, double x)", atan2, module, baseSystemAccess);
6130    eSystem_RegisterFunction("asin", "Angle asin(double number)", asin, module, baseSystemAccess);
6131    eSystem_RegisterFunction("acos", "Angle acos(double number)", acos, module, baseSystemAccess);
6132    eSystem_RegisterFunction("atan", "Angle atan(double number)", atan, module, baseSystemAccess);
6133    eSystem_RegisterFunction("pow", "double pow(double number, double number2)", pow, module, baseSystemAccess);
6134    eSystem_RegisterFunction("fmod", "double fmod(double x, double y)", fmod, module, baseSystemAccess);
6135    eSystem_RegisterFunction("fabs", "double fabs(double number)", fabs, module, baseSystemAccess);
6136    eSystem_RegisterFunction("log", "double log(double number)", log, module, baseSystemAccess);
6137    eSystem_RegisterFunction("log10", "double log10(double number)", log10, module, baseSystemAccess);
6138    eSystem_RegisterFunction("ceil", "double ceil(double number)", ceil, module, baseSystemAccess);
6139    eSystem_RegisterFunction("floor", "double floor(double number)", floor, module, baseSystemAccess);
6140    eSystem_RegisterFunction("exp", "double exp(double number)", exp, module, baseSystemAccess);
6141
6142    // --- Stdlib ---
6143    eSystem_RegisterFunction("qsort", "void qsort(void *, uintsize, uintsize, int (*)(void *, void *))", qsort, module, baseSystemAccess);
6144    eSystem_RegisterFunction("strtod", "double strtod(char*, char**)", strtod, module, baseSystemAccess);
6145    eSystem_RegisterFunction("strtol", "int strtol(char*, char**, int base)", strtol, module, baseSystemAccess);
6146    eSystem_RegisterFunction("system", "int system(const char*)", system, module, baseSystemAccess);
6147    eSystem_RegisterFunction("atoi", "int atoi(const char*)", atoi, module, baseSystemAccess);
6148    eSystem_RegisterFunction("atof", "double atof(const char*)", atof, module, baseSystemAccess);
6149    eSystem_RegisterFunction("tolower", "int tolower(int)", tolower, module, baseSystemAccess);
6150    eSystem_RegisterFunction("toupper", "int toupper(int)", toupper, module, baseSystemAccess);
6151    eSystem_RegisterFunction("isdigit", "bool isdigit(int)", isdigit, module, baseSystemAccess);
6152    eSystem_RegisterFunction("memset", "void * memset(void * area, int value, uintsize count)", memset, module, baseSystemAccess);
6153    eSystem_RegisterFunction("getenv", "char * getenv(const char * name)", getenv, module, baseSystemAccess);
6154    eSystem_RegisterFunction("rename", "int rename(const char *oldpath, const char *newpath)", rename, module, baseSystemAccess);
6155
6156    // --- String --- (These might move to the string class)
6157    eSystem_RegisterFunction("strlen", "uintsize strlen(const char *)", strlen, module, baseSystemAccess);
6158    eSystem_RegisterFunction("strcat", "char * strcat(char *, const char *)", strcat, module, baseSystemAccess);
6159    eSystem_RegisterFunction("strncat", "char * strncat(char *, const char *, uintsize n)", strncat, module, baseSystemAccess);
6160    eSystem_RegisterFunction("strchr", "char * strchr(const char *, int)", strchr, module, baseSystemAccess);
6161    eSystem_RegisterFunction("strstr", "char * strstr(const char *, const char *)", strstr, module, baseSystemAccess);
6162    eSystem_RegisterFunction("strspn", "uintsize strspn(const char *, const char *)", strspn, module, baseSystemAccess);
6163    eSystem_RegisterFunction("strcspn", "uintsize strcspn(const char *, const char *)", strcspn, module, baseSystemAccess);
6164    eSystem_RegisterFunction("strpbrk", "char * strpbrk(const char *, const char *)", strpbrk, module, baseSystemAccess);
6165
6166    eSystem_RegisterDefine("fstrcmp", "(GetRuntimePlatform() == win32) ? strcmpi : strcmp", module, baseSystemAccess);
6167
6168 //#if defined(__GNUC__)
6169    eSystem_RegisterDefine("strcmpi", "strcasecmp", module, baseSystemAccess);
6170    eSystem_RegisterDefine("strnicmp", "strncasecmp", module, baseSystemAccess);
6171    eSystem_RegisterFunction("strcasecmp", "int strcasecmp(const char *, const char *)", strcmpi, module, baseSystemAccess);
6172    eSystem_RegisterFunction("strncasecmp", "int strncasecmp(const char *, const char *, uintsize n)", strnicmp, module, baseSystemAccess);
6173 /*
6174 #else
6175    eSystem_RegisterDefine("strcasecmp", "strcmpi", module, baseSystemAccess);
6176    eSystem_RegisterDefine("strncasecmp", "strnicmp", module, baseSystemAccess);
6177    eSystem_RegisterFunction("strcmpi", "int strcmpi(const char *, const char *)", strcmpi, module, baseSystemAccess);
6178    eSystem_RegisterFunction("strnicmp", "int strnicmp(const char *, const char *, int n)", strnicmp, module, baseSystemAccess);
6179 #endif
6180 */
6181
6182    eSystem_RegisterFunction("strcmp", "int strcmp(const char *, const char *)", strcmp, module, baseSystemAccess);
6183    eSystem_RegisterFunction("strncmp", "int strncmp(const char *, const char *, uintsize n)", strncmp, module, baseSystemAccess);
6184    eSystem_RegisterFunction("strlwr", "char * strlwr(char *)", strlwr, module, baseSystemAccess);
6185    eSystem_RegisterFunction("strupr", "char * strupr(char *)", strupr, module, baseSystemAccess);
6186    eSystem_RegisterFunction("strcpy", "char * strcpy(char *, const char *)", strcpy, module, baseSystemAccess);
6187    eSystem_RegisterFunction("strncpy", "char * strncpy(char *, const char *, uintsize n)", strncpy, module, baseSystemAccess);
6188    eSystem_RegisterFunction("memcpy", "void * memcpy(void *, const void *, uintsize size)", memcpy, module, baseSystemAccess);
6189    eSystem_RegisterFunction("memmove", "void * memmove(void *, const void *, uintsize size)", memmove, module, baseSystemAccess);
6190
6191    // --- Stdio ---
6192    eSystem_RegisterFunction("sprintf", "int sprintf(char *, char *, ...)", sprintf, module, baseSystemAccess);
6193    eSystem_RegisterFunction("snprintf", "int sprintf(char *, uintsize, char *, ...)", snprintf, module, baseSystemAccess);
6194    eSystem_RegisterFunction("printf", "int printf(char *, ...)", printf, module, baseSystemAccess);
6195    eSystem_RegisterFunction("vsprintf", "int vsprintf(char*, const char*, __builtin_va_list)", vsprintf, module, baseSystemAccess);
6196    eSystem_RegisterFunction("vsnprintf", "int vsnprintf(char*, uintsize, const char*, __builtin_va_list)", vsnprintf, module, baseSystemAccess);
6197    eSystem_RegisterFunction("puts", "int puts(char *)", puts, module, baseSystemAccess);
6198    eSystem_RegisterFunction("fputs", "int fputs(char *, void * stream)", fputs, module, baseSystemAccess);
6199
6200    // --- Ctype ---
6201    eSystem_RegisterFunction("isalnum", "int isalnum(int c)", isalnum, module, baseSystemAccess);
6202    eSystem_RegisterFunction("isspace", "int isspace(int c)", isspace, module, baseSystemAccess);
6203    eSystem_RegisterFunction("isalpha", "int isalpha(int c)", isalpha, module, baseSystemAccess);
6204    eSystem_RegisterFunction("islower", "int islower(int c)", islower, module, baseSystemAccess);
6205    eSystem_RegisterFunction("isupper", "int isupper(int c)", isupper, module, baseSystemAccess);
6206    eSystem_RegisterFunction("isprint", "int isprint(int c)", isprint, module, baseSystemAccess);
6207    eSystem_RegisterFunction("strtoul", "unsigned long strtoul(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
6208    eSystem_RegisterFunction("strtoll", "int64 strtoll(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
6209    eSystem_RegisterFunction("strtoull", "uint64 strtoull(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
6210
6211 }
6212
6213 public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char * argv[])
6214 {
6215    Application app;
6216
6217 #ifdef __ANDROID__
6218    // Clean up global variables
6219    memoryInitialized = false;
6220    pools = null;
6221 #ifdef MEMINFO
6222    memset(&memStacks, 0, sizeof(BinaryTree));
6223    memoryErrorsCount = 0;
6224    memset(&memBlocks, 0, sizeof(BinaryTree));
6225    recurse = false;
6226    blockID = 0;
6227    allocateClass = null;
6228    allocateInternal = false;
6229    TOTAL_MEM = 0;
6230    OUTSIDE_MEM = 0;
6231 #endif
6232 #endif
6233
6234 #ifdef _DEBUG
6235    // printf("Using debug ecere runtime library\n");
6236 #endif
6237    app = _calloc(1, sizeof(class Application));
6238
6239    Module_Constructor(app);
6240    app.systemNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
6241    app.systemNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
6242    app.systemNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
6243    app.systemNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6244
6245    Instance_COM_Initialize(argc, argv, &app.parsedCommand, &app.argc, &app.argv);
6246
6247    app.application = app;
6248    app.allModules.offset = sizeof(class Instance) + (uint)&((struct Module *)0)->prev;
6249    app.isGUIApp = guiApp;
6250
6251    LoadCOM(app);
6252
6253    app._class = eSystem_FindClass(app, "Application");
6254
6255    return app;
6256 }
6257
6258 public dllexport ClassTemplateParameter eClass_AddTemplateParameter(Class _class, char * name, TemplateParameterType type, void * info, ClassTemplateArgument defaultArg)
6259 {
6260    if(_class && name)
6261    {
6262       ClassTemplateParameter param;
6263
6264       for(param = _class.templateParams.first; param; param = param.next)
6265       {
6266          if(!strcmp(param.name, name))
6267             return param;
6268       }
6269       param =
6270       {
6271          name = CopyString(name);
6272          type = type;
6273          (type == identifier) ? info : CopyString(info);
6274       };
6275       if(defaultArg != null)
6276       {
6277          param.defaultArg = defaultArg;
6278          CopyTemplateArg(param, param.defaultArg);
6279       }
6280       _class.templateParams.Add(param);
6281       return param;
6282    }
6283    return null;
6284 }
6285
6286 public dllexport void eClass_DoneAddingTemplateParameters(Class base)
6287 {
6288    if(base)
6289    {
6290       OldLink derivative;
6291       ClassTemplateParameter param;
6292       {
6293          void * first = base.templateParams.first;
6294          int count = base.templateParams.count;
6295
6296          FreeTemplateArgs(base);
6297          delete base.templateArgs;
6298
6299          base.templateParams.first = null;
6300          base.templateParams.count = 0;
6301
6302          FreeTemplatesDerivatives(base);
6303
6304          base.templateParams.first = first;
6305          base.templateParams.count = count;
6306       }
6307
6308       for(param = base.templateParams.first; param; param = param.next)
6309       {
6310          if(param.type == identifier && param.defaultArg.memberString)
6311          {
6312             Class memberClass = base;
6313             char * colon = strstr(param.defaultArg.memberString, "::");
6314             char * memberName;
6315             if(colon)
6316             {
6317                char className[1024];
6318                Class sClass;
6319
6320                memcpy(className, param.defaultArg.memberString, colon - param.defaultArg.memberString);
6321                className[colon - param.defaultArg.memberString] = '\0';
6322                memberName = colon + 2;
6323
6324                for(sClass = base; sClass; sClass = sClass.base)
6325                {
6326                   ClassTemplateParameter cParam;
6327                   Class nextClass;
6328                   int id = 0;
6329                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) id += nextClass.templateParams.count;
6330                   // Safety! What could cause base.templateArgs to be null?
6331                   if(sClass == base || base.templateArgs)
6332                   {
6333                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
6334                      {
6335                         if(cParam.type == type && !strcmp(cParam.name, className))
6336                            strcpy(className, (sClass == base) ? cParam.defaultArg.dataTypeString : base.templateArgs[id].dataTypeString);
6337                         id++;
6338                      }
6339                   }
6340                }
6341                memberClass = eSystem_FindClass(base.module, className);
6342                if(!memberClass)
6343                   memberClass = eSystem_FindClass(base.module.application, className);
6344             }
6345             else
6346                memberName = param.defaultArg.memberString;
6347
6348             if(memberClass)
6349             {
6350                switch(param.memberType)
6351                {
6352                   case dataMember:
6353                      param.defaultArg.member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
6354                      break;
6355                   case method:
6356                      param.defaultArg.method = eClass_FindMethod(memberClass, memberName, memberClass.module);
6357                      break;
6358                   case prop:
6359                      param.defaultArg.prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
6360                      break;
6361                }
6362             }
6363          }
6364       }
6365
6366       //ComputeClassParameters(base, null, null);
6367
6368       FixDerivativesBase(base, base);
6369    }
6370 }
6371
6372 static void FreeTemplatesDerivatives(Class base)
6373 {
6374    OldLink derivative, templateLink;
6375    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
6376    {
6377       Class _class = derivative.data;
6378       if(_class.templateArgs)
6379       {
6380          FreeTemplateArgs(_class);
6381          delete _class.templateArgs;
6382       }
6383       FreeTemplatesDerivatives(_class);
6384    }
6385
6386    for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
6387    {
6388       Class _class = templateLink.data;
6389       if(_class.templateArgs)
6390       {
6391          FreeTemplateArgs(_class);
6392          delete _class.templateArgs;
6393       }
6394       FreeTemplatesDerivatives(_class);
6395    }
6396 }
6397
6398 static const char * platformNames[Platform] = { "", "win32", "linux", "apple" }; // how to have this be accessible outside of dll/lib
6399 static const Platform firstPlatform = win32;
6400 static const Platform lastPlatform = apple;
6401
6402 public enum Platform
6403 {
6404    unknown, win32, tux, apple;
6405
6406    property char *
6407    {
6408       get { return OnGetString(null, null, null); }
6409       set
6410       {
6411          if(value)
6412          {
6413             Platform c;
6414             for(c = firstPlatform; c <= lastPlatform; c++)
6415                if(!strcmpi(value, platformNames[c]))
6416                   return c;
6417          }
6418          return unknown;
6419       }
6420    };
6421
6422    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
6423    {
6424       if(this >= firstPlatform && this <= lastPlatform)
6425       {
6426          if(tempString)
6427             strcpy(tempString, platformNames[this]);
6428          return platformNames[this];
6429       }
6430       if(tempString && tempString[0])
6431          tempString[0] = '\0';
6432       return null;
6433    }
6434
6435    bool OnGetDataFromString(char * string)
6436    {
6437       this = string;
6438       return (bool)this;
6439    }
6440 };
6441
6442 default extern Platform runtimePlatform;
6443
6444 public Platform GetRuntimePlatform()
6445 {
6446    return runtimePlatform;
6447 }
6448
6449 namespace gui;
6450
6451 class Window;
6452
6453 namespace com;
6454 // CLASS DESIGNER SUPPORT
6455
6456 public class ObjectInfo : struct
6457 {
6458 public:
6459    ObjectInfo prev, next;
6460    Instance instance;
6461    char * name;
6462    Instantiation instCode;
6463    bool deleted;
6464    ObjectInfo oClass;
6465    OldList instances;
6466    ClassDefinition classDefinition;
6467    bool modified;
6468 };
6469
6470 public class DesignerBase : Window
6471 {
6472 public:
6473    virtual bool FindObject(Instance * instance, char * string);
6474    virtual void RenameObject(ObjectInfo object, char * name);
6475    virtual void SelectObjectFromDesigner(ObjectInfo object);
6476    virtual void CodeAddObject(Instance instance, ObjectInfo * object);
6477    virtual void SheetAddObject(ObjectInfo object);
6478    virtual void AddToolBoxClass(Class _class);
6479    virtual void AddDefaultMethod(Instance instance, Instance classInstance);
6480    virtual void DeleteObject(ObjectInfo object);
6481    virtual bool ObjectContainsCode(ObjectInfo object);
6482    virtual void ModifyCode(void);
6483    virtual void UpdateProperties(void);
6484
6485    ClassDesignerBase classDesigner;
6486    char * objectClass;
6487    bool isDragging;
6488
6489    // FIX THIS WITH PUBLIC:
6490    property ClassDesignerBase classDesigner
6491    {
6492       get { return classDesigner; }
6493       set { classDesigner = value; }
6494    };
6495    property char * objectClass
6496    {
6497       get { return objectClass; }
6498       set { objectClass = value; }
6499    };
6500    property bool isDragging
6501    {
6502       get { return isDragging; }
6503       set { isDragging = value; }
6504    };
6505 }
6506
6507 public class ClassDesignerBase : Window
6508 {
6509 public:
6510    virtual void Reset(void);
6511    virtual void AddObject(void);
6512    virtual void SelectObject(ObjectInfo object, Instance control);
6513
6514    virtual void ListToolBoxClasses(DesignerBase designer);
6515
6516    virtual void ::PrepareTestObject(DesignerBase designer, Instance test);
6517    virtual void ::CreateObject(DesignerBase designer, Instance instance, ObjectInfo object, bool isClass, Instance _class);
6518    virtual void ::PostCreateObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6519    virtual void ::DroppedObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6520    virtual void ::DestroyObject(Instance object);
6521    virtual void ::FixProperty(Property prop, Instance object);
6522    virtual void ::CreateNew(EditBox editBox, Size clientSize, char * name, char * inherit);
6523 }
6524
6525 DesignerBase activeDesigner;
6526
6527 public void SetActiveDesigner(DesignerBase designer)
6528 {
6529    activeDesigner = designer;
6530 }
6531
6532 public DesignerBase GetActiveDesigner()
6533 {
6534    return activeDesigner;
6535 }
6536
6537
6538 bool poolingDisabled;
6539
6540 public dllexport void eSystem_SetPoolingDisabled(bool disabled)
6541 {
6542    poolingDisabled = disabled;
6543 }
6544
6545 namespace sys;
6546
6547 // constants
6548 define LEAD_OFFSET      = 0xD800 - (0x10000 >> 10);
6549 define SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00;
6550
6551 public bool UTF8Validate(char * source)
6552 {
6553    if(source)
6554    {
6555       int c;
6556       for(c = 0; source[c];)
6557       {
6558          byte ch = source[c];
6559          unichar codePoint = 0;
6560          int numBytes = 1;
6561          int i;
6562          byte mask = 0x7F;
6563          if(ch & 0x80)
6564          {
6565             if(ch & 0x40)
6566             {
6567                mask >>= 2;
6568                numBytes++;
6569                if(ch & 0x20)
6570                {
6571                   numBytes++;
6572                   mask >>= 1;
6573                   if(ch & 0x10)
6574                   {
6575                      if(ch & 0x08)
6576                         return false;
6577                      numBytes++;
6578                      mask >>= 1;
6579                   }
6580                }
6581             }
6582             else
6583                return false;
6584          }
6585          for(i = 0; i<numBytes && (ch = source[c]); i++, c++)
6586          {
6587             codePoint <<= 6;
6588             codePoint |= ch & mask;
6589             mask = 0x3F;
6590             if(i > 1)
6591             {
6592                if(!(ch & 0x80) || (ch & 0x40))
6593                   return false;
6594             }
6595          }
6596          if(i < numBytes) return false;
6597
6598          if(codePoint > 0x10FFFF || (codePoint >= 0xD800 && codePoint <= 0xDFFF) ||
6599            (codePoint < 0x80 && numBytes > 1) ||
6600            (codePoint < 0x800 && numBytes > 2) ||
6601            (codePoint < 0x10000 && numBytes > 3))
6602             return false;
6603       }
6604    }
6605    return true;
6606 }
6607
6608 public int ISO8859_1toUTF8(char * source, char * dest, int max)
6609 {
6610    int c;
6611    int d = 0;
6612    for(c = 0; source[c]; c++)
6613    {
6614       unichar ch = ((byte *)source)[c];
6615       switch(ch)
6616       {
6617          case 150: ch = (unichar)0x2012; break;
6618       }
6619       if(ch < 0x80)
6620       {
6621          if(d + 1 >= max) break;
6622          dest[d++] = (char)ch;
6623       }
6624       else if(ch < 0x800)
6625       {
6626          if(d + 2 >= max) break;
6627          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6628          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6629       }
6630       else if(ch < 0x10000)
6631       {
6632          if(d + 3 >= max) break;
6633          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6634          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6635          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6636       }
6637       else
6638       {
6639          if(d + 4 >= max) break;
6640          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6641          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6642          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6643          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6644       }
6645    }
6646    dest[d] = 0;
6647    return d;
6648 }
6649
6650 public char * UTF16toUTF8(uint16 * source)
6651 {
6652    int c;
6653    int d = 0;
6654    int len;
6655    char * dest;
6656    uint16 u16;
6657    bool invert = false;
6658
6659    for(len = 0; source[len]; len++);
6660    dest = new char[len * 3 + 1];
6661    for(c = 0; (u16 = source[c]); c++)
6662    {
6663       unichar ch;
6664       if(!c && (u16 == 0xFFFE || u16 == 0xFEFF))
6665       {
6666          if(u16 == 0xFFFE) invert = true;
6667          continue;
6668       }
6669       if(invert) { u16 = ((u16 & 0xFF00) >> 8) | ((u16 & 0x00FF) << 8); }
6670
6671       if(u16 < 0xD800 || u16 > 0xDBFF)
6672          ch = (unichar)u16;
6673       else
6674          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6675
6676       if(ch < 0x80)
6677       {
6678          dest[d++] = (char)ch;
6679       }
6680       else if(ch < 0x800)
6681       {
6682          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6683          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6684       }
6685       else if(ch < 0x10000)
6686       {
6687          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6688          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6689          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6690       }
6691       else
6692       {
6693          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6694          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6695          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6696          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6697       }
6698    }
6699    dest[d] = 0;
6700    dest = renew dest char[d+1];
6701    return dest;
6702 }
6703
6704 public int UTF16toUTF8Buffer(uint16 * source, byte * dest, int max)
6705 {
6706    int c;
6707    int d = 0;
6708    uint16 u16;
6709    for(c = 0; (u16 = source[c]); c++)
6710    {
6711       unichar ch;
6712       if(u16 < 0xD800 || u16 > 0xDBFF)
6713          ch = (unichar)u16;
6714       else
6715          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6716
6717       if(ch < 0x80)
6718       {
6719          if(d + 1 >= max) break;
6720          dest[d++] = (char)ch;
6721       }
6722       else if(ch < 0x800)
6723       {
6724          if(d + 2 >= max) break;
6725          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6726          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6727       }
6728       else if(ch < 0x10000)
6729       {
6730          if(d + 3 >= max) break;
6731          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6732          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6733          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6734       }
6735       else
6736       {
6737          if(d + 4 >= max) break;
6738          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6739          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6740          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6741          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6742       }
6743    }
6744    dest[d] = 0;
6745    return d;
6746 }
6747
6748 // NOTE: UTF8GetChar now returns 0 into numBytes for the null-terminating character ('\0')
6749 public unichar UTF8GetChar(char * string, int * numBytes)
6750 {
6751    unichar ch;
6752    byte b = ((byte *)string)[0];
6753    int i;
6754    byte mask = 0x7F;
6755    int nb = b ? 1 : 0;
6756    ch = 0;
6757    if(b & 0x80)
6758    {
6759       if(b & 0x40)
6760       {
6761          mask >>= 2;
6762          nb++;
6763          if(b & 0x20)
6764          {
6765             nb++;
6766             mask >>= 1;
6767             if(b & 0x10)
6768             {
6769                if(b & 0x08) { nb = 0; }
6770                nb++;
6771                mask >>= 1;
6772             }
6773          }
6774       }
6775       else
6776          nb = 0;
6777    }
6778    for(i = 0; i<nb; i++)
6779    {
6780       ch <<= 6;
6781       ch |= (b = ((byte *)string)[i]) & mask;
6782       mask = 0x3F;
6783       if(i > 1 && (!(b & 0x80) || (b & 0x40)))
6784       {
6785          nb = 0;
6786          ch = 0;
6787       }
6788    }
6789
6790    if(i < nb ||
6791       ch > 0x10FFFF || (ch >= 0xD800 && ch <= 0xDFFF) ||
6792      (ch < 0x80 && nb > 1) ||
6793      (ch < 0x800 && nb > 2) ||
6794      (ch < 0x10000 && nb > 3))
6795    {
6796       ch = 0;
6797       nb = 0;
6798    }
6799    if(numBytes) *numBytes = nb;
6800    return ch;
6801 }
6802
6803 public int UTF8toUTF16Buffer(char * source, uint16 * dest, int max)
6804 {
6805    if(source)
6806    {
6807       int c;
6808       int d = 0;
6809       for(c = 0; source[c];)
6810       {
6811          byte ch = source[c];
6812          unichar codePoint = 0;
6813          int numBytes = 1;
6814          int i;
6815          byte mask = 0x7F;
6816          if(ch & 0x80 && ch & 0x40)
6817          {
6818             mask >>= 2;
6819             numBytes++;
6820             if(ch & 0x20)
6821             {
6822                numBytes++;
6823                mask >>= 1;
6824                if(ch & 0x10)
6825                {
6826                   numBytes++;
6827                   mask >>= 1;
6828                }
6829             }
6830          }
6831          for(i = 0; i<numBytes; i++)
6832          {
6833             codePoint <<= 6;
6834             codePoint |= source[c++] & mask;
6835             mask = 0x3F;
6836          }
6837
6838          if(codePoint > 0xFFFF)
6839          {
6840             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6841             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6842             if(d >= max - 1) break;
6843             dest[d++] = lead;
6844             dest[d++] = trail;
6845          }
6846          else
6847          {
6848             if(d >= max) break;
6849             dest[d++] = (uint16)codePoint;
6850          }
6851       }
6852       dest[d] = 0;
6853       return d;
6854    }
6855    return 0;
6856 }
6857
6858 public int UTF32toUTF8Len(unichar * source, int count, byte * dest, int max)
6859 {
6860    int c;
6861    int d = 0;
6862    uint32 ch;
6863    for(c = 0; c<count && (ch = source[c]); c++)
6864    {
6865       if(ch < 0x80)
6866       {
6867          if(d + 1 >= max) break;
6868          dest[d++] = (char)ch;
6869       }
6870       else if(ch < 0x800)
6871       {
6872          if(d + 2 >= max) break;
6873          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6874          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6875       }
6876       else if(ch < 0x10000)
6877       {
6878          if(d + 3 >= max) break;
6879          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6880          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6881          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6882       }
6883       else
6884       {
6885          if(d + 4 >= max) break;
6886          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6887          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6888          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6889          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6890       }
6891    }
6892    dest[d] = 0;
6893    return d;
6894 }
6895
6896 public uint16 * UTF8toUTF16(char * source, int * wordCount)
6897 {
6898    if(source)
6899    {
6900       int len = (int)strlen(source);
6901       uint16 * dest = new uint16[len + 1];
6902       int c;
6903       int d = 0;
6904       for(c = 0; source[c];)
6905       {
6906          byte ch = source[c];
6907          unichar codePoint = 0;
6908          int numBytes = 1;
6909          int i;
6910          byte mask = 0x7F;
6911          if(ch & 0x80 && ch & 0x40)
6912          {
6913             mask >>= 2;
6914             numBytes++;
6915             if(ch & 0x20)
6916             {
6917                numBytes++;
6918                mask >>= 1;
6919                if(ch & 0x10)
6920                {
6921                   numBytes++;
6922                   mask >>= 1;
6923                }
6924             }
6925          }
6926          for(i = 0; i<numBytes; i++)
6927          {
6928             codePoint <<= 6;
6929             codePoint |= source[c++] & mask;
6930             mask = 0x3F;
6931          }
6932
6933          if(codePoint > 0xFFFF)
6934          {
6935             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6936             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6937             dest[d++] = lead;
6938             dest[d++] = trail;
6939          }
6940          else
6941          {
6942             dest[d++] = (uint16)codePoint;
6943          }
6944       }
6945       dest[d] = 0;
6946       if(wordCount) *wordCount = d;
6947       return dest;
6948    }
6949    return null;
6950 }
6951
6952 namespace com;