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