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