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