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