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