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