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