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