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