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