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