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