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