ecere/com/instance.ec: Prevent IDE crashes in instance.ec
[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;
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          break;
2940       case identifier:
2941          delete (void *)template.templateArgs[id].memberString;
2942          break;
2943       case expression:
2944
2945          break;
2946    }
2947 }
2948
2949 static void FreeTemplateArgs(Class template)
2950 {
2951    if(template.templateArgs)
2952    {
2953       Class _class;
2954       for(_class = template; _class; _class = _class.base)
2955       {
2956          Class prevClass;
2957          ClassTemplateParameter param;
2958          int id = 0;
2959          if(_class.templateClass) _class = _class.templateClass;
2960          for(prevClass = _class.base; prevClass; prevClass = prevClass.base)
2961          {
2962             if(prevClass.templateClass) prevClass = prevClass.templateClass;
2963             id += prevClass.templateParams.count;
2964          }
2965          if(id < template.numParams)
2966          {
2967             for(param = _class.templateParams.first; param; param = param.next)
2968             {
2969                switch(param.type)
2970                {
2971                   case type:
2972                      delete (void *)template.templateArgs[id].dataTypeString;
2973                      break;
2974                   case identifier:
2975                      delete (void *)template.templateArgs[id].memberString;
2976                      break;
2977                   case expression:
2978                      // delete template.templateArgs[id].dataTypeString;
2979                      break;
2980                }
2981                id++;
2982             }
2983          }
2984       }
2985    }
2986 }
2987
2988 static void FreeTemplate(Class template)
2989 {
2990    OldLink deriv;
2991
2992    if(template.nameSpace)
2993    {
2994       BTNamedLink link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
2995       if(link)
2996          template.nameSpace->classes.Delete((BTNode)link);
2997    }
2998    FreeTemplateArgs(template);
2999
3000    delete (void *)template.fullName;
3001    delete (void *)template.name;
3002    delete (void *)template.templateArgs;
3003    delete (void *)template.dataTypeString;
3004
3005    while((deriv = template.derivatives.first))
3006    {
3007       ((Class)deriv.data).base = null;
3008       template.derivatives.Delete(deriv);
3009    }
3010
3011    if(template.module)
3012       template.module.classes.Delete(template);
3013    else
3014       _free(template);
3015 }
3016
3017 static void FreeTemplates(Class _class)
3018 {
3019    OldLink deriv, template;
3020
3021    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
3022    {
3023       FreeTemplates(deriv.data);
3024    }
3025
3026    FreeTemplateArgs(_class);
3027    //if(_class.templateArgs)
3028       //printf("Deleting  Template args for %s\n", _class.name);
3029    delete _class.templateArgs;
3030    delete (void *)_class.dataTypeString;
3031
3032    while((template = _class.templatized.first))
3033    {
3034       FreeTemplates(template.data);
3035       FreeTemplate(template.data);
3036       _class.templatized.Delete(template);
3037    }
3038 }
3039
3040 public dllexport void eClass_Unregister(Class _class)
3041 {
3042    BTNamedLink namedLink;
3043    DataMember member;
3044    Method method;
3045    OldLink deriv, template;
3046    ClassProperty classProp;
3047    ClassTemplateParameter param;
3048
3049    if(_class.templateClass)
3050    {
3051       // Unregistering templates... Used in IDE to address crash on Ecere classes templatized with imported modules
3052       OldLink templateLink;
3053       for(templateLink = _class.templateClass.templatized.first; templateLink; templateLink = templateLink.next)
3054       {
3055          if(templateLink.data == _class)
3056          {
3057             _class.templateClass.templatized.Delete(templateLink);
3058             break;
3059          }
3060       }
3061       FreeTemplate(_class);
3062       return;
3063    }
3064
3065    delete _class._vTbl;
3066
3067    FreeTemplates(_class);
3068
3069    FreeTemplateArgs(_class);
3070    delete _class.templateArgs;
3071
3072    while((template = _class.templatized.first))
3073    {
3074       FreeTemplate(template.data);
3075       _class.templatized.Delete(template);
3076    }
3077
3078    while((member = _class.membersAndProperties.first))
3079    {
3080       if(!member.isProperty && (member.type == unionMember || member.type == structMember))
3081          DataMember_Free(member);
3082       delete (void *)member.name;
3083       delete (void *)member.dataTypeString;
3084       _class.membersAndProperties.Delete(member);
3085    }
3086
3087    while((member = _class.conversions.first))
3088    {
3089       delete (void *)member.name;
3090       delete (void *)member.dataTypeString;
3091       _class.conversions.Delete(member);
3092    }
3093
3094    while((namedLink = (BTNamedLink)_class.prop.first))
3095    {
3096       _class.prop.Delete((BTNode)namedLink);
3097    }
3098
3099    while((namedLink = (BTNamedLink)_class.members.first))
3100    {
3101       _class.members.Delete((BTNode)namedLink);
3102    }
3103
3104    while((classProp = (ClassProperty)_class.classProperties.first))
3105    {
3106       delete (void *)classProp.name;
3107       delete (void *)classProp.dataTypeString;
3108       _class.classProperties.Delete((BTNode)classProp);
3109    }
3110
3111    while((method = (Method)_class.methods.first))
3112    {
3113       delete (void *)method.name;
3114       delete (void *)method.dataTypeString;
3115       _class.methods.Delete((BTNode)method);
3116    }
3117
3118    if(_class.type == enumClass)
3119    {
3120       EnumClassData data = (EnumClassData)_class.data;
3121
3122       data.values.Free((void *)FreeEnumValue);
3123    }
3124    _class.delayedCPValues.Free(null);
3125
3126    _class.selfWatchers.Free(null);
3127
3128    if(_class.base)
3129    {
3130       // Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
3131       Class base = _class.base;
3132       for(deriv = base.derivatives.first; deriv; deriv = deriv.next)
3133       {
3134          if(deriv.data == _class)
3135             break;
3136       }
3137       if(deriv)
3138          base.derivatives.Delete(deriv);
3139    }
3140    while((deriv = _class.derivatives.first))
3141    {
3142       ((Class)deriv.data).base = null;
3143       _class.derivatives.Delete(deriv);
3144    }
3145
3146    if(_class.nameSpace)
3147    {
3148       BTNamedLink link = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
3149       _class.nameSpace->classes.Delete((BTNode)link);
3150    }
3151
3152    delete (void *)_class.name;
3153    delete (void *)_class.fullName;
3154
3155    delete (void *)_class.dataTypeString;
3156
3157    delete _class.data;
3158
3159    while((param = _class.templateParams.first))
3160    {
3161       switch(param.type)
3162       {
3163          case type:
3164             delete (void *)param.defaultArg.dataTypeString;
3165             break;
3166          case identifier:
3167             delete (void *)param.defaultArg.memberString;
3168             break;
3169          case expression:
3170
3171             break;
3172       }
3173       if(param.type != identifier) delete (void *)param.dataTypeString;
3174       delete (void *)param.name;
3175
3176       _class.templateParams.Delete(param);
3177    }
3178
3179    //_class.nameSpace->classes.Delete(_class);
3180    _free(_class);
3181 }
3182
3183 static BTNamedLink ScanNameSpace(NameSpace nameSpace, const char * name, void * listOffset)
3184 {
3185    BinaryTree * tree = (BinaryTree *)((byte *)nameSpace + (uintptr)listOffset);
3186    BTNamedLink link = (BTNamedLink)tree->Find((uintptr)name);
3187    NameSpace * child;
3188    if(!link)
3189    {
3190       for(child = (NameSpace *)nameSpace.nameSpaces.first; child; child = (NameSpace *)((BTNode)child).next)
3191       {
3192          link = ScanNameSpace(child, name, listOffset);
3193          if(link)
3194             break;
3195       }
3196    }
3197    return link;
3198 }
3199
3200 static BTNamedLink SearchNameSpace(NameSpace nameSpace, const char * name, void * listOffset)
3201 {
3202    int start = 0, c;
3203    char ch;
3204    int level = 0;
3205    for(c = 0; (ch = name[c]); c++)
3206    {
3207       if(ch == '<') level++;
3208       if(ch == '>') level--;
3209       if(level == 0 && (ch == '.' || (ch == ':' && name[c+1] == ':')))
3210       {
3211          NameSpace * newSpace;
3212          char * spaceName = _malloc(c - start + 1);
3213          memcpy(spaceName, name + start, c - start);
3214          spaceName[c-start] = '\0';
3215          newSpace = (NameSpace *)nameSpace.nameSpaces.FindString(spaceName);
3216          _free(spaceName);
3217          if(!newSpace)
3218             return null;
3219          nameSpace = newSpace;
3220          if(level == 0 && ch == ':') c++;
3221          start = c+1;
3222       }
3223    }
3224    if(c - start)
3225    {
3226       return ScanNameSpace(nameSpace, name + start, listOffset);
3227    }
3228    return null;
3229 }
3230
3231 static BTNamedLink SearchModule(Module module, const char * name, void * listOffset, bool searchPrivate)
3232 {
3233    SubModule subModule;
3234    BTNamedLink link;
3235
3236    if(searchPrivate)
3237    {
3238       link = SearchNameSpace(&module.privateNameSpace, name, listOffset);
3239       if(link) return link;
3240    }
3241    link = SearchNameSpace(&module.publicNameSpace, name, listOffset);
3242    if(link) return link;
3243
3244    for(subModule = module.modules.first; subModule; subModule = subModule.next)
3245    {
3246       if(searchPrivate || subModule.importMode == publicAccess)
3247       {
3248          // TOCHECK: Reverting to false to test what we were trying to fix by passing searchPrivate
3249          // Passing searchPrivate finds ALL classes private or not and thus classes clash
3250          // SearchModule here is called mainly from eSystem_FindClass, and also for Functions and Defines
3251
3252          link = SearchModule(subModule.module, name, listOffset, false);
3253          //link = SearchModule(subModule.module, name, listOffset, searchPrivate /*false*/);
3254          if(link) return link;
3255       }
3256    }
3257    return null;
3258 }
3259
3260 public int64 _strtoi64(const char * string, const char ** endString, int base)
3261 {
3262    int64 value = 0;
3263    int sign = 1;
3264    int c;
3265    char ch;
3266    for(c = 0; (ch = string[c]) && isspace(ch); c++);
3267    if(ch =='+') c++;
3268    else if(ch == '-') { sign = -1; c++; };
3269    if(!base)
3270    {
3271       if(ch == '0' && string[c+1] == 'x')
3272       {
3273          base = 16;
3274          c+=2;
3275       }
3276       else if(ch == '0')
3277       {
3278          base = 8;
3279          c++;
3280       }
3281       else
3282          base = 10;
3283    }
3284    for( ;(ch = string[c]); c++)
3285    {
3286       if(ch >= '0' && ch <= '9')
3287          ch -= '0';
3288       else if(ch >= 'a' && ch <= 'z')
3289          ch -= ('a' - 10);
3290       else if(ch >= 'A' && ch <= 'Z')
3291          ch -= ('A'- 10);
3292       else
3293       {
3294          if(endString)
3295             *endString = string + c;
3296          // Invalid character
3297          break;
3298       }
3299       if(ch < base)
3300       {
3301          value *= base;
3302          value += ch;
3303       }
3304       else
3305       {
3306          if(endString)
3307             *endString = string + c;
3308          // Invalid character
3309          break;
3310       }
3311    }
3312    return sign*value;
3313 }
3314
3315 public uint64 _strtoui64(const char * string, const char ** endString, int base)
3316 {
3317    uint64 value = 0;
3318    int sign = 1;
3319    int c;
3320    char ch;
3321    for(c = 0; (ch = string[c]) && isspace(ch); c++);
3322    if(ch =='+') c++;
3323    else if(ch == '-') { sign = -1; c++; };
3324    if(!base)
3325    {
3326       if(ch == '0' && string[c+1] == 'x')
3327       {
3328          base = 16;
3329          c+=2;
3330       }
3331       else if(ch == '0')
3332       {
3333          base = 8;
3334          c++;
3335       }
3336       else
3337          base = 10;
3338    }
3339    for( ;(ch = string[c]); c++)
3340    {
3341       if(ch >= '0' && ch <= '9')
3342          ch -= '0';
3343       else if(ch >= 'a' && ch <= 'z')
3344          ch -= ('a' - 10);
3345       else if(ch >= 'A' && ch <= 'Z')
3346          ch -= ('A' - 10);
3347       else
3348       {
3349          if(endString)
3350             *endString = string + c;
3351          // Invalid character
3352          break;
3353       }
3354       if(ch < base)
3355       {
3356          value *= base;
3357          value += ch;
3358       }
3359       else
3360       {
3361          if(endString)
3362             *endString = string + c;
3363          // Invalid character
3364          break;
3365       }
3366    }
3367    return sign*value;
3368 }
3369
3370 public dllexport Class eSystem_FindClass(Module module, const char * name)
3371 {
3372    if(name && module)
3373    {
3374       BTNamedLink link;
3375       if(!strncmp(name, "const ", 6)) name += 6;
3376       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->classes);
3377       if(link) return link.data;
3378
3379       link = SearchModule(module, name, &((NameSpace *)0)->classes, true);
3380       if(link) return link.data;
3381
3382       {
3383          char noTemplateName[1024];
3384          char * templateParams = strchr(name, '<');
3385
3386          if(templateParams)
3387          {
3388             strncpy(noTemplateName, name, templateParams - name);
3389             noTemplateName[templateParams - name] = '\0';
3390          }
3391          else
3392             strcpy(noTemplateName, name);
3393
3394          link = SearchNameSpace(&module.application.systemNameSpace, noTemplateName, &((NameSpace *)0)->classes);
3395          if(!link)
3396             link = SearchModule(module, noTemplateName, &((NameSpace *)0)->classes, true);
3397          if(link)
3398          {
3399             Class _class = link.data;
3400             Class templatedClass = null;
3401             char className[1024];
3402             strcpy(className, _class.fullName);
3403             strcat(className, templateParams);
3404
3405             link = SearchNameSpace(&module.application.systemNameSpace, className, &((NameSpace *)0)->classes);
3406             if(link)
3407                return link.data;
3408
3409             link = SearchModule(module, className, &((NameSpace *)0)->classes, true);
3410             if(link)
3411                return link.data;
3412
3413             if(_class && templateParams)
3414             {
3415                // if(!numParams) return null;
3416
3417                templatedClass = Class { };
3418                *templatedClass = *_class;
3419                templatedClass.templateClass = _class;
3420                //templatedClass.fullName = CopyString(name);
3421                templatedClass.fullName = CopyString(className);
3422                templatedClass.dataTypeString = CopyString(_class.dataTypeString);
3423                templatedClass.name = CopyString(templatedClass.fullName + strlen(_class.fullName) - strlen(_class.name));
3424                templatedClass.nameSpace->classes.Add((BTNode)BTNamedLink { name = (char *)templatedClass.name, data = templatedClass });
3425                templatedClass.templateArgs = null;
3426                templatedClass.numParams = 0;
3427                templatedClass.derivatives = { };
3428                templatedClass.templatized = { };
3429                templatedClass.module = module;
3430                templatedClass.count = 0; // TOCHECK: Keeping track of individual templatized classes?
3431                templatedClass.prev = null;
3432                templatedClass.next = null;
3433
3434                module.classes.Add(templatedClass);
3435
3436                ComputeClassParameters(templatedClass, templateParams, module);
3437
3438                _class.templatized.Add(OldLink { data = templatedClass });
3439             }
3440             return templatedClass;
3441          }
3442       }
3443    }
3444    return null;
3445 }
3446
3447 static void CopyTemplateArg(ClassTemplateParameter param, ClassTemplateArgument arg)
3448 {
3449    switch(param.type)
3450    {
3451       case type:
3452          arg.dataTypeString = CopyString(arg.dataTypeString);
3453          break;
3454       case expression:
3455
3456          break;
3457       case identifier:
3458          arg.memberString = CopyString(arg.memberString);
3459          break;
3460    }
3461 }
3462
3463 static void ComputeClassParameters(Class templatedClass, const char * templateParams, Module findModule)
3464 {
3465    char ch;
3466    const char * nextParamStart = templateParams ? (templateParams + 1) : null;
3467    ClassTemplateParameter curParam = null;
3468    Class lastClass = null, sClass;
3469    int curParamID = 0;
3470    int numParams = 0;
3471    Class _class = templatedClass.templateClass ? templatedClass.templateClass : templatedClass;
3472
3473    for(sClass = _class; sClass; sClass = sClass.base)
3474    {
3475       if(sClass.templateClass) sClass = sClass.templateClass;
3476       numParams += sClass.templateParams.count;
3477    }
3478
3479    if(templatedClass.templateArgs)
3480       FreeTemplateArgs(templatedClass);
3481    delete templatedClass.templateArgs;
3482    templatedClass.templateArgs = new0 ClassTemplateArgument[numParams];
3483    templatedClass.numParams = numParams;
3484
3485    if(_class != templatedClass)
3486    {
3487       /*int c;
3488       Class sClass;
3489       memcpy(templatedClass.templateArgs, _class.templateArgs, numParams * sizeof(ClassTemplateArgument));
3490       for(sClass = _class; sClass; sClass = sClass.base)
3491       {
3492          ClassTemplateParameter param;
3493          Class prevClass;
3494          int id = 0;
3495          if(sClass.templateClass) sClass = sClass.templateClass;
3496          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3497          {
3498             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3499             id += prevClass.templateParams.count;
3500          }
3501          for(param = sClass.templateParams.first; param; param = param.next)
3502            CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3503       }*/
3504    }
3505
3506    if(templatedClass.base && templatedClass.base.templateArgs && _class == templatedClass)
3507    {
3508       Class sClass;
3509       memcpy(templatedClass.templateArgs, templatedClass.base.templateArgs,
3510          sizeof(ClassTemplateArgument) * (numParams - templatedClass.templateParams.count));
3511       for(sClass = templatedClass.base; sClass; sClass = sClass.base)
3512       {
3513          ClassTemplateParameter param;
3514          Class prevClass;
3515          int id = 0;
3516          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3517          {
3518             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3519             id += prevClass.templateParams.count;
3520          }
3521
3522          if(sClass.templateClass) sClass = sClass.templateClass;
3523          for(param = sClass.templateParams.first; param; param = param.next)
3524             CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3525       }
3526    }
3527
3528    while(nextParamStart)
3529    {
3530       const char * paramStart = nextParamStart;
3531       const char * paramEnd;
3532       int level = 0;
3533       while(*paramStart == ' ') paramStart++;
3534       paramEnd = paramStart;
3535       while((ch = *paramEnd, ch && (level > 0 || (ch != '>' && ch != ','))))
3536       {
3537          if(ch == '<') level++;
3538          if(ch == '>') level--;
3539
3540          paramEnd++;
3541       }
3542       nextParamStart = (ch == ',') ? (paramEnd + 1) : null;
3543       while(*paramEnd == ' ') paramEnd--;
3544       if(paramEnd > paramStart)
3545       {
3546          const char * ptr, * equal = null;
3547          for(ptr = paramStart; ptr <= paramEnd; ptr++)
3548          {
3549             if(*ptr == '=')
3550             {
3551                equal = ptr;
3552                break;
3553             }
3554          }
3555          if(equal)
3556          {
3557             const char * end = equal - 1;
3558             char ident[1024];
3559
3560             while(*end == ' ') end--;
3561             strncpy(ident, paramStart, end + 1 - paramStart);
3562             ident[end + 1 - paramStart] = 0;
3563
3564             for(sClass = _class; sClass; sClass = sClass.base)
3565             {
3566                if(sClass.templateClass) sClass = sClass.templateClass;
3567                for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
3568                {
3569                   if(!strcmp(curParam.name, ident))
3570                      break;
3571                }
3572                if(curParam)
3573                {
3574                   Class nextClass;
3575                   ClassTemplateParameter prevParam;
3576                   curParamID = 0;
3577                   for(prevParam = curParam.prev; prevParam; prevParam = prevParam.prev) curParamID++;
3578                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3579                   {
3580                      if(nextClass.templateClass) nextClass = nextClass.templateClass;
3581                      curParamID += nextClass.templateParams.count;
3582                   }
3583                   break;
3584                }
3585             }
3586             lastClass = sClass;
3587          }
3588          else
3589          {
3590             if(curParam)
3591             {
3592                curParam = curParam.next;
3593                curParamID++;
3594             }
3595
3596             if(!curParam)
3597             {
3598                for(sClass = lastClass ? lastClass.base : _class; sClass; sClass = sClass.base)
3599                {
3600                   ClassTemplateParameter param;
3601                   curParamID = 0;
3602                   if(sClass.templateClass) sClass = sClass.templateClass;
3603                   for(param = sClass.templateParams.first; param; param = param.next, curParamID++)
3604                   {
3605                      curParam = param;
3606                      break;
3607                   }
3608                   if(curParam)
3609                   {
3610                      Class nextClass;
3611                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3612                      {
3613                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
3614                         curParamID += nextClass.templateParams.count;
3615                      }
3616                      lastClass = sClass;
3617                      break;
3618                   }
3619                }
3620                /*
3621                for(sClass = _class; sClass; sClass = sClass.base)
3622                {
3623                   if(sClass.templateParams.first)
3624                   {
3625                      Class nextClass;
3626                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3627                         if(nextClass.templateParams.first)
3628                            break;
3629                      if(nextClass != lastClass) continue;
3630
3631                      curParam = sClass.templateParams.first;
3632                      lastClass = sClass;
3633
3634                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3635                         if(nextClass.templateParams.first)
3636                         {
3637                            curParamID += nextClass.templateParams.count;
3638                            break;
3639                         }
3640                      break;
3641                   }
3642                }
3643                */
3644             }
3645          }
3646
3647          if(curParam)
3648          {
3649             ClassTemplateArgument argument { };
3650             char value[1024];
3651             if(equal)
3652             {
3653                equal++;
3654                while(*equal == ' ') equal++;
3655                memcpy(value, equal, paramEnd - equal);
3656                value[paramEnd - equal] = 0;
3657             }
3658             else
3659             {
3660                memcpy(value, paramStart, paramEnd - paramStart);
3661                value[paramEnd - paramStart] = 0;
3662             }
3663             TrimRSpaces(value, value);
3664
3665             switch(curParam.type)
3666             {
3667                case type:
3668                   argument.dataTypeString = CopyString(value);
3669                   argument.dataTypeClass = eSystem_FindClass(findModule, value);
3670                   if(!argument.dataTypeClass)
3671                      argument.dataTypeClass = eSystem_FindClass(_class.module, value);
3672                   if(!argument.dataTypeClass)
3673                      argument.dataTypeClass = eSystem_FindClass(_class.module.application, value);
3674                   break;
3675                case expression:
3676                {
3677                   Class expClass = eSystem_FindClass(_class.module, curParam.dataTypeString);
3678                   if(!expClass) expClass = eSystem_FindClass(_class.module.application, curParam.dataTypeString);
3679                   if(expClass)
3680                   {
3681                      //if(expClass.type ==
3682                      ((bool (*)(void *, void *, const char *))(void *)expClass._vTbl[__ecereVMethodID_class_OnGetDataFromString])(expClass, &argument.expression, value);
3683                   }
3684                   // Expression should be pre simplified here
3685                   else if(value[0] == '\"')
3686                   {
3687                      char * endQuote = value + strlen(value) - 1;
3688                      if(*endQuote != '\"') endQuote++;
3689                      *endQuote = '\0';
3690                      argument.expression.p = CopyString(value + 1);
3691                   }
3692                   else if(value[0] == '\'')
3693                   {
3694                      int nb;
3695                      unichar ch = UTF8GetChar(value + 1, &nb);
3696                      argument.expression.ui = ch;
3697                   }
3698                   else if(!strcmp(curParam.dataTypeString, "uint"))
3699                   {
3700                      argument.expression.ui = (uint)strtoul(value, null, 0);
3701                   }
3702                   else if(!strcmp(curParam.dataTypeString, "char"))
3703                   {
3704                      argument.expression.c = (char)strtol(value, null, 0);
3705                   }
3706                   else if(!strcmp(curParam.dataTypeString, "byte"))
3707                   {
3708                      argument.expression.uc = (unsigned char)strtoul(value, null, 0);
3709                   }
3710                   else if(!strcmp(curParam.dataTypeString, "short"))
3711                   {
3712                      argument.expression.s = (short)strtol(value, null, 0);
3713                   }
3714                   else if(!strcmp(curParam.dataTypeString, "uint16"))
3715                   {
3716                      argument.expression.us = (unsigned short)strtoul(value, null, 0);
3717                   }
3718                   else if(!strcmp(curParam.dataTypeString, "int64"))
3719                   {
3720                      argument.expression.i64 = _strtoi64(value, null, 0);
3721                   }
3722                   else if(!strcmp(curParam.dataTypeString, "uint64"))
3723                   {
3724                      argument.expression.ui64 = _strtoui64(value, null, 0);
3725                   }
3726                   else if(!strcmp(curParam.dataTypeString, "float"))
3727                   {
3728                      argument.expression.f = (float)strtod(value, null);
3729                   }
3730                   else if(!strcmp(curParam.dataTypeString, "double"))
3731                   {
3732                      argument.expression.d = strtod(value, null);
3733                   }
3734                   else // if(!strcmp(curParam.dataTypeString, "int"))
3735                   {
3736                      argument.expression.i = (int)strtol(value, null, 0);
3737                   }
3738                   break;
3739                }
3740                case identifier:
3741                   argument.memberString = CopyString(value);
3742                   break;
3743             }
3744             FreeTemplateArg(templatedClass, curParam, curParamID);
3745             templatedClass.templateArgs[curParamID] = argument;
3746          }
3747       }
3748    }
3749
3750    // TESTING THIS BEFORE...
3751    if(templatedClass == _class)
3752    {
3753       Class sClass = _class;
3754       int curParamID = 0;
3755       Class nextClass;
3756       ClassTemplateParameter param;
3757       for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3758       {
3759          if(nextClass.templateClass) nextClass = nextClass.templateClass;
3760          curParamID += nextClass.templateParams.count;
3761       }
3762
3763       for(param = sClass.templateParams.first; param; param = param.next)
3764       {
3765          if(!templatedClass.templateArgs[curParamID].dataTypeString)
3766          {
3767             templatedClass.templateArgs[curParamID] = param.defaultArg;
3768             CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3769             if(param.type == type && param.defaultArg.dataTypeString)
3770             {
3771                templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3772                if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3773                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3774                if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3775                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3776             }
3777          }
3778          curParamID++;
3779       }
3780    }
3781
3782    if(templatedClass.base && templatedClass.base.templateArgs && numParams - _class.templateParams.count)
3783    {
3784       int c = numParams - _class.templateParams.count-1;
3785
3786       for(sClass = _class.base; sClass; sClass = sClass.base)
3787       {
3788          ClassTemplateParameter param;
3789          if(sClass.templateClass) sClass = sClass.templateClass;
3790          for(param = sClass.templateParams.last; param; param = param.prev)
3791          {
3792             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3793             ClassTemplateArgument * baseArg = &templatedClass.base.templateArgs[c];
3794             if(!arg->dataTypeString)
3795             {
3796                *arg = templatedClass.base.templateArgs[c];
3797                CopyTemplateArg(param, arg);
3798                if(param.type == type)
3799                {
3800                   if(arg->dataTypeClass && strchr(arg->dataTypeString, '<') && arg->dataTypeClass.templateArgs)
3801                   {
3802                      Class expClass = arg->dataTypeClass;
3803                      Class cClass = null;
3804                      int paramCount = 0;
3805                      int lastParam = -1;
3806
3807                      char templateString[1024];
3808                      sprintf(templateString, "%s<", expClass.templateClass.fullName);
3809                      for(cClass = expClass; cClass; cClass = cClass.base)
3810                      {
3811                         int p = 0;
3812                         ClassTemplateParameter param;
3813                         for(param = cClass.templateParams.first; param; param = param.next)
3814                         {
3815                            int id = p;
3816                            Class sClass;
3817                            ClassTemplateArgument arg;
3818                            for(sClass = expClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
3819                            arg = expClass.templateArgs[id];
3820
3821                            {
3822                               ClassTemplateParameter cParam;
3823                               int p = numParams - _class.templateParams.count;
3824                               for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3825                               {
3826                                  if(cParam.type == type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
3827                                  {
3828                                     arg.dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3829                                     arg.dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3830                                     break;
3831                                  }
3832                               }
3833                            }
3834
3835                            {
3836                               char argument[256];
3837                               argument[0] = '\0';
3838                               switch(param.type)
3839                               {
3840                                  case expression:
3841                                  {
3842                                     // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
3843                                     /*
3844                                     char expString[1024];
3845                                     OldList * specs = MkList();
3846                                     Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
3847                                     Expression exp;
3848                                     char * string = PrintHexUInt64(arg.expression.ui64);
3849                                     exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
3850
3851                                     ProcessExpressionType(exp);
3852                                     ComputeExpression(exp);
3853                                     expString[0] = '\0';
3854                                     PrintExpression(exp, expString);
3855                                     strcat(argument, expString);
3856                                     //delete exp;
3857                                     FreeExpression(exp);
3858                                     */
3859                                     break;
3860                                  }
3861                                  case identifier:
3862                                  {
3863                                     strcat(argument, arg.member.name);
3864                                     break;
3865                                  }
3866                                  case TemplateParameterType::type:
3867                                  {
3868                                     if(arg.dataTypeString)
3869                                        strcat(argument, arg.dataTypeString);
3870                                     break;
3871                                  }
3872                               }
3873                               if(argument[0])
3874                               {
3875                                  if(paramCount) strcat(templateString, ", ");
3876                                  if(lastParam != p - 1)
3877                                  {
3878                                     strcat(templateString, param.name);
3879                                     strcat(templateString, " = ");
3880                                  }
3881                                  strcat(templateString, argument);
3882                                  paramCount++;
3883                                  lastParam = p;
3884                               }
3885                            }
3886                            p++;
3887                         }
3888                      }
3889                      {
3890                         int len = (int)strlen(templateString);
3891                         if(templateString[len-1] == '>') templateString[len++] = ' ';
3892                         templateString[len++] = '>';
3893                         templateString[len++] = '\0';
3894                      }
3895
3896                      FreeTemplateArg(templatedClass, param, c);
3897
3898                      arg->dataTypeString = CopyString(templateString);
3899                      arg->dataTypeClass = eSystem_FindClass(findModule, templateString);
3900                      if(!arg->dataTypeClass)
3901                         arg->dataTypeClass = eSystem_FindClass(templatedClass.module, templateString);
3902                      if(!arg->dataTypeClass)
3903                         arg->dataTypeClass = eSystem_FindClass(templatedClass.module.application, templateString);
3904                   }
3905                   else
3906                   {
3907                      ClassTemplateParameter cParam;
3908                      int p = numParams - _class.templateParams.count;
3909                      for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3910                      {
3911                         // if(cParam.type == type && !strcmp(cParam.name, param.name))
3912                         if(cParam.type == type && baseArg->dataTypeString && !strcmp(cParam.name, baseArg->dataTypeString))
3913                         {
3914                            FreeTemplateArg(templatedClass, param, c);
3915
3916                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3917                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3918                            CopyTemplateArg(cParam, arg);
3919                            break;
3920                         }
3921                      }
3922                   }
3923                }
3924             }
3925             c--;
3926          }
3927       }
3928    }
3929
3930    {
3931       Class sClass;
3932       for(sClass = _class; sClass; sClass = sClass.base)
3933       {
3934          int curParamID = 0;
3935          Class nextClass;
3936          ClassTemplateParameter param;
3937          if(sClass.templateClass) sClass = sClass.templateClass;
3938
3939          for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3940          {
3941             if(nextClass.templateClass) nextClass = nextClass.templateClass;
3942             curParamID += nextClass.templateParams.count;
3943          }
3944
3945          for(param = sClass.templateParams.first; param; param = param.next)
3946          {
3947             if(!templatedClass.templateArgs[curParamID].dataTypeString)
3948             {
3949                templatedClass.templateArgs[curParamID] = param.defaultArg;
3950                CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3951                if(param.type == type && param.defaultArg.dataTypeString)
3952                {
3953                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3954                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3955                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3956                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3957                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3958                }
3959             }
3960             curParamID++;
3961          }
3962       }
3963    }
3964
3965    {
3966       int c = numParams - 1;
3967       for(sClass = _class; sClass; sClass = sClass.base)
3968       {
3969          ClassTemplateParameter param;
3970          if(sClass.templateClass) sClass = sClass.templateClass;
3971          for(param = sClass.templateParams.last; param; param = param.prev)
3972          {
3973             if(param.type == type)
3974             {
3975                ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3976                ClassTemplateParameter cParam;
3977                Class dClass;
3978                int p = numParams - 1;
3979                for(dClass = _class; dClass; dClass = dClass.base)
3980                {
3981                   if(dClass.templateClass) dClass = dClass.templateClass;
3982                   for(cParam = dClass.templateParams.last; cParam; cParam = cParam.prev, p--)
3983                   {
3984                      if(cParam.type == type && arg->dataTypeString && !strcmp(cParam.name, arg->dataTypeString))
3985                      {
3986                         if(templatedClass.templateArgs[p].dataTypeString && c != p)
3987                         {
3988                            FreeTemplateArg(templatedClass, param, c);
3989
3990                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3991                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3992                            CopyTemplateArg(cParam, arg);
3993                         }
3994                      }
3995                   }
3996                }
3997             }
3998             c--;
3999          }
4000       }
4001    }
4002
4003    {
4004       Class tClass;
4005       int c = numParams - 1;
4006       for(tClass = _class; tClass; tClass = tClass.base)
4007       {
4008          ClassTemplateParameter param;
4009          if(tClass.templateClass) tClass = tClass.templateClass;
4010          for(param = tClass.templateParams.last; param; param = param.prev)
4011          {
4012             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
4013             if(param.type == identifier && arg->memberString)
4014             {
4015                Class memberClass = templatedClass;
4016                const char * memberString = arg->memberString;
4017                const char * colon = strstr(memberString, "::");
4018                const char * memberName = memberString;
4019                if(colon) memberName = colon + 2;
4020                if(!colon)
4021                {
4022                   memberString = param.defaultArg.memberString;
4023                   colon = memberString ? strstr(memberString, "::") : null;
4024                }
4025
4026                if(colon)
4027                {
4028                   char className[1024];
4029                   Class sClass;
4030
4031                   memcpy(className, memberString, colon - memberString);
4032                   className[colon - memberString] = '\0';
4033
4034                   for(sClass = _class; sClass; sClass = sClass.base)
4035                   {
4036                      ClassTemplateParameter cParam;
4037                      Class nextClass;
4038                      int id = 0;
4039
4040                      if(sClass.templateClass) sClass = sClass.templateClass;
4041                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
4042                      {
4043                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
4044                         id += nextClass.templateParams.count;
4045                      }
4046                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
4047                      {
4048                         if(cParam.type == type && !strcmp(cParam.name, className) && templatedClass.templateArgs[id].dataTypeString)
4049                         {
4050                            strcpy(className, templatedClass.templateArgs[id].dataTypeString);
4051                         }
4052                         id++;
4053                      }
4054                   }
4055                   // TESTING: Added this here...
4056                   memberClass = eSystem_FindClass(findModule, className);
4057                   if(!memberClass)
4058                      memberClass = eSystem_FindClass(templatedClass.module, className);
4059                   if(!memberClass)
4060                      memberClass = eSystem_FindClass(templatedClass.module.application, className);
4061                }
4062
4063                if(memberClass)
4064                {
4065                   switch(param.memberType)
4066                   {
4067                      case dataMember:
4068                         arg->member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
4069                         break;
4070                      case method:
4071                         arg->method = eClass_FindMethod(memberClass, memberName, memberClass.module);
4072                         break;
4073                      case prop:
4074                         arg->prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
4075                         break;
4076                   }
4077                }
4078             }
4079             c--;
4080          }
4081       }
4082    }
4083 }
4084
4085 /*static */bool DefaultFunction()
4086 {
4087    return true;
4088 }
4089
4090 public dllexport bool eClass_IsDerived(Class _class, Class from)
4091 {
4092    if(!_class && !from)
4093       return true;
4094
4095    if(_class && from && (_class.templateClass || from.templateClass))
4096    {
4097       if(eClass_IsDerived(_class.templateClass ? _class.templateClass : _class, from.templateClass ? from.templateClass : from))
4098       {
4099          if(!from.templateClass)
4100             return true;
4101          else if(!_class.templateClass && _class == from.templateClass)
4102             return false;
4103          else
4104          {
4105             Class sClass;
4106             for(sClass = from; sClass; sClass = sClass.base)
4107             {
4108                if(sClass.templateParams.first)
4109                {
4110                   ClassTemplateParameter param;
4111                   Class nextClass;
4112                   int p = 0;
4113                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;
4114                   for(param = sClass.templateParams.first; param; param = param.next, p++)
4115                   {
4116                      ClassTemplateArgument * arg = &_class.templateArgs[p];
4117                      ClassTemplateArgument * fArg = &from.templateArgs[p];
4118                      if(param.type == type)
4119                      {
4120                         if(arg->dataTypeString != fArg->dataTypeString && arg->dataTypeString && fArg->dataTypeString &&
4121                           strcmp(arg->dataTypeString, fArg->dataTypeString))
4122                            break;
4123                      }
4124                      else if(param.type == identifier)
4125                      {
4126                         if(arg->member != fArg->member)
4127                            break;
4128                      }
4129                      else if(param.type == expression)
4130                      {
4131                         if(arg->expression.ui64 != fArg->expression.ui64)
4132                            break;
4133                      }
4134                   }
4135                   if(param)
4136                      return false;
4137                }
4138             }
4139             return true;
4140          }
4141       }
4142    }
4143    else
4144    {
4145       for(; _class && from; _class = _class.base)
4146       {
4147          if(_class == from || _class.templateClass == from || ((_class.type == systemClass || (_class.type == normalClass && _class.isInstanceClass)) && from.name && !strcmp(_class.name, from.name)))
4148             return true;
4149       }
4150    }
4151    return false;
4152 }
4153
4154 static void FixDerivativeVirtualMethod(Class base, const char * name, int vid, void * origFunction, const char * type)
4155 {
4156    OldLink derivative;
4157    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
4158    {
4159       Class _class = derivative.data;
4160       Method method, next;
4161       void * function = origFunction;
4162
4163       _class.vTblSize++;
4164       _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
4165       memmove(_class._vTbl + vid + 1, _class._vTbl + vid, (_class.vTblSize - vid - 1) * sizeof(void *));
4166
4167       method = (Method) _class.methods.FindString(name);
4168       if(method)
4169       {
4170          if(method.function) function = method.function;
4171
4172          if(!method.symbol)
4173          {
4174             delete (void *)method.name;
4175             delete (void *)method.dataTypeString;
4176             _class.methods.Delete((BTNode)method);
4177          }
4178          else
4179          {
4180             delete (void *)method.dataTypeString;
4181             method.type = virtualMethod;
4182             method.dataTypeString = CopyString(type);
4183             method._class = base;
4184          }
4185       }
4186       for(method = (Method)_class.methods.first; method; method = next)
4187       {
4188          next = (Method)((BTNode)method).next;
4189          if(method.type == virtualMethod)
4190             method.vid++;
4191       }
4192       _class._vTbl[vid] = function;
4193
4194       {
4195          OldLink templateLink;
4196          for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4197          {
4198             Class template = templateLink.data;
4199             template._vTbl = _class._vTbl;
4200          }
4201       }
4202       if(_class.derivatives.first || _class.templatized.first)
4203          FixDerivativeVirtualMethod(_class, name, vid, function, type);
4204    }
4205    {
4206       OldLink templateLink;
4207       for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
4208       {
4209          Class template = templateLink.data;
4210          template._vTbl = base._vTbl;
4211          FixDerivativeVirtualMethod(template, name, vid, origFunction, type);
4212       }
4213    }
4214 }
4215
4216 public dllexport Method eClass_AddMethod(Class _class, const char * name, const char * type, void * function, AccessMode declMode)
4217 {
4218    if(_class && !_class.comRedefinition && name)
4219    {
4220       Class base;
4221       for(base = _class; base; base = base.base)
4222       {
4223          Method method;
4224          if(base.templateClass) base = base.templateClass;
4225          method = (Method)base.methods.FindString(name);
4226          if(method)
4227          {
4228             // If this overrides a virtual method
4229             if(method.type == virtualMethod)
4230             {
4231                OldLink deriv;
4232                void * oldFunction = _class._vTbl[method.vid];
4233                if(method.vid >= _class.vTblSize)
4234                   printf("error: virtual methods overriding failure\n");
4235                else
4236                   _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
4237                for(deriv = _class.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                   OldLink templateLink;
4245                   for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4246                   {
4247                      Class template = templateLink.data;
4248                      for(deriv = template.derivatives.first; deriv; deriv = deriv.next)
4249                      {
4250                         Class derivClass = deriv.data;
4251                         if(derivClass._vTbl[method.vid] == oldFunction)
4252                            eClass_AddMethod(derivClass, name, type, function, declMode);
4253                      }
4254                   }
4255                }
4256
4257             }
4258             else
4259             {
4260                if(base == _class)
4261                {
4262                   // printf("error: Redefinition of method %s in class %s\n", name, _class.name);
4263                   break;
4264                }
4265                base = null;
4266                break;
4267             }
4268             return method;
4269          }
4270       }
4271
4272       if(!base)
4273       {
4274          Method method
4275          {
4276             name = CopyString(name),
4277             function = function ? function : null; //DefaultFunction;
4278             _class = _class;
4279             dataTypeString = CopyString(type);
4280             memberAccess = declMode;
4281          };
4282          _class.methods.Add((BTNode)method);
4283          return method;
4284       }
4285    }
4286    return null;
4287 }
4288
4289 public dllexport Method eClass_AddVirtualMethod(Class _class, const char * name, const char * type, void * function, AccessMode declMode)
4290 {
4291    if(_class && !_class.comRedefinition && name)
4292    {
4293       Class base;
4294       for(base = _class; base; base = base.base)
4295       {
4296          Method method = (Method)base.methods.FindString(name);
4297          if(method)
4298          {
4299             // If this overides a virtual method
4300             if(method.type == virtualMethod)
4301             {
4302                if(method.vid >= _class.vTblSize)
4303                   printf("error: virtual methods overriding failure\n");
4304                else
4305                   _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
4306             }
4307             else
4308                base = null;
4309             return method;
4310          }
4311       }
4312
4313       if(!base)
4314       {
4315          Method method
4316          {
4317             name = CopyString(name);
4318             function = function ? function : null; //DefaultFunction;
4319             type = virtualMethod;
4320             _class = _class;
4321             vid = _class.vTblSize++;
4322             dataTypeString = CopyString(type);
4323             memberAccess = declMode;
4324          };
4325          _class.methods.Add((BTNode)method);
4326          _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
4327          _class._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
4328
4329          // TODO: Fix derived classes
4330          if(_class.derivatives.first || _class.templatized.first)
4331             FixDerivativeVirtualMethod(_class, name, method.vid, function ? function : null /*(void *)DefaultFunction*/, type);
4332          return method;
4333       }
4334    }
4335    return null;
4336 }
4337
4338 static void FixDerivativeProperty(Class base, Property _property)
4339 {
4340    OldLink derivative;
4341    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
4342    {
4343       Class _class = derivative.data;
4344       Property prop;
4345       BTNamedLink link = (BTNamedLink)_class.prop.FindString(_property.name);
4346       if(link)
4347       {
4348          prop = link.data;
4349          if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
4350          {
4351             SelfWatcher watcher;
4352             for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
4353             {
4354                if(watcher._property == prop)
4355                   watcher._property = _property;
4356             }
4357             _property.selfWatchable = true;
4358
4359             delete (void *)prop.name;
4360             delete (void *)prop.dataTypeString;
4361             _class.membersAndProperties.Delete(prop);
4362             _class.prop.Delete((BTNode)link);
4363          }
4364       }
4365
4366       for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
4367          prop.id++;
4368       _class.memberID++;
4369       _class.startMemberID++;
4370
4371       FixDerivativeProperty(_class, _property);
4372    }
4373 }
4374
4375 public dllexport Property eClass_AddProperty(Class _class, const char * name, const char * dataType, void * setStmt, void * getStmt, AccessMode declMode)
4376 {
4377    Property _property = null;
4378    if(_class)
4379    {
4380       BTNamedLink link = (BTNamedLink)_class.prop.FindString(name ? name : dataType);
4381       bool isConversion = name ? false : true;
4382       if(!name && dataType && !strncmp(dataType, "const ", 6))
4383       {
4384          name = dataType + 6;
4385          isConversion = true;
4386       }
4387       if(link)
4388          _property = link.data;
4389       if(!_property)
4390       {
4391          _property =
4392          {
4393             isProperty = true;
4394             name = CopyString(name ? name : dataType);
4395             id = (name && (setStmt || getStmt || dataType)) ? _class.memberID++ : 0;
4396             Set = setStmt;
4397             Get = getStmt;
4398             dataTypeString = CopyString(dataType);
4399             _class = _class;
4400             compiled = true;
4401             conversion = isConversion;
4402             memberAccess = declMode;
4403          };
4404          if(!isConversion)
4405             _class.membersAndProperties.Add(_property);
4406          else
4407             _class.conversions.Add(_property);
4408          _class.prop.Add((BTNode)BTNamedLink { name = _property.name, data = _property });
4409
4410          if(!_property.conversion)
4411          {
4412             FixDerivativeProperty(_class, _property);
4413          }
4414       }
4415    }
4416    return _property;
4417 }
4418
4419 static void SetDelayedCPValues(Class _class, ClassProperty _property)
4420 {
4421    OldLink deriv;
4422    NamedLink64 value, next;
4423
4424    for(value = _class.delayedCPValues.first; value; value = next)
4425    {
4426       next = value.next;
4427       if(!strcmp(value.name, _property.name))
4428       {
4429          // eClass_SetProperty(_class, _property.name, value.data);
4430          _property.Set(_class, value.data);
4431          _class.delayedCPValues.Delete(value);
4432       }
4433    }
4434
4435    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4436    {
4437       SetDelayedCPValues(deriv.data, _property);
4438    }
4439 }
4440
4441 public dllexport ClassProperty eClass_AddClassProperty(Class _class, const char * name, const char * dataType, void * setStmt, void * getStmt)
4442 {
4443    if(name && !_class.classProperties.FindString(name))
4444    {
4445       ClassProperty _property
4446       {
4447          name = CopyString(name);
4448          Set = setStmt;
4449          Get = getStmt;
4450          dataTypeString = CopyString(dataType);
4451       };
4452       _class.classProperties.Add((BTNode)_property);
4453       SetDelayedCPValues(_class, _property);
4454       return _property;
4455    }
4456    return null;
4457 }
4458
4459 /*import "Time"
4460
4461 Time classFindTotalTime;
4462
4463 public dllexport void ResetClassFindTime()
4464 {
4465    classFindTotalTime = 0;
4466 }
4467
4468 public dllexport Time GetClassFindTime()
4469 {
4470    return classFindTotalTime;
4471 }
4472 */
4473 public dllexport ClassProperty eClass_FindClassProperty(Class _class, const char * name)
4474 {
4475    //Time startTime = GetTime();
4476    ClassProperty _property = null;
4477    if(name && _class)
4478    {
4479       Class origClass = _class;
4480       for(; _class; _class = _class.base)
4481       {
4482          _property = (ClassProperty)_class.classProperties.FindString(name);
4483          if(_property)
4484             break;
4485       }
4486       // For enum class deriving off something else than enum to find enumSize...
4487       if(!_property && origClass.type == enumClass)
4488       {
4489          Class enumClass = eSystem_FindClass(origClass.module, "enum");
4490          _property = eClass_FindClassProperty(enumClass, name);
4491       }
4492    }
4493    /*if(!_property)
4494       eSystem_Logf("No such property (%s) for class %s\n", name, _class.name);*/
4495    //classFindTotalTime += GetTime() - startTime;
4496    return _property;
4497 }
4498
4499 public dllexport int64 eClass_GetProperty(Class _class, const char * name)
4500 {
4501    ClassProperty _property = eClass_FindClassProperty(_class, name);
4502    if(_property && _property.Get && _property.Get != (void *)1)
4503    {
4504       int64 result = _property.Get(_class);
4505       return result;
4506    }
4507    return 0;
4508 }
4509
4510 public dllexport void eClass_SetProperty(Class _class, const char * name, int64 value)
4511 {
4512    ClassProperty _property = eClass_FindClassProperty(_class, name);
4513    if(_property)
4514    {
4515       if(_property.Set)
4516          ((void(*)(void *, int64))_property.Set)(_class, value);
4517    }
4518    else
4519    {
4520       _class.delayedCPValues.Add(NamedLink64 { name = (char *)name, value });
4521    }
4522 }
4523
4524 public dllexport Method eClass_FindMethod(Class _class, const char * name, Module module)
4525 {
4526    //Time startTime = GetTime();
4527    if(_class && name)
4528    {
4529       for(; _class; _class = _class.base)
4530       {
4531          Method method;
4532          if(_class.templateClass) _class = _class.templateClass;
4533          method = (Method)_class.methods.FindString(name);
4534          if(method && (method.memberAccess == publicAccess || _class.module == module || !method.dataTypeString))
4535          {
4536             if(!method.dataTypeString)
4537             {
4538                if(_class.module != module)
4539                {
4540                   if(method.memberAccess == publicAccess)
4541                      module = _class.module;
4542                   else
4543                   {
4544                      //classFindTotalTime += GetTime() - startTime;
4545                      return null;
4546                   }
4547                }
4548             }
4549             else
4550             {
4551                //classFindTotalTime += GetTime() - startTime;
4552                return method;
4553             }
4554          }
4555          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4556       }
4557    }
4558    //classFindTotalTime += GetTime() - startTime;
4559    return null;
4560 }
4561
4562 // Construct an instance
4563 static bool ConstructInstance(void * instance, Class _class, Class from)
4564 {
4565    if(_class.templateClass) _class = _class.templateClass;
4566    if(_class.base && from != _class.base)
4567    {
4568       if(!ConstructInstance(instance, _class.base, from))
4569          return false;
4570    }
4571    if(_class.Initialize)
4572    {
4573       void (* Initialize)(Module module) = (void *)_class.Initialize;
4574       _class.Initialize = null;
4575       Initialize(_class.module);
4576    }
4577    if(_class.Constructor)
4578    {
4579       if(!_class.Constructor(instance))
4580       {
4581          for(; _class; _class = _class.base)
4582          {
4583             if(_class.templateClass) _class = _class.templateClass;
4584             if(_class.Destructor)
4585                _class.Destructor(instance);
4586          }
4587          return false;
4588       }
4589    }
4590    (_class.templateClass ? _class.templateClass : _class).count++;
4591    return true;
4592 }
4593
4594 public dllexport void * eInstance_New(Class _class)
4595 {
4596    Instance instance = null;
4597    if(_class)
4598    {
4599       // instance = _malloc(_class.size);
4600 #ifdef MEMINFO
4601
4602 #undef malloc
4603    memMutex.Wait();
4604       //allocateClass = _class;
4605       allocateClass = malloc(strlen(_class.name)+1);
4606       allocateInternal = _class.module == __thisModule;
4607       strcpy(allocateClass, _class.name);
4608 #ifndef MEMINFO
4609 #define malloc _mymalloc
4610 #endif
4611
4612 #endif
4613       {
4614          int size = _class.structSize;
4615          int flags = _class.module.application.isGUIApp;
4616          bool inCompiler = (flags & 8) ? true : false;
4617          bool force32Bits = (flags & 4) ? true : false;
4618          if(force32Bits && inCompiler)
4619          {
4620             // Allocate 64 bit sizes for these when cross-compiling for 32 bit to allow loaded libraries to work properly
4621             if(!strcmp(_class.name, "Module"))
4622                size = 560;
4623             else if(_class.templateClass && !strcmp(_class.templateClass.name, "Map"))
4624                size = 40;
4625             else
4626                size *= 3;
4627          }
4628          instance = _calloc(1, size);
4629       }
4630 #ifdef MEMINFO
4631       allocateClass = null;
4632    memMutex.Release();
4633 #endif
4634
4635 #if !defined(MEMINFO) && defined(MEMTRACKING)
4636       {
4637          MemBlock block = (MemBlock)((byte *)instance - sizeof(class MemBlock));
4638          block._class = _class;
4639       }
4640 #endif
4641
4642       if(_class.type == normalClass)
4643       {
4644          instance._class = _class;
4645          // Copy the virtual table initially
4646          instance._vTbl = _class._vTbl;
4647       }
4648       if(!ConstructInstance(instance, _class, null))
4649       {
4650          _free(instance);
4651          instance = null;
4652       }
4653       /*if(_class.type == normalClass && _class.count > 1000)
4654          printf("%s: %d instances\n", _class.name, _class.count);*/
4655    }
4656    return instance;
4657 }
4658
4659 public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
4660 {
4661    if(_class && instancePtr && *instancePtr)
4662    {
4663       bool wasApp = false, wasGuiApp = false;
4664       Instance oldInstance = *instancePtr;
4665       Instance instance = (Instance)renew *instancePtr byte[_class.structSize];
4666       Class fromClass = instance._class;
4667       *instancePtr = instance;
4668       memset(((byte *)instance) + instance._class.structSize, 0, _class.structSize - instance._class.structSize);
4669       // Fix pointers to application
4670       if((wasApp = !strcmp(instance._class.name, "Application")) ||
4671          (wasGuiApp = !strcmp(instance._class.name, "GuiApplication")))
4672       {
4673          Module module;
4674          Application app = (Application) instance;
4675          BTNamedLink link;
4676          Class _class;
4677          NameSpace * nameSpace;
4678          for(module = app.allModules.first; module; module = module.next)
4679             module.application = app;
4680
4681          for(link = (BTNamedLink)app.privateNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4682          {
4683             OldLink t;
4684             ((Class)link.data).nameSpace = &app.privateNameSpace;
4685             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4686          }
4687          for(link = (BTNamedLink)app.publicNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4688          {
4689             OldLink t;
4690             ((Class)link.data).nameSpace = &app.publicNameSpace;
4691             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4692          }
4693
4694          for(link = (BTNamedLink)app.privateNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4695             ((DefinedExpression)link.data).nameSpace = &app.privateNameSpace;
4696          for(link = (BTNamedLink)app.publicNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4697             ((DefinedExpression)link.data).nameSpace = &app.publicNameSpace;
4698
4699          for(link = (BTNamedLink)app.privateNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4700             ((GlobalFunction)link.data).nameSpace = &app.privateNameSpace;
4701          for(link = (BTNamedLink)app.publicNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4702             ((GlobalFunction)link.data).nameSpace = &app.publicNameSpace;
4703
4704          for(nameSpace = (NameSpace *)app.privateNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4705             nameSpace->parent = &app.privateNameSpace;
4706          for(nameSpace = (NameSpace *)app.publicNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4707             nameSpace->parent = &app.publicNameSpace;
4708
4709          // --------------------------------------------------
4710          for(link = (BTNamedLink)app.systemNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4711          {
4712             OldLink t;
4713             ((Class)link.data).nameSpace = &app.systemNameSpace;
4714             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4715          }
4716          for(link = (BTNamedLink)app.systemNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4717             ((DefinedExpression)link.data).nameSpace = &app.systemNameSpace;
4718          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4719             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4720          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4721             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4722          for(nameSpace = (NameSpace *)app.systemNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4723             nameSpace->parent = &app.systemNameSpace;
4724          // --------------------------------------------------
4725
4726          for(_class = app.classes.first; _class; _class = _class.next)
4727          {
4728             OldLink templateLink;
4729             _class.module = (Module) app;
4730             for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4731             {
4732                Class template = templateLink.data;
4733                if(template.module == oldInstance)
4734                   template.module = _class.module;
4735             }
4736          }
4737
4738          for(module = app.allModules.first; module; module = module.next)
4739          {
4740             for(_class = module.classes.first; _class; _class = _class.next)
4741             {
4742                OldLink templateLink;
4743                Module oldModule = _class.module;
4744                _class.module = module;
4745                for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4746                {
4747                   Class template = templateLink.data;
4748                   if(template.module == oldModule)
4749                      template.module = _class.module;
4750                }
4751             }
4752          }
4753
4754          app.application = app;
4755       }
4756
4757       {
4758          Class base;
4759          for(base = instance._class; base && base.type == normalClass && base.count; base = base.base)
4760             (base.templateClass ? base.templateClass : base).count--;
4761       }
4762
4763       instance._class = _class;
4764       // Copy the virtual table initially
4765       instance._vTbl = _class._vTbl;
4766
4767       // We don't want to reconstruct the portion already constructed...
4768       if(!ConstructInstance(instance, _class, fromClass))
4769       {
4770          _free(instance);
4771          *instancePtr = null;
4772       }
4773    }
4774 }
4775
4776 public dllexport void eInstance_Delete(Instance instance)
4777 {
4778 #ifdef MEMINFO
4779    bool checkMemory = false;
4780 #endif
4781    if(instance)
4782    {
4783       Class _class, base;
4784       bool ownVtbl;
4785
4786 #ifdef MEMINFO
4787 #if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
4788       if(instance._class == (void *)0xecececececececec)
4789 #else
4790       if(instance._class == (void *)0xecececec)
4791 #endif
4792          _free(instance);
4793 #endif
4794
4795       ownVtbl = instance._vTbl != instance._class._vTbl;
4796
4797       for(_class = instance._class; _class; _class = base)
4798       {
4799          if(_class.templateClass) _class = _class.templateClass;
4800          if(_class.destructionWatchOffset)
4801          {
4802             OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
4803             Watcher watcher, next;
4804
4805             for(watcher = watchers->first; watcher; watcher = next)
4806             {
4807                next = watcher.next;
4808                watchers->Remove(watcher);
4809                watcher.callback(watcher.object, instance);
4810                watchers->Delete(watcher);
4811             }
4812          }
4813
4814          /*// Loop through properties to delete all watchers? Might slow down destruction...
4815          {
4816             Property _property;
4817             for(_property = _class.membersAndProperties.first; _property; _property = _property.next)
4818             {
4819                if(_property.isProperty && _property.isWatchable)
4820                {
4821                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
4822                   Watcher watcher, next;
4823                   for(watcher = watchers->first; watcher; watcher = next)
4824                   {
4825                      next = watcher.next;
4826                      watchers->Delete(watcher);
4827                   }
4828                }
4829             }
4830          }*/
4831
4832
4833          base = _class.base;
4834          if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
4835          if(_class.Destructor)
4836             _class.Destructor(instance);
4837 #ifdef MEMINFO
4838          if(_class == class(Application))
4839             checkMemory = true;
4840 #endif
4841       }
4842
4843       for(_class = instance._class; _class; _class = base)
4844       {
4845          if(_class.templateClass) _class = _class.templateClass;
4846
4847          base = _class.base;
4848          (_class.templateClass ? _class.templateClass : _class).count--;
4849          if(_class.type == normalClass && !_class.count && !_class.module)
4850          {
4851 #ifdef MEMINFO
4852             // printf("Now Destructing class %s\n", _class.name);
4853 #endif
4854             eClass_Unregister(_class);
4855          }
4856       }
4857
4858       if(ownVtbl)
4859       {
4860          delete instance._vTbl;
4861       }
4862       //instance.prop.Free(null);
4863       _free(instance);
4864 #ifdef MEMINFO
4865       if(checkMemory) CheckMemory();
4866 #endif
4867    }
4868 }
4869
4870 public dllexport Property eClass_FindProperty(Class _class, const char * name, Module module)
4871 {
4872    //Time startTime = GetTime();
4873    if(_class && name)
4874    {
4875       if(!strncmp(name, "const ", 6))
4876          name += 6;
4877
4878       for(; _class; _class = _class.base)
4879       {
4880          BTNamedLink link;
4881          if(_class.templateClass) _class = _class.templateClass;
4882          link = (BTNamedLink)_class.prop.FindString(name);
4883          if(link)
4884          {
4885             Property _property = (Property)link.data;
4886             if(_property.memberAccess == publicAccess || _class.module == module || !_property.dataTypeString)
4887             {
4888                if(!_property.dataTypeString)
4889                {
4890                   if(_class.module != module)
4891                   {
4892                      if(_property.memberAccess == publicAccess)
4893                         module = _class.module;
4894                      else
4895                      {
4896                         //classFindTotalTime += GetTime() - startTime;
4897                         return null;
4898                      }
4899                   }
4900                }
4901                else
4902                {
4903                   //classFindTotalTime += GetTime() - startTime;
4904                   return _property;
4905                }
4906             }
4907          }
4908          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4909       }
4910    }
4911    //classFindTotalTime += GetTime() - startTime;
4912    return null;
4913 }
4914
4915 static DataMember FindDataMember(OldList list, BinaryTree alist, const char * name, uint * offset, int * id, bool searchPrivate, DataMember * subMemberStack, int * subMemberStackPos)
4916 {
4917    BTNamedLink link;
4918    DataMember dataMember;
4919
4920    link = (BTNamedLink)alist.FindString(name);
4921    if(link)
4922    {
4923       dataMember = link.data;
4924       if(dataMember.type == normalMember && (dataMember.memberAccess == publicAccess || searchPrivate || !dataMember.dataTypeString))
4925       {
4926          if(offset)
4927             *offset += dataMember.offset;
4928          if(id) *id = dataMember.id;
4929          return dataMember;
4930       }
4931       return null;
4932    }
4933    for(dataMember = list.first; dataMember; dataMember = dataMember.next)
4934    {
4935       if(!dataMember.isProperty && (dataMember.memberAccess == publicAccess || searchPrivate) && !dataMember.name && (dataMember.type == unionMember || dataMember.type == structMember))
4936       {
4937          DataMember childMember;
4938          if(subMemberStackPos) subMemberStack[(*subMemberStackPos)++] = dataMember;
4939          childMember = FindDataMember(dataMember.members, dataMember.membersAlpha, name, offset, id, searchPrivate, subMemberStack, subMemberStackPos);
4940          if(childMember)
4941          {
4942             if(offset)
4943                *offset += dataMember.offset;
4944             if(id) *id += dataMember.id;
4945             return childMember;
4946          }
4947          if(subMemberStackPos) (*subMemberStackPos)--;
4948       }
4949    }
4950    return null;
4951 }
4952
4953 public dllexport DataMember eClass_FindDataMember(Class _class, const char * name, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4954 {
4955    //Time startTime = GetTime();
4956    DataMember dataMember = null;
4957    if(subMemberStackPos) *subMemberStackPos = 0;
4958    if(_class && name)
4959    {
4960       for(; _class; _class = _class.base)
4961       {
4962          if(_class.templateClass) _class = _class.templateClass;
4963          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, null, _class.module == module, subMemberStack, subMemberStackPos);
4964          if(dataMember)
4965          {
4966             if(!dataMember.dataTypeString)
4967             {
4968                if(_class.module != module)
4969                {
4970                   if(dataMember.memberAccess == publicAccess)
4971                      module = _class.module;
4972                   else
4973                   {
4974                      //classFindTotalTime += GetTime() - startTime;
4975                      return null;
4976                   }
4977                }
4978                dataMember = null;
4979             }
4980             else
4981             {
4982                // HACK: Is this good enough? avoiding setting it when adding...
4983                dataMember._class = _class.templateClass ? _class.templateClass : _class;
4984                //classFindTotalTime += GetTime() - startTime;
4985                return dataMember;
4986             }
4987          }
4988          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4989       }
4990    }
4991    //classFindTotalTime += GetTime() - startTime;
4992    return dataMember;
4993 }
4994
4995 public dllexport DataMember eClass_FindDataMemberAndOffset(Class _class, const char * name, uint * offset, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4996 {
4997    //Time startTime = GetTime();
4998    DataMember dataMember = null;
4999    if(subMemberStackPos) *subMemberStackPos = 0;
5000    if(offset) *offset = 0;
5001    if(_class)
5002    {
5003       for(; _class; _class = _class.base)
5004       {
5005          if(_class.templateClass) _class = _class.templateClass;
5006          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, offset, null, _class.module == module, subMemberStack, subMemberStackPos);
5007          if(dataMember)
5008          {
5009             if(!dataMember.dataTypeString)
5010             {
5011                if(_class.module != module)
5012                {
5013                   if(dataMember.memberAccess == publicAccess)
5014                      module = _class.module;
5015                   else
5016                   {
5017                      //classFindTotalTime += GetTime() - startTime;
5018                      return null;
5019                   }
5020                }
5021                dataMember = null;
5022             }
5023             else
5024             {
5025                // HACK: Is this good enouh? avoiding setting it when adding...
5026                dataMember._class = _class;
5027                //classFindTotalTime += GetTime() - startTime;
5028                return dataMember;
5029             }
5030          }
5031          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
5032       }
5033    }
5034    //classFindTotalTime += GetTime() - startTime;
5035    return dataMember;
5036 }
5037
5038 public dllexport DataMember eClass_FindDataMemberAndId(Class _class, const char * name, int * id, Module module, DataMember * subMemberStack, int * subMemberStackPos)
5039 {
5040    //Time startTime = GetTime();
5041    DataMember dataMember = null;
5042    if(subMemberStackPos) *subMemberStackPos = 0;
5043    if(_class)
5044    {
5045       for(; _class; _class = _class.base)
5046       {
5047          if(_class.templateClass) _class = _class.templateClass;
5048          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, id, _class.module == module, subMemberStack, subMemberStackPos);  // TOCHECK: Why was this null? null, null);
5049          if(dataMember)
5050          {
5051             if(!dataMember.dataTypeString)
5052             {
5053                if(_class.module != module)
5054                {
5055                   if(dataMember.memberAccess == publicAccess)
5056                      module = _class.module;
5057                   else
5058                   {
5059                      //classFindTotalTime += GetTime() - startTime;
5060                      return null;
5061                   }
5062                }
5063                dataMember = null;
5064             }
5065             else
5066             {
5067                // HACK: Is this good enouh? avoiding setting it when adding...
5068                dataMember._class = _class;
5069                //classFindTotalTime += GetTime() - startTime;
5070                return dataMember;
5071             }
5072          }
5073          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
5074       }
5075    }
5076    //classFindTotalTime += GetTime() - startTime;
5077    return dataMember;
5078 }
5079
5080 public dllexport void eClass_FindNextMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
5081 {
5082    // THIS CODE WILL FIND NEXT MEMBER... (PUBLIC MEMBERS ONLY)
5083    if(*curMember)
5084    {
5085       *curMember = (*curMember).next;
5086
5087       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
5088       {
5089          *curMember = subMemberStack[--(*subMemberStackPos)];
5090          *curMember = (*curMember).next;
5091       }
5092
5093       if(subMemberStackPos && *subMemberStackPos > 0)
5094       {
5095          while(*curMember && ((*curMember).memberAccess == privateAccess))
5096             *curMember = (*curMember).next;
5097       }
5098       else
5099          while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
5100          {
5101             DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
5102             if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
5103             if(dataMember && dataMember.memberAccess != privateAccess)
5104             {
5105                *curMember = dataMember;
5106                break;
5107             }
5108             else
5109                *curMember = (*curMember).next;
5110          }
5111
5112       if(subMemberStackPos)
5113       {
5114          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
5115          {
5116             subMemberStack[(*subMemberStackPos)++] = *curMember;
5117
5118             *curMember = (*curMember).members.first;
5119             while(*curMember && ((*curMember).memberAccess == privateAccess))
5120                *curMember = (*curMember).next;
5121          }
5122       }
5123    }
5124    while(!*curMember)
5125    {
5126       if(!*curMember)
5127       {
5128          if(subMemberStackPos && *subMemberStackPos)
5129          {
5130             *curMember = subMemberStack[--(*subMemberStackPos)];
5131             *curMember = (*curMember).next;
5132          }
5133          else
5134          {
5135             Class lastCurClass = *curClass;
5136
5137             if(*curClass == _class) break;     // REACHED THE END
5138
5139             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass && (*curClass).inheritanceAccess != privateAccess; *curClass = (*curClass).base);
5140             *curMember = (*curClass).membersAndProperties.first;
5141          }
5142
5143          if(subMemberStackPos && *subMemberStackPos > 0)
5144          {
5145             while(*curMember && ((*curMember).memberAccess == privateAccess))
5146                *curMember = (*curMember).next;
5147          }
5148          else
5149             while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
5150             {
5151                DataMember dataMember = null;
5152                if(((*curMember).memberAccess != privateAccess))
5153                {
5154                   dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
5155                   if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
5156                }
5157                if(dataMember && dataMember.memberAccess != privateAccess && dataMember.id >= 0) // Skip _vTbl, _refCount and _class in Instance
5158                {
5159                   *curMember = dataMember;
5160                   break;
5161                }
5162                else
5163                   *curMember = (*curMember).next;
5164             }
5165
5166          if(subMemberStackPos)
5167          {
5168             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
5169             {
5170                subMemberStack[(*subMemberStackPos)++] = *curMember;
5171
5172                *curMember = (*curMember).members.first;
5173                while(*curMember && (*curMember).memberAccess == privateAccess)
5174                   *curMember = (*curMember).next;
5175             }
5176          }
5177       }
5178    }
5179 }
5180
5181 public dllexport void eInstance_SetMethod(Instance instance, const char * name, void * function)     // YET TO BE DECIDED:   , Module module)
5182 {
5183    if(instance && name)
5184    {
5185       Class _class;
5186       for(_class = instance._class; _class; _class = _class.base)
5187       {
5188          Method method = (Method)_class.methods.FindString(name);
5189          if(method && method.type == virtualMethod)
5190          {
5191             if(instance._vTbl == instance._class._vTbl)
5192             {
5193                instance._vTbl = _malloc(sizeof(void *) * instance._class.vTblSize);
5194                memcpy(instance._vTbl, instance._class._vTbl,
5195                   sizeof(int(*)()) * instance._class.vTblSize);
5196             }
5197             instance._vTbl[method.vid] = function ? function : null; //(void *)DefaultFunction;
5198          }
5199       }
5200    }
5201 }
5202
5203 public dllexport bool eInstance_IsDerived(Instance instance, Class from)
5204 {
5205    if(instance)
5206    {
5207       Class _class = instance._class;
5208       for(; _class; _class = _class.base)
5209       {
5210          if(_class == from)
5211             return true;
5212       }
5213    }
5214    return false;
5215 }
5216
5217 public dllexport void eInstance_IncRef(Instance instance)
5218 {
5219    if(instance)
5220       instance._refCount++;
5221 }
5222
5223 public dllexport void eInstance_DecRef(Instance instance)
5224 {
5225    if(instance)
5226    {
5227       instance._refCount--;
5228       //if(!instance._refCount)
5229       if(instance._refCount <= 0)
5230       {
5231          eInstance_Delete(instance);
5232       }
5233    }
5234 }
5235
5236 static void FixOffsets(Class _class)
5237 {
5238    OldLink deriv;
5239    _class.structSize += _class.base.structSize - _class.offset;
5240
5241    _class.offset = _class.base.structSize;
5242
5243    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
5244       FixOffsets(deriv.data);
5245 }
5246
5247 public dllexport void eClass_Resize(Class _class, int newSize)
5248 {
5249    OldLink deriv;
5250    _class.structSize = newSize;
5251    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
5252       FixOffsets(deriv.data);
5253 }
5254                                                                                                                         // F000F000 will mean a pointer size alignment
5255 public dllexport DataMember eClass_AddDataMember(Class _class, const char * name, const char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5256 {
5257    if(_class && name)
5258    {
5259       if(!_class.members.FindString(name))
5260       {
5261          DataMember dataMember;
5262
5263          if(alignment)
5264          {
5265             bool pointerAlignment = alignment == 0xF000F000;
5266             bool force64Bits = (_class.module.application.isGUIApp & 2) ? true : false;
5267             bool force32Bits = (_class.module.application.isGUIApp & 4) ? true : false;
5268             if((force32Bits || force64Bits) && !strcmp(_class.name, "AVLNode") && !strcmp(name, "__ecerePrivateData0"))
5269             {
5270                if(force64Bits)
5271                {
5272                   type = "byte[32]";
5273                   size = 32;
5274                }
5275                if(force32Bits)
5276                {
5277                   type = "byte[16]";
5278                   size = 16;
5279                }
5280             }
5281
5282             if(pointerAlignment) alignment = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
5283
5284             if(pointerAlignment && _class.structAlignment <= 4)
5285                _class.pointerAlignment = 1;
5286             else if(!pointerAlignment && alignment >= 8)
5287                _class.pointerAlignment = 0;
5288
5289             _class.structAlignment = Max(_class.structAlignment, alignment);
5290
5291             if(_class.offset % alignment)
5292             {
5293                _class.structSize += alignment - (_class.offset % alignment);
5294                _class.offset += alignment - (_class.offset % alignment);
5295             }
5296             if(_class.memberOffset % alignment)
5297                _class.memberOffset += alignment - (_class.memberOffset % alignment);
5298          }
5299
5300          dataMember = DataMember {
5301             name = CopyString(name);
5302             dataTypeString = CopyString(type);
5303             id = _class.memberID++;
5304             _class = _class;
5305             offset = _class.memberOffset;
5306             memberOffset = size;
5307             memberAccess = declMode;
5308             membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5309          };
5310          _class.membersAndProperties.Add(dataMember);
5311          _class.memberOffset += size;
5312
5313          _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5314          return dataMember;
5315       }
5316    }
5317    return null;
5318 }
5319                                                                                                                               // F000F000 will mean a pointer size alignment
5320 public dllexport DataMember eMember_AddDataMember(DataMember member, const char * name, const char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5321 {
5322    if(name && !member.membersAlpha.FindString(name))
5323    {
5324       DataMember dataMember;
5325
5326       if(alignment)
5327       {
5328          bool pointerAlignment = alignment == 0xF000F000;
5329          bool force64Bits = false; //(member._class.module.application.isGUIApp & 2) ? true : false;
5330          bool force32Bits = false; //(member._class.module.application.isGUIApp & 4) ? true : false;
5331          if(pointerAlignment) alignment = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
5332
5333          if(pointerAlignment && member.structAlignment <= 4)
5334             member.pointerAlignment = 1;
5335          else if(!pointerAlignment && alignment >= 8)
5336             member.pointerAlignment = 0;
5337
5338          member.structAlignment = Max(member.structAlignment, alignment);
5339
5340          if(member.memberOffset % alignment)
5341             member.memberOffset += alignment - (member.memberOffset % alignment);
5342       }
5343       dataMember = DataMember {
5344          name = CopyString(name);
5345          _class = member._class;
5346          dataTypeString = CopyString(type);
5347          id = member.memberID++;
5348          offset = (member.type == unionMember) ? 0 : member.memberOffset;
5349          memberAccess = declMode;
5350          membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5351       };
5352       member.members.Add(dataMember);
5353       if(member.type == unionMember)
5354       {
5355          if(size > member.memberOffset)
5356             member.memberOffset = size;
5357       }
5358       else
5359          member.memberOffset += size;
5360       member.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5361       return dataMember;
5362    }
5363    return null;
5364 }
5365
5366 public dllexport DataMember eMember_New(DataMemberType type, AccessMode declMode)
5367 {
5368    return DataMember { type = type, memberAccess = declMode, membersAlpha.CompareKey = (void *)BinaryTree::CompareString };
5369 }
5370
5371 static void SetMemberClass(DataMember member, Class _class)
5372 {
5373    DataMember dataMember;
5374    member._class = _class;
5375    for(dataMember = member.members.first; dataMember; dataMember = dataMember.next)
5376       SetMemberClass(dataMember, _class);
5377 }
5378
5379 public dllexport bool eMember_AddMember(DataMember addTo, DataMember dataMember)
5380 {
5381    if(dataMember.name && addTo.membersAlpha.FindString(dataMember.name))
5382    {
5383       DataMember_Free(dataMember);
5384       delete dataMember;
5385       return false;
5386    }
5387    addTo.members.Add(dataMember);
5388
5389    if(dataMember.name)
5390       addTo.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5391
5392    dataMember._class = addTo._class;
5393    // ? SetMemberClass(dataMember, addTo._class);
5394
5395    //dataMember.id = addTo.memberID++;
5396    dataMember.id = addTo.memberID;
5397    if(dataMember.type == unionMember)
5398       addTo.memberID += 1;
5399    else
5400       addTo.memberID += dataMember.memberID;
5401
5402    if(dataMember.pointerAlignment && dataMember.structAlignment <= 4)
5403       addTo.pointerAlignment = 1;
5404    else if(!dataMember.pointerAlignment && dataMember.structAlignment >= 8)
5405       addTo.pointerAlignment = 0;
5406
5407    addTo.structAlignment = Max(addTo.structAlignment, dataMember.structAlignment);
5408
5409    dataMember.offset = (addTo.type == unionMember) ? 0 : addTo.memberOffset;
5410
5411    if(dataMember.structAlignment)
5412    {
5413       if(addTo.memberOffset % dataMember.structAlignment)
5414          addTo.memberOffset += dataMember.structAlignment - (addTo.memberOffset % dataMember.structAlignment);
5415    }
5416
5417    if(addTo.type == unionMember)
5418    {
5419       if(dataMember.memberOffset > addTo.memberOffset)
5420          addTo.memberOffset = dataMember.memberOffset;
5421    }
5422    else
5423       addTo.memberOffset += dataMember.memberOffset;
5424    return true;
5425 }
5426
5427 public dllexport bool eClass_AddMember(Class _class, DataMember dataMember)
5428 {
5429    if(!_class || _class.comRedefinition || (dataMember.name && _class.members.FindString(dataMember.name)))
5430    {
5431       DataMember_Free(dataMember);
5432       delete dataMember;
5433       return false;
5434    }
5435    _class.membersAndProperties.Add(dataMember);
5436
5437    if(dataMember.name)
5438       _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5439
5440    //dataMember._class = _class;
5441    SetMemberClass(dataMember, _class);
5442
5443    //dataMember.id = _class.memberID++;
5444    dataMember.id = _class.memberID;
5445
5446    if(dataMember.pointerAlignment && dataMember.structAlignment <= 4)
5447       _class.pointerAlignment = 1;
5448    else if(!dataMember.pointerAlignment && dataMember.structAlignment >= 8)
5449       _class.pointerAlignment = 0;
5450
5451    _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
5452    if(dataMember.type == unionMember)
5453       _class.memberID += 1;
5454    else
5455       _class.memberID += dataMember.memberID;
5456
5457    if(dataMember.structAlignment)
5458    {
5459       if(_class.memberOffset % dataMember.structAlignment)
5460          _class.memberOffset += dataMember.structAlignment - (_class.memberOffset % dataMember.structAlignment);
5461    }
5462
5463    dataMember.offset = _class.memberOffset;
5464    _class.memberOffset += dataMember.memberOffset;
5465    return true;
5466 }
5467
5468 public dllexport BitMember eClass_AddBitMember(Class _class, const char * name, const char * type, int bitSize, int bitPos, AccessMode declMode)
5469 {
5470    if(_class && name && !_class.members.FindString(name))
5471    {
5472       uint64 mask = 0;
5473       int c;
5474       BitMember bitMember
5475       {
5476          name = CopyString(name);
5477          _class = _class;
5478          dataTypeString = CopyString(type);
5479          id = _class.memberID++;
5480          memberAccess = declMode;
5481       };
5482       _class.membersAndProperties.Add(bitMember);
5483       if(bitSize)
5484       {
5485          bitMember.pos = (bitPos == -1) ? _class.memberOffset : bitPos;
5486          bitMember.size = bitSize;
5487          _class.memberOffset = bitMember.pos + bitMember.size;
5488          for(c = 0; c<bitSize; c++)
5489          {
5490             if(c)
5491                mask <<= 1;
5492             mask |= 1;
5493          }
5494          bitMember.mask = mask << bitMember.pos;
5495       }
5496
5497      _class.members.Add((BTNode)BTNamedLink { name = bitMember.name, data = bitMember });
5498       return bitMember;
5499    }
5500    return null;
5501 }
5502
5503 static Module Module_Load(Module fromModule, const char * name, AccessMode importAccess, bool ensureCOM)
5504 {
5505    bool (stdcall * Load)(Module module) = null;
5506    bool (stdcall * Unload)(Module module) = null;
5507    Module module;
5508
5509    for(module = fromModule.application.allModules.first; module; module = module.next)
5510    {
5511       if(!strcmp(module.name, name))
5512          break;
5513    }
5514    if(ensureCOM && (!strcmp(name, "ecereCOM") || !strcmp(name, "ecere")))
5515    {
5516       for(module = fromModule.application.allModules.first; module; module = module.next)
5517       {
5518          if(!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM"))
5519             break;
5520       }
5521    }
5522    if(!module)
5523    {
5524       void * library = null;
5525
5526       if(ensureCOM && !strcmp(name, "ecereCOM"))
5527       {
5528          Load = COM_LOAD_FUNCTION;
5529          Unload = COM_UNLOAD_FUNCTION;
5530       }
5531       else
5532       {
5533          const char * libLocation = null;
5534 #if defined(__ANDROID__)
5535          libLocation = AndroidInterface_GetLibLocation();
5536 #endif
5537          library = Instance_Module_Load(libLocation, name, &Load, &Unload);
5538       }
5539       if(Load)
5540       {
5541          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5542          module.application = fromModule.application;
5543          module.library = library;
5544          {
5545             char moduleName[MAX_FILENAME];
5546             char ext[MAX_EXTENSION];
5547             GetLastDirectory(name, moduleName);
5548             GetExtension(moduleName, ext);
5549             StripExtension(moduleName);
5550             if((!strcmpi(ext, "dylib") || !strcmpi(ext, "so")) && strstr(moduleName, "lib") == moduleName)
5551             {
5552                int len = (int)strlen(moduleName) - 3;
5553                memmove(moduleName, moduleName + 3, len);
5554                moduleName[len] = 0;
5555             }
5556             module.name = CopyString(moduleName);
5557          }
5558          module.Unload = Unload;
5559          module.origImportType = normalImport;
5560
5561          if(!Load(module))
5562          {
5563             eInstance_Delete((Instance)module);
5564             module = null;
5565          }
5566       }
5567       fromModule.application.allModules.Add(module);
5568    }
5569    if(ensureCOM && !strcmp(name, "ecere") && module)
5570    {
5571       name = !strcmp(module.name, "ecereCOM") ? "ecere" : "ecereCOM";
5572       if((!Load && !strcmp(module.name, "ecereCOM")) ||
5573          (Load && (!__thisModule || !__thisModule.name || !strcmp(__thisModule.name, "ecereCOM")) && Load != (void *)COM_LOAD_FUNCTION))
5574       {
5575          Module module;
5576          for(module = fromModule.application.allModules.first; module; module = module.next)
5577          {
5578             if(!strcmp(module.name, name))
5579                break;
5580          }
5581          if(!module)
5582          {
5583             Load = COM_LOAD_FUNCTION;
5584             Unload = COM_UNLOAD_FUNCTION;
5585
5586             module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5587             module.application = fromModule.application;
5588             module.library = null;
5589             module.name = CopyString(name);
5590             module.Unload = Unload;
5591
5592             if(!Load(module))
5593             {
5594                eInstance_Delete((Instance)module);
5595                module = null;
5596             }
5597
5598             fromModule.application.allModules.Add(module);
5599          }
5600          if(module)
5601          {
5602             if(fromModule)
5603             {
5604                fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5605             }
5606             incref module;
5607          }
5608       }
5609    }
5610    if(module)
5611    {
5612       if(fromModule)
5613       {
5614          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5615       }
5616       incref module;
5617    }
5618 #if defined(_DEBUG)
5619    InternalModuleLoadBreakpoint();
5620 #endif
5621    return module;
5622 }
5623
5624 public dllexport Module eModule_Load(Module fromModule, const char * name, AccessMode importAccess)
5625 {
5626    return Module_Load(fromModule, name, importAccess, true);
5627 }
5628
5629 public dllexport Module eModule_LoadStrict(Module fromModule, const char * name, AccessMode importAccess)
5630 {
5631    return Module_Load(fromModule, name, importAccess, false);
5632 }
5633
5634 public dllexport Module eModule_LoadStatic(Module fromModule, const char * name, AccessMode importAccess, bool (* Load)(Module module), bool (* Unload)(Module module))
5635 {
5636    Module module;
5637    for(module = fromModule.application.allModules.first; module; module = module.next)
5638    {
5639       if(!strcmp(module.name, name))
5640          break;
5641    }
5642    if(!module)
5643    {
5644       if(Load)
5645       {
5646          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5647          module.application = fromModule.application;
5648          module.name = CopyString(name);
5649          module.origImportType = staticImport;
5650          module.Unload = (void *)Unload;
5651          if(!Load(module))
5652          {
5653             eInstance_Delete((Instance)module);
5654             module = null;
5655          }
5656       }
5657       fromModule.application.allModules.Add(module);
5658    }
5659    if(module)
5660    {
5661       if(fromModule)
5662       {
5663          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5664       }
5665       incref module;
5666    }
5667    return module;
5668 }
5669
5670 public dllexport void eModule_Unload(Module fromModule, Module module)
5671 {
5672    OldLink m;
5673    for(m = fromModule.modules.first; m; m = m.next)
5674    {
5675       if(m.data == module)
5676          break;
5677    }
5678    if(m)
5679    {
5680       fromModule.modules.Delete(m);
5681       delete module;
5682    }
5683 }
5684
5685 public dllexport void eEnum_AddFixedValue(Class _class, const char * string, int64 value)
5686 {
5687    if(_class && _class.type == enumClass)
5688    {
5689       EnumClassData data = (EnumClassData)_class.data;
5690       NamedLink64 item;
5691
5692       for(item = data.values.first; item; item = item.next)
5693          if(!strcmp(item.name, string))
5694             break;
5695       if(!item)
5696       {
5697          data.values.Add(NamedLink64 { data = value, name = CopyString(string) });
5698          if(value > data.largest)
5699             data.largest = value;
5700       }
5701    }
5702 }
5703
5704 public dllexport int64 eEnum_AddValue(Class _class, const char * string)
5705 {
5706    if(_class && _class.type == enumClass)
5707    {
5708       EnumClassData data = (EnumClassData)_class.data;
5709       int64 value = data.largest + 1;
5710       NamedLink64 item;
5711       for(item = data.values.first; item; item = item.next)
5712          if(!strcmp(item.name, string))
5713             break;
5714       if(!item)
5715       {
5716          data.values.Add(NamedLink64 { data = value, name = CopyString(string) });
5717          if(value > data.largest)
5718             data.largest = value;
5719          return value;
5720       }
5721    }
5722    return -1;
5723 }
5724
5725 static void NameSpace_Free(NameSpace parentNameSpace)
5726 {
5727    NameSpace * nameSpace;
5728    delete (void *)parentNameSpace.name;
5729
5730          /*   {
5731       BTNamedLink n, next;
5732       for(n = (BTNamedLink)parentNameSpace.classes.first; n; n = next)
5733       {
5734          Class c = n.data;
5735
5736          next = (BTNamedLink)((BTNode)n).next;
5737
5738          if(c.templateClass)
5739             eClass_Unregister(c);
5740       }
5741    }         */
5742
5743    while((nameSpace = (NameSpace *)parentNameSpace.nameSpaces.first))
5744    {
5745       NameSpace_Free(nameSpace);
5746       parentNameSpace.nameSpaces.Delete((BTNode)nameSpace);
5747    }
5748 }
5749
5750 static void Application_Destructor(Application app)
5751 {
5752    if(app.parsedCommand)
5753    {
5754       delete (void *)app.argv;
5755       delete app.parsedCommand;
5756    }
5757 }
5758
5759 static bool Module_Constructor(Module module)
5760 {
5761    module.privateNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5762    module.privateNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5763    module.privateNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5764    module.privateNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5765
5766    module.publicNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5767    module.publicNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5768    module.publicNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5769    module.publicNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5770    return true;
5771 }
5772
5773 static void Module_Destructor(Module module)
5774 {
5775    Class _class;
5776    DefinedExpression def;
5777    GlobalFunction function;
5778    Module m;
5779    SubModule handle;
5780
5781    // printf("Destructing module %s\n", module.name);
5782
5783    // Take out references from all modules
5784    for(m = module.application.allModules.first; m; m = m.next)
5785    {
5786       SubModule next;
5787       for(handle = m.modules.first; handle; handle = next)
5788       {
5789          next = handle.next;
5790          if(handle.module == module)
5791             m.modules.Delete(handle);
5792       }
5793    }
5794
5795    if(module.Unload)
5796    {
5797       if(module.origImportType == staticImport)
5798       {
5799          bool (* Unload)(Module module) = (void *)module.Unload;
5800          Unload(module);
5801       }
5802       else
5803       {
5804          bool (stdcall * Unload)(Module module) = (void *)module.Unload;
5805          Unload(module);
5806       }
5807    }
5808
5809    // Unload dependencies
5810    {
5811       Module ourWorld = class(Class).module;
5812       void * ourHandle = null;
5813       while((handle = module.modules.last))  // STARTING WITH LAST SO THAT ecereCOM IS UNLOADED LAST...
5814       {
5815          Module depModule = handle.module;
5816          if(depModule == ourWorld)
5817          {
5818             module.modules.Remove(handle);
5819             ourHandle = handle;
5820          }
5821          else
5822          {
5823             module.modules.Delete(handle);
5824             delete depModule;
5825          }
5826       }
5827       if(ourHandle)
5828       {
5829          delete ourHandle;
5830          delete ourWorld;
5831       }
5832    }
5833
5834    // Unload classes
5835    for(;(_class = module.classes.first);)
5836    {
5837       if(_class.nameSpace)
5838       {
5839          BTNamedLink classLink = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
5840          if(classLink)
5841          {
5842             OldLink t;
5843             for(t = _class.templatized.first; t; t = t.next)
5844             {
5845                Class template = t.data;
5846                BTNamedLink link;
5847                link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
5848
5849                template.nameSpace->classes.Delete((BTNode)link);
5850                template.nameSpace = null;
5851             }
5852             _class.nameSpace->classes.Delete((BTNode)classLink);
5853          }
5854 #ifdef _DEBUG
5855          else
5856          {
5857             printf("Warning: Could not find %s in namespace classes while destructing module %s\n", _class.name, module.name);
5858          }
5859 #endif
5860          _class.nameSpace = null;
5861       }
5862       _class.module = null;
5863       module.classes.Remove(_class);
5864       if(_class.count <= 0 || _class.type != normalClass || _class.isInstanceClass)
5865          eClass_Unregister(_class);
5866       else
5867       {
5868 #ifdef MEMINFO
5869          // printf("Delayed destruction of class %s\n", _class.name);
5870 #endif
5871       }
5872    }
5873
5874    // Unload defines
5875    for(;(def = module.defines.first);)
5876    {
5877       if(def.nameSpace)
5878       {
5879          BTNamedLink defLink;
5880          for(defLink = (BTNamedLink)def.nameSpace->defines.first; defLink; defLink = (BTNamedLink)((BTNode)defLink).next)
5881             if(defLink.data == def)
5882             {
5883                def.nameSpace->defines.Delete((BTNode)defLink);
5884                break;
5885             }
5886       }
5887       delete (void *)def.name;
5888       delete (void *)def.value;
5889       module.defines.Delete(def);
5890    }
5891
5892    // Unload functions
5893    for(;(function = module.functions.first);)
5894    {
5895       if(function.nameSpace)
5896       {
5897          BTNamedLink functionLink;
5898          for(functionLink = (BTNamedLink)function.nameSpace->functions.first; functionLink; functionLink = (BTNamedLink)((BTNode)functionLink).next)
5899             if(functionLink.data == function)
5900             {
5901                function.nameSpace->functions.Delete((BTNode)functionLink);
5902                break;
5903             }
5904       }
5905       delete (void *)function.name;
5906       delete (void *)function.dataTypeString;
5907       module.functions.Delete(function);
5908    }
5909
5910    delete (void *)module.name;
5911
5912    NameSpace_Free(module.privateNameSpace);
5913    NameSpace_Free(module.publicNameSpace);
5914
5915    if(module != module.application)
5916       module.application.allModules.Remove(module);
5917    else
5918       NameSpace_Free(module.application.systemNameSpace);
5919
5920 #ifndef MEMINFO
5921    Instance_Module_Free(module.library);
5922 #endif
5923 }
5924
5925 static int64 GetEnumSize(Class _class)
5926 {
5927    EnumClassData data = (EnumClassData)_class.data;
5928    return data.largest+1;
5929 }
5930
5931 #if defined(__GNUC__)
5932 #define strcmpi strcasecmp
5933 #define strnicmp strncasecmp
5934 #endif
5935
5936 #if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__))
5937 #undef strlwr
5938 #undef strupr
5939 default dllexport char * strlwr(char *string)
5940 {
5941    int c;
5942    for(c=0; string[c]; c++)
5943       if(string[c]>='A' && string[c]<='Z')
5944          string[c]+='a'-'A';
5945    return string;
5946 }
5947 default dllexport char * strupr(char *string)
5948 {
5949    int c;
5950    for(c=0; string[c]; c++)
5951       if(string[c]>='a' && string[c]<='z')
5952          string[c]-='a'-'A';
5953    return string;
5954 }
5955 #endif
5956
5957 public dllexport DefinedExpression eSystem_RegisterDefine(const char * name, const char * value, Module module, AccessMode declMode)
5958 {
5959    NameSpace * nameSpace = null;
5960
5961    int start = 0, c;
5962
5963    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5964    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5965
5966    if(declMode != staticAccess)
5967    {
5968       for(c = 0; name[c]; c++)
5969       {
5970          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5971          {
5972             NameSpace * newSpace;
5973
5974             char * spaceName = _malloc(c - start + 1);
5975             strncpy(spaceName, name + start, c - start);
5976             spaceName[c-start] = '\0';
5977
5978             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5979             if(!newSpace)
5980             {
5981                newSpace = new0 NameSpace[1];
5982                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5983                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5984                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5985                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5986                newSpace->name = spaceName;
5987                newSpace->parent = nameSpace;
5988                nameSpace->nameSpaces.Add((BTNode)newSpace);
5989             }
5990             else
5991                delete spaceName;
5992             nameSpace = newSpace;
5993             if(name[c] == ':') c++;
5994             start = c+1;
5995          }
5996       }
5997    }
5998    else
5999       c = (int)strlen(name);
6000
6001    if(c - start && !nameSpace->defines.FindString(name + start))
6002    {
6003       DefinedExpression def
6004       {
6005          name = CopyString(name);
6006          nameSpace = nameSpace;
6007          value = CopyString(value);
6008       };
6009       nameSpace->defines.Add((BTNode)BTNamedLink { name = def.name + start, data = def });
6010       // Reference the definition in the module
6011       module.defines.Add(def);
6012       return def;
6013    }
6014    return null;
6015 }
6016
6017 public dllexport GlobalFunction eSystem_RegisterFunction(const char * name, const char * type, void * func, Module module, AccessMode declMode)
6018 {
6019    NameSpace * nameSpace = null;
6020    int start = 0, c;
6021
6022    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
6023    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
6024
6025    if(declMode != staticAccess)
6026    {
6027       for(c = 0; name[c]; c++)
6028       {
6029          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
6030          {
6031             NameSpace * newSpace;
6032
6033             char * spaceName = _malloc(c - start + 1);
6034             strncpy(spaceName, name + start, c - start);
6035             spaceName[c-start] = '\0';
6036
6037             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
6038             if(!newSpace)
6039             {
6040                newSpace = new0 NameSpace[1];
6041                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
6042                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
6043                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
6044                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6045                newSpace->name = spaceName;
6046                newSpace->parent = nameSpace;
6047                nameSpace->nameSpaces.Add((BTNode)newSpace);
6048             }
6049             else
6050                delete spaceName;
6051             nameSpace = newSpace;
6052             if(name[c] == ':') c++;
6053             start = c+1;
6054          }
6055       }
6056    }
6057    else
6058       c = (int)strlen(name);
6059
6060    if(c - start && !nameSpace->functions.FindString(name + start))
6061    {
6062       GlobalFunction function
6063       {
6064          name = CopyString(name);
6065          nameSpace = nameSpace;
6066          dataTypeString = CopyString(type);
6067          function = func;
6068          module = module;
6069       };
6070       nameSpace->functions.Add((BTNode)BTNamedLink { name = function.name + start, data = function });
6071       // Reference the definition in the module
6072       module.functions.Add(function);
6073       return function;
6074    }
6075    return null;
6076 }
6077
6078 public dllexport DefinedExpression eSystem_FindDefine(Module module, const char * name)
6079 {
6080    if(name && module)
6081    {
6082       BTNamedLink link;
6083       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->defines);
6084       if(link) return link.data;
6085
6086       link = SearchModule(module, name, &((NameSpace *)0)->defines, true);
6087       if(link) return link.data;
6088    }
6089    return null;
6090 }
6091
6092 public dllexport GlobalFunction eSystem_FindFunction(Module module, const char * name)
6093 {
6094    if(name && module)
6095    {
6096       BTNamedLink link;
6097       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->functions);
6098       if(link) return link.data;
6099
6100       link = SearchModule(module, name, &((NameSpace *)0)->functions, true);
6101       if(link) return link.data;
6102    }
6103    return null;
6104 }
6105
6106 public dllexport void * eSystem_Renew(void * memory, unsigned int size)
6107 {
6108    return _realloc(memory, size);
6109 }
6110
6111 public dllexport void * eSystem_Renew0(void * memory, unsigned int size)
6112 {
6113    return _crealloc(memory, size);
6114 }
6115
6116 public dllexport void * eSystem_New(unsigned int size)
6117 {
6118 /*#ifdef _DEBUG
6119    void * pointer = _malloc(size);
6120    memset(pointer, 0xec, size);
6121    return pointer;
6122 #else*/
6123    return _malloc(size);
6124 //#endif
6125 }
6126
6127 public dllexport void * eSystem_New0(unsigned int size)
6128 {
6129    return _calloc(1,size);
6130 }
6131
6132 public dllexport void eSystem_Delete(void * memory)
6133 {
6134    if(memory)
6135       _free(memory);
6136 }
6137
6138 // Properties
6139 public dllexport void eInstance_FireSelfWatchers(Instance instance, Property _property)
6140 {
6141    if(instance && _property && _property.selfWatchable)
6142    {
6143       Class _class;
6144       for(_class = instance._class; _class; _class = _class.base)
6145       {
6146          SelfWatcher selfWatcher, next;
6147          for(selfWatcher = _class.selfWatchers.first; selfWatcher; selfWatcher = next)
6148          {
6149             next = selfWatcher.next;
6150             if(selfWatcher._property == _property)
6151                selfWatcher.callback(instance);
6152          }
6153       }
6154    }
6155 }
6156
6157 public dllexport void eInstance_FireWatchers(Instance instance, Property _property)
6158 {
6159    if(instance && _property && _property.isWatchable)
6160    {
6161       Module module = instance._class ? instance._class.module : null;
6162       Application application = module ? module.application : null;
6163       int flags = application ? application.isGUIApp : 0;
6164       bool inCompiler = (flags & 8) ? true : false;
6165       bool force32Bits = (flags & 4) ? true : false;
6166       if(!force32Bits || !inCompiler)
6167       {
6168          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6169          Watcher watcher, next;
6170
6171          for(watcher = watchers->first; watcher; watcher = next)
6172          {
6173             next = watcher.next;
6174             watcher.callback(watcher.object, instance);
6175          }
6176       }
6177    }
6178 }
6179
6180 public dllexport void eProperty_Watchable(Property _property)
6181 {
6182    if(!_property.isWatchable)
6183    {
6184       Class _class = _property._class;
6185       if(!_class.computeSize)
6186       {
6187          _property.watcherOffset = _class.structSize;
6188          _class.structSize += sizeof(OldList);
6189
6190          // highly inefficient
6191          FixDerivativesBase(_class, _class);
6192       }
6193       _property.isWatchable = true;
6194    }
6195 }
6196
6197 public dllexport void eClass_DestructionWatchable(Class _class)
6198 {
6199    if(!_class.destructionWatchOffset)
6200    {
6201       _class.destructionWatchOffset = _class.structSize;
6202       _class.structSize += sizeof(OldList);
6203       // highly inefficient
6204       FixDerivativesBase(_class, _class);
6205    }
6206 }
6207
6208 public dllexport void eProperty_SelfWatch(Class _class, const char * name, void (*callback)(void *))
6209 {
6210    if(_class)
6211    {
6212       Property _property = eClass_FindProperty(_class, name, _class.module);
6213
6214       if(!_property)
6215          _property = eClass_AddProperty(_class, name, null, null, null, baseSystemAccess /*privateAccess*/);
6216       _class.selfWatchers.Add(SelfWatcher { _property = _property, callback = callback });
6217       _property.selfWatchable = true;
6218    }
6219 }
6220
6221 public dllexport void eInstance_Watch(void * instance, Property _property, void * object, void (*callback)(void *, void *))
6222 {
6223    if(_property.isWatchable)
6224    {
6225       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6226       watchers->Add(Watcher { callback = callback, object = object });
6227    }
6228 }
6229
6230 public dllexport void eInstance_WatchDestruction(Instance instance, Instance object, void (*callback)(void *, void *))
6231 {
6232    OldList * watchers = (OldList *)((byte *)instance + instance._class.destructionWatchOffset);
6233    watchers->Add(Watcher { callback = callback, object = object });
6234 }
6235
6236 public dllexport void eInstance_StopWatching(Instance instance, Property _property, Instance object)
6237 {
6238    if(instance && (!_property || _property.isWatchable))
6239    {
6240       if(_property)
6241       {
6242          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6243          Watcher watcher;
6244          for(watcher = watchers->first; watcher; watcher = watcher.next)
6245             if(watcher.object == object)
6246             {
6247                watchers->Delete(watcher);
6248                break;
6249             }
6250       }
6251       else
6252       {
6253          // Stop watching all properties as well as destruction
6254          Class _class, base;
6255          for(_class = instance._class; _class; _class = base)
6256          {
6257             if(_class.destructionWatchOffset)
6258             {
6259                OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
6260                Watcher watcher;
6261
6262                for(watcher = watchers->first; watcher; watcher = watcher.next)
6263                {
6264                   watchers->Delete(watcher);
6265                   break;
6266                }
6267             }
6268             for(_property = (Property)_class.membersAndProperties.first; _property; _property = _property.next)
6269             {
6270                if(_property.isProperty && _property.isWatchable)
6271                {
6272                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
6273                   Watcher watcher;
6274                   for(watcher = watchers->first; watcher; watcher = watcher.next)
6275                      if(watcher.object == object)
6276                      {
6277                         watchers->Delete(watcher);
6278                         break;
6279                      }
6280                }
6281             }
6282             base = _class.base;
6283             if(base && (base.type == systemClass || base.isInstanceClass)) base = null;
6284          }
6285       }
6286    }
6287 }
6288
6289 public dllexport subclass(ClassDesignerBase) eClass_GetDesigner(Class _class)
6290 {
6291    for(;_class;_class = _class.base)
6292    {
6293       if(_class.designerClass)
6294          return (subclass(ClassDesignerBase))eSystem_FindClass(_class.module, _class.designerClass);
6295    }
6296    return null;
6297 }
6298
6299
6300 public dllexport subclass(ClassDesignerBase) eInstance_GetDesigner(Instance instance)
6301 {
6302    if(instance)
6303       return eClass_GetDesigner(instance._class);
6304    return null;
6305 }
6306
6307 public bool LocateModule(const char * name, const char * fileName)
6308 {
6309    return Instance_LocateModule(name, fileName);
6310 }
6311
6312 /*
6313 #if (defined(__WORDSIZE) && __WORDSIZE == 8) || defined(__x86_64__)
6314 #define _64BIT 1
6315 #else
6316 #define _64BIT 0
6317 #endif
6318
6319 #define arch_PointerSize                  sizeof(void *)
6320 #define structSize_Instance               (_64BIT ? 24 : 12)
6321 #define structSize_Module                 (_64BIT ? 560 : 300)
6322 #define structSize_BinaryTree             (_64BIT ? 32 : 16)
6323 #define structSize_OldList                (_64BIT ? 32 : 20)
6324 #define structSize_NamedLink64            (_64BIT ? 32 : 24)
6325 #define structSize_ClassTemplateArgument  (_64BIT ? 16 : 8)
6326 #define structSize_ClassTemplateParameter (_64BIT ? 64 : 40)
6327 #define structSize_OldLink                (_64BIT ? 24 : 12)
6328 #define structSize_BTNamedLink            (_64BIT ? 48 : 24)
6329 #define structSize_Application            (_64BIT ? 800 : 428)
6330 #define structSize_Watcher                (_64BIT ? 32 : 16)
6331 #define structSize_SelfWatcher            (_64BIT ? 32 : 16)
6332 #define structSize_GlobalFunction         (_64BIT ? 72 : 36)
6333 #define structSize_DefinedExpression      (_64BIT ? 40 : 20)
6334 #define structSize_BitMember              (_64BIT ? 96 : 64)
6335 #define structSize_DataMember             (_64BIT ? 160 : 96)
6336 #define structSize_ClassProperty          (_64BIT ? 80 : 40)
6337 #define structSize_Method                 (_64BIT ? 96 : 52)
6338 #define structSize_Property               (_64BIT ? 152 : 88)
6339 #define structSize_Class                  (_64BIT ? 624 : 376)
6340 */
6341
6342 static void LoadCOM(Module module)
6343 {
6344    bool force64Bits = (module.application.isGUIApp & 2) ? true : false;
6345    bool force32Bits = (module.application.isGUIApp & 4) ? true : false;
6346    bool inCompiler = (module.application.isGUIApp & 8) ? true : false;
6347    int pointerSize = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
6348    Class applicationClass;
6349    Class enumClass, structClass, boolClass;
6350    Class moduleClass;
6351
6352    // Create Base Class
6353    Class baseClass = eSystem_RegisterClass(normalClass, "class", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6354    baseClass.type = systemClass;
6355    baseClass.memberOffset = 0;
6356    baseClass.offset = 0;
6357    baseClass.structSize = 0;
6358    baseClass.typeSize = 0;
6359
6360    {
6361       Class instanceClass = eSystem_RegisterClass(normalClass, "ecere::com::Instance", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6362       instanceClass.type = normalClass;
6363       instanceClass.isInstanceClass = true;
6364       instanceClass.fixed = true;
6365       instanceClass.memberOffset = 0;
6366       instanceClass.offset = 0;
6367
6368       instanceClass.memberID = -3;
6369       instanceClass.startMemberID = -3;
6370
6371       eClass_AddDataMember(instanceClass, "_vTbl", "void **", pointerSize, pointerSize, publicAccess);
6372       eClass_AddDataMember(instanceClass, "_class", "ecere::com::Class", pointerSize, pointerSize, publicAccess);
6373       eClass_AddDataMember(instanceClass, "_refCount", "int", sizeof(int), sizeof(int), publicAccess);
6374    }
6375
6376    InitializeDataTypes1(module);
6377
6378    // Create Enum class
6379    enumClass = eSystem_RegisterClass(normalClass, "enum", null, 0, force64Bits ? 40 : sizeof(class EnumClassData), null, null, module, baseSystemAccess, publicAccess);
6380    eClass_AddClassProperty(enumClass, "enumSize", "int", null, GetEnumSize).constant = true;
6381    enumClass.type = systemClass;
6382
6383    delete (void *)enumClass.dataTypeString;
6384    enumClass.dataTypeString = CopyString(/*"unsigned int"*/"int");
6385
6386    // Create Struct (simple) class
6387    //structClass = eSystem_RegisterClass(structClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6388    structClass = eSystem_RegisterClass(normalClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
6389    structClass.type = systemClass;
6390    structClass.memberOffset = 0;
6391    structClass.offset = 0;
6392    structClass.structSize = 0;
6393    structClass.typeSize = 0;
6394
6395    //eClass_AddMethod(enumClass, "AddValue", "int()", eEnum_AddValue);
6396    //eClass_AddMethod(enumClass, "AddFixedValue", "void()", eEnum_AddFixedValue);
6397
6398    InitializeDataTypes(module);
6399
6400    // Create bool class
6401    boolClass = eSystem_RegisterClass(ClassType::enumClass, "bool", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
6402    eEnum_AddFixedValue(boolClass, "true",  bool::true);
6403    eEnum_AddFixedValue(boolClass, "false", bool::false);
6404
6405    // Create Module class
6406    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) :
6407                                                                                 sizeof(struct Module), 0, (void *)Module_Constructor, (void *)Module_Destructor, module, baseSystemAccess, publicAccess);
6408    eClass_AddVirtualMethod(moduleClass, "OnLoad", "bool()", null, publicAccess);
6409    eClass_AddVirtualMethod(moduleClass, "OnUnload", "void()", null, publicAccess);
6410    eClass_AddMethod(moduleClass, "Load", "Module(const char * name, AccessMode importAccess)", eModule_Load, publicAccess);
6411    eClass_AddMethod(moduleClass, "Unload", "void(Module module)", eModule_Unload, publicAccess);
6412    eClass_AddDataMember(moduleClass, "application", "Application", pointerSize, pointerSize, publicAccess);
6413    eClass_AddDataMember(moduleClass, "classes", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6414    eClass_AddDataMember(moduleClass, "defines", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6415    eClass_AddDataMember(moduleClass, "functions", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6416    eClass_AddDataMember(moduleClass, "modules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6417    eClass_AddDataMember(moduleClass, "prev", "Module", pointerSize, pointerSize, publicAccess);
6418    eClass_AddDataMember(moduleClass, "next", "Module", pointerSize, pointerSize, publicAccess);
6419    eClass_AddDataMember(moduleClass, "name", "const char *", pointerSize, pointerSize, publicAccess);
6420    eClass_AddDataMember(moduleClass, "library", "void *", pointerSize, pointerSize, publicAccess);
6421    eClass_AddDataMember(moduleClass, "Unload", "void *", pointerSize, pointerSize, publicAccess);
6422    eClass_AddDataMember(moduleClass, "importType", "ImportType", sizeof(ImportType), 4, publicAccess);
6423    eClass_AddDataMember(moduleClass, "origImportType", "ImportType", sizeof(ImportType), 4, publicAccess);
6424    eClass_AddDataMember(moduleClass, "privateNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6425    eClass_AddDataMember(moduleClass, "publicNameSpace", "NameSpace",  force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6426    moduleClass.fixed = true;
6427    moduleClass.count++;
6428    if(inCompiler && force32Bits)
6429       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);
6430
6431    // Create Application class
6432    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);
6433    if(inCompiler && force32Bits)
6434    {
6435       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);
6436       applicationClass.structSize = applicationClass.offset + (4+4+4+4 + 20 + 4 + 88);
6437    }
6438    eClass_AddVirtualMethod(applicationClass, "Main", "void()", null, publicAccess);
6439    eClass_AddDataMember(applicationClass, "argc", "int", sizeof(int), 4, publicAccess);
6440    eClass_AddDataMember(applicationClass, "argv", "const char **", pointerSize, pointerSize, publicAccess);
6441    eClass_AddDataMember(applicationClass, "exitCode", "int", sizeof(int), 4, publicAccess);
6442    eClass_AddDataMember(applicationClass, "isGUIApp", "bool", sizeof(bool), 4, publicAccess);
6443    eClass_AddDataMember(applicationClass, "allModules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6444    eClass_AddDataMember(applicationClass, "parsedCommand", "char *", pointerSize, pointerSize, publicAccess);
6445    eClass_AddDataMember(applicationClass, "systemNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6446    applicationClass.fixed = true;
6447    applicationClass.count++;
6448
6449    //AttachConsole(-1);
6450    //AllocConsole();
6451
6452    // --- Math ---
6453    eSystem_RegisterFunction("sin", "double sin(Angle number)", sin, module, baseSystemAccess);
6454    eSystem_RegisterFunction("sinh", "double sinh(Angle number)", sinh, module, baseSystemAccess);
6455    eSystem_RegisterFunction("cosh", "double cosh(Angle number)", cosh, module, baseSystemAccess);
6456    eSystem_RegisterFunction("tanh", "double tanh(Angle number)", tanh, module, baseSystemAccess);
6457    eSystem_RegisterFunction("sqrt", "double sqrt(double number)", sqrt, module, baseSystemAccess);
6458    eSystem_RegisterFunction("cos", "double cos(Angle number)", cos, module, baseSystemAccess);
6459    eSystem_RegisterFunction("tan", "double tan(Angle number)", tan, module, baseSystemAccess);
6460    eSystem_RegisterFunction("atan2", "Angle atan2(double y, double x)", atan2, module, baseSystemAccess);
6461    eSystem_RegisterFunction("asin", "Angle asin(double number)", asin, module, baseSystemAccess);
6462    eSystem_RegisterFunction("acos", "Angle acos(double number)", acos, module, baseSystemAccess);
6463    eSystem_RegisterFunction("atan", "Angle atan(double number)", atan, module, baseSystemAccess);
6464    eSystem_RegisterFunction("asinh", "Angle asinh(double number)", asinh, module, baseSystemAccess);
6465    eSystem_RegisterFunction("acosh", "Angle acosh(double number)", acosh, module, baseSystemAccess);
6466    eSystem_RegisterFunction("atanh", "Angle atanh(double number)", atanh, module, baseSystemAccess);
6467    eSystem_RegisterFunction("pow", "double pow(double number, double number2)", pow, module, baseSystemAccess);
6468    eSystem_RegisterFunction("fmod", "double fmod(double x, double y)", fmod, module, baseSystemAccess);
6469    eSystem_RegisterFunction("fabs", "double fabs(double number)", fabs, module, baseSystemAccess);
6470    eSystem_RegisterFunction("log", "double log(double number)", log, module, baseSystemAccess);
6471    eSystem_RegisterFunction("log10", "double log10(double number)", log10, module, baseSystemAccess);
6472    eSystem_RegisterFunction("ceil", "double ceil(double number)", ceil, module, baseSystemAccess);
6473    eSystem_RegisterFunction("floor", "double floor(double number)", floor, module, baseSystemAccess);
6474    eSystem_RegisterFunction("exp", "double exp(double number)", exp, module, baseSystemAccess);
6475
6476    // --- Stdlib ---
6477    eSystem_RegisterFunction("qsort", "void qsort(void *, uintsize, uintsize, int (*)(void *, void *))", qsort, module, baseSystemAccess);
6478    eSystem_RegisterFunction("strtod", "double strtod(const char*, char**)", strtod, module, baseSystemAccess);
6479    eSystem_RegisterFunction("strtol", "int strtol(const char*, char**, int base)", strtol, module, baseSystemAccess);
6480    eSystem_RegisterFunction("strtoul", "unsigned long strtoul(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
6481    eSystem_RegisterFunction("strtoll", "int64 strtoll(const char * nptr, char ** endptr, int base)", strtoll, module, baseSystemAccess);
6482    eSystem_RegisterFunction("strtoull", "uint64 strtoull(const char * nptr, char ** endptr, int base)", strtoull, module, baseSystemAccess);
6483    eSystem_RegisterFunction("system", "int system(const char*)", system, module, baseSystemAccess);
6484    eSystem_RegisterFunction("atoi", "int atoi(const char*)", atoi, module, baseSystemAccess);
6485    eSystem_RegisterFunction("atof", "double atof(const char*)", atof, module, baseSystemAccess);
6486    eSystem_RegisterFunction("memset", "void * memset(void * area, int value, uintsize count)", memset, module, baseSystemAccess);
6487    eSystem_RegisterFunction("getenv", "char * getenv(const char * name)", getenv, module, baseSystemAccess);
6488    eSystem_RegisterFunction("rename", "int rename(const char *oldpath, const char *newpath)", rename, module, baseSystemAccess);
6489
6490    // --- String --- (These might move to the string class)
6491    eSystem_RegisterFunction("strlen", "uintsize strlen(const char *)", strlen, module, baseSystemAccess);
6492    eSystem_RegisterFunction("strcat", "char * strcat(char *, const char *)", strcat, module, baseSystemAccess);
6493    eSystem_RegisterFunction("strncat", "char * strncat(char *, const char *, uintsize n)", strncat, module, baseSystemAccess);
6494    eSystem_RegisterFunction("strchr", "char * strchr(const char *, int)", strchr, module, baseSystemAccess);
6495    eSystem_RegisterFunction("strstr", "char * strstr(const char *, const char *)", strstr, module, baseSystemAccess);
6496    eSystem_RegisterFunction("strspn", "uintsize strspn(const char *, const char *)", strspn, module, baseSystemAccess);
6497    eSystem_RegisterFunction("strcspn", "uintsize strcspn(const char *, const char *)", strcspn, module, baseSystemAccess);
6498    eSystem_RegisterFunction("strpbrk", "char * strpbrk(const char *, const char *)", strpbrk, module, baseSystemAccess);
6499
6500    eSystem_RegisterDefine("fstrcmp", "(__runtimePlatform == win32) ? strcmpi : strcmp", module, baseSystemAccess);
6501
6502 //#if defined(__GNUC__)
6503    eSystem_RegisterDefine("strcmpi", "strcasecmp", module, baseSystemAccess);
6504    eSystem_RegisterDefine("strnicmp", "strncasecmp", module, baseSystemAccess);
6505    eSystem_RegisterFunction("strcasecmp", "int strcasecmp(const char *, const char *)", strcmpi, module, baseSystemAccess);
6506    eSystem_RegisterFunction("strncasecmp", "int strncasecmp(const char *, const char *, uintsize n)", strnicmp, module, baseSystemAccess);
6507 /*
6508 #else
6509    eSystem_RegisterDefine("strcasecmp", "strcmpi", module, baseSystemAccess);
6510    eSystem_RegisterDefine("strncasecmp", "strnicmp", module, baseSystemAccess);
6511    eSystem_RegisterFunction("strcmpi", "int strcmpi(const char *, const char *)", strcmpi, module, baseSystemAccess);
6512    eSystem_RegisterFunction("strnicmp", "int strnicmp(const char *, const char *, int n)", strnicmp, module, baseSystemAccess);
6513 #endif
6514 */
6515
6516    eSystem_RegisterFunction("strcmp", "int strcmp(const char *, const char *)", strcmp, module, baseSystemAccess);
6517    eSystem_RegisterFunction("strncmp", "int strncmp(const char *, const char *, uintsize n)", strncmp, module, baseSystemAccess);
6518    eSystem_RegisterFunction("strlwr", "char * strlwr(char *)", strlwr, module, baseSystemAccess);
6519    eSystem_RegisterFunction("strupr", "char * strupr(char *)", strupr, module, baseSystemAccess);
6520    eSystem_RegisterFunction("strcpy", "char * strcpy(char *, const char *)", strcpy, module, baseSystemAccess);
6521    eSystem_RegisterFunction("strncpy", "char * strncpy(char *, const char *, uintsize n)", strncpy, module, baseSystemAccess);
6522    eSystem_RegisterFunction("memcpy", "void * memcpy(void *, const void *, uintsize size)", memcpy, module, baseSystemAccess);
6523    eSystem_RegisterFunction("memmove", "void * memmove(void *, const void *, uintsize size)", memmove, module, baseSystemAccess);
6524    eSystem_RegisterFunction("memcmp", "int memcmp(const void *, const void *, uintsize size)", memcmp, module, baseSystemAccess);
6525
6526    // --- Stdio ---
6527    eSystem_RegisterFunction("sprintf", "int sprintf(char *, const char *, ...)", sprintf, module, baseSystemAccess);
6528    eSystem_RegisterFunction("snprintf", "int sprintf(char *, uintsize, const char *, ...)", snprintf, module, baseSystemAccess);
6529    eSystem_RegisterFunction("printf", "int printf(const char *, ...)", printf, module, baseSystemAccess);
6530    eSystem_RegisterFunction("vsprintf", "int vsprintf(char*, const char*, __builtin_va_list)", vsprintf, module, baseSystemAccess);
6531    eSystem_RegisterFunction("vsnprintf", "int vsnprintf(char*, uintsize, const char*, __builtin_va_list)", vsnprintf, module, baseSystemAccess);
6532    eSystem_RegisterFunction("puts", "int puts(const char *)", puts, module, baseSystemAccess);
6533    eSystem_RegisterFunction("fputs", "int fputs(const char *, void * stream)", fputs, module, baseSystemAccess);
6534
6535    // --- Ctype ---
6536    eSystem_RegisterFunction("tolower", "int tolower(int)", tolower, module, baseSystemAccess);
6537    eSystem_RegisterFunction("toupper", "int toupper(int)", toupper, module, baseSystemAccess);
6538    eSystem_RegisterFunction("isdigit", "bool isdigit(int)", isdigit, module, baseSystemAccess);
6539    eSystem_RegisterFunction("isxdigit","bool isxdigit(int)", isxdigit, module, baseSystemAccess);
6540    eSystem_RegisterFunction("isalnum", "int isalnum(int c)", isalnum, module, baseSystemAccess);
6541    eSystem_RegisterFunction("isspace", "int isspace(int c)", isspace, module, baseSystemAccess);
6542    eSystem_RegisterFunction("isalpha", "int isalpha(int c)", isalpha, module, baseSystemAccess);
6543    eSystem_RegisterFunction("islower", "int islower(int c)", islower, module, baseSystemAccess);
6544    eSystem_RegisterFunction("isupper", "int isupper(int c)", isupper, module, baseSystemAccess);
6545    eSystem_RegisterFunction("isprint", "int isprint(int c)", isprint, module, baseSystemAccess);
6546    eSystem_RegisterFunction("isblank", "int isblank(int c)", isblank, module, baseSystemAccess);
6547
6548 }
6549
6550 public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char * argv[])
6551 {
6552    Application app;
6553
6554 #ifdef __ANDROID__
6555    // Clean up global variables
6556    memoryInitialized = false;
6557    pools = null;
6558 #ifdef MEMINFO
6559    memset(&memStacks, 0, sizeof(BinaryTree));
6560    memoryErrorsCount = 0;
6561    memset(&memBlocks, 0, sizeof(BinaryTree));
6562    recurse = false;
6563    blockID = 0;
6564    allocateClass = null;
6565    allocateInternal = false;
6566    TOTAL_MEM = 0;
6567    OUTSIDE_MEM = 0;
6568 #endif
6569 #endif
6570
6571 #ifdef _DEBUG
6572    // printf("Using debug ecere runtime library\n");
6573 #endif
6574    app = _calloc(1, sizeof(class Application));
6575
6576    Module_Constructor(app);
6577    app.systemNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
6578    app.systemNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
6579    app.systemNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
6580    app.systemNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6581
6582    Instance_COM_Initialize(argc, argv, &app.parsedCommand, &app.argc, &app.argv);
6583
6584    app.application = app;
6585    app.allModules.offset = sizeof(class Instance) + (uint)(uintptr)&((struct Module *)0)->prev;
6586    app.isGUIApp = guiApp;
6587
6588    LoadCOM(app);
6589
6590    app._class = eSystem_FindClass(app, "Application");
6591
6592    return app;
6593 }
6594
6595 public dllexport ClassTemplateParameter eClass_AddTemplateParameter(Class _class, const char * name, TemplateParameterType type, const void * info, ClassTemplateArgument defaultArg)
6596 {
6597    if(_class && name)
6598    {
6599       ClassTemplateParameter param;
6600
6601       for(param = _class.templateParams.first; param; param = param.next)
6602       {
6603          if(!strcmp(param.name, name))
6604             return param;
6605       }
6606       param =
6607       {
6608          name = CopyString(name);
6609          type = type;
6610          (type == identifier) ? info : CopyString(info);
6611       };
6612       if(defaultArg != null)
6613       {
6614          param.defaultArg = defaultArg;
6615          CopyTemplateArg(param, param.defaultArg);
6616       }
6617       _class.templateParams.Add(param);
6618       return param;
6619    }
6620    return null;
6621 }
6622
6623 public dllexport void eClass_DoneAddingTemplateParameters(Class base)
6624 {
6625    if(base)
6626    {
6627       ClassTemplateParameter param;
6628       {
6629          void * first = base.templateParams.first;
6630          int count = base.templateParams.count;
6631
6632          FreeTemplateArgs(base);
6633          delete base.templateArgs;
6634
6635          base.templateParams.first = null;
6636          base.templateParams.count = 0;
6637
6638          FreeTemplatesDerivatives(base);
6639
6640          base.templateParams.first = first;
6641          base.templateParams.count = count;
6642       }
6643
6644       for(param = base.templateParams.first; param; param = param.next)
6645       {
6646          if(param.type == identifier && param.defaultArg.memberString)
6647          {
6648             Class memberClass = base;
6649             const char * colon = strstr(param.defaultArg.memberString, "::");
6650             const char * memberName;
6651             if(colon)
6652             {
6653                char className[1024];
6654                Class sClass;
6655
6656                memcpy(className, param.defaultArg.memberString, colon - param.defaultArg.memberString);
6657                className[colon - param.defaultArg.memberString] = '\0';
6658                memberName = colon + 2;
6659
6660                for(sClass = base; sClass; sClass = sClass.base)
6661                {
6662                   ClassTemplateParameter cParam;
6663                   Class nextClass;
6664                   int id = 0;
6665                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) id += nextClass.templateParams.count;
6666                   // Safety! What could cause base.templateArgs to be null?
6667                   if(sClass == base || base.templateArgs)
6668                   {
6669                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
6670                      {
6671                         if(cParam.type == type && !strcmp(cParam.name, className))
6672                            strcpy(className, (sClass == base) ? cParam.defaultArg.dataTypeString : base.templateArgs[id].dataTypeString);
6673                         id++;
6674                      }
6675                   }
6676                }
6677                memberClass = eSystem_FindClass(base.module, className);
6678                if(!memberClass)
6679                   memberClass = eSystem_FindClass(base.module.application, className);
6680             }
6681             else
6682                memberName = param.defaultArg.memberString;
6683
6684             if(memberClass)
6685             {
6686                switch(param.memberType)
6687                {
6688                   case dataMember:
6689                      param.defaultArg.member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
6690                      break;
6691                   case method:
6692                      param.defaultArg.method = eClass_FindMethod(memberClass, memberName, memberClass.module);
6693                      break;
6694                   case prop:
6695                      param.defaultArg.prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
6696                      break;
6697                }
6698             }
6699          }
6700       }
6701
6702       //ComputeClassParameters(base, null, null);
6703
6704       FixDerivativesBase(base, base);
6705    }
6706 }
6707
6708 static void FreeTemplatesDerivatives(Class base)
6709 {
6710    OldLink derivative, templateLink;
6711    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
6712    {
6713       Class _class = derivative.data;
6714       if(_class.templateArgs)
6715       {
6716          FreeTemplateArgs(_class);
6717          delete _class.templateArgs;
6718       }
6719       FreeTemplatesDerivatives(_class);
6720    }
6721
6722    for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
6723    {
6724       Class _class = templateLink.data;
6725       if(_class.templateArgs)
6726       {
6727          FreeTemplateArgs(_class);
6728          delete _class.templateArgs;
6729       }
6730       FreeTemplatesDerivatives(_class);
6731    }
6732 }
6733
6734 static const char * platformNames[Platform] = { "", "win32", "linux", "apple" }; // how to have this be accessible outside of dll/lib
6735 static const Platform firstPlatform = win32;
6736 static const Platform lastPlatform = apple;
6737
6738 public enum Platform
6739 {
6740    unknown, win32, tux, apple;
6741
6742    property const char *
6743    {
6744       get { return OnGetString(null, null, null); }
6745       set
6746       {
6747          if(value)
6748          {
6749             Platform c;
6750             for(c = firstPlatform; c <= lastPlatform; c++)
6751                if(!strcmpi(value, platformNames[c]))
6752                   return c;
6753          }
6754          return unknown;
6755       }
6756    };
6757
6758    const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
6759    {
6760       if(this >= firstPlatform && this <= lastPlatform)
6761       {
6762          if(tempString)
6763             strcpy(tempString, platformNames[this]);
6764          return platformNames[this];
6765       }
6766       if(tempString && tempString[0])
6767          tempString[0] = '\0';
6768       return null;
6769    }
6770
6771    bool OnGetDataFromString(const char * string)
6772    {
6773       this = string;
6774       return this != unknown;
6775    }
6776 };
6777
6778 default extern Platform runtimePlatform;
6779
6780 public Platform GetRuntimePlatform()
6781 {
6782    return runtimePlatform;
6783 }
6784
6785 namespace gui;
6786
6787 class Window;
6788
6789 namespace com;
6790 // CLASS DESIGNER SUPPORT
6791
6792 public class ObjectInfo : struct
6793 {
6794 public:
6795    ObjectInfo prev, next;
6796    Instance instance;
6797    char * name;
6798    Instantiation instCode;
6799    bool deleted;
6800    ObjectInfo oClass;
6801    OldList instances;
6802    ClassDefinition classDefinition;
6803    bool modified;
6804    void * i18nStrings;
6805 };
6806
6807 public class DesignerBase : Window
6808 {
6809 public:
6810    virtual bool FindObject(Instance * instance, const char * string);
6811    virtual void RenameObject(ObjectInfo object, const char * name);
6812    virtual void SelectObjectFromDesigner(ObjectInfo object);
6813    virtual void CodeAddObject(Instance instance, ObjectInfo * object);
6814    virtual void SheetAddObject(ObjectInfo object);
6815    virtual void AddToolBoxClass(Class _class);
6816    virtual void AddDefaultMethod(Instance instance, Instance classInstance);
6817    virtual void DeleteObject(ObjectInfo object);
6818    virtual bool ObjectContainsCode(ObjectInfo object);
6819    virtual void ModifyCode(void);
6820    virtual void UpdateProperties(void);
6821
6822    ClassDesignerBase classDesigner;
6823    const char * objectClass;
6824    bool isDragging;
6825
6826    // FIX THIS WITH PUBLIC:
6827    property ClassDesignerBase classDesigner
6828    {
6829       get { return classDesigner; }
6830       set { classDesigner = value; }
6831    };
6832    property const char * objectClass
6833    {
6834       get { return objectClass; }
6835       set { objectClass = value; }
6836    };
6837    property bool isDragging
6838    {
6839       get { return isDragging; }
6840       set { isDragging = value; }
6841    };
6842 }
6843
6844 public class ClassDesignerBase : Window
6845 {
6846 public:
6847    virtual void Reset(void);
6848    virtual void AddObject(void);
6849    virtual void SelectObject(ObjectInfo object, Instance control);
6850
6851    virtual void ListToolBoxClasses(DesignerBase designer);
6852
6853    virtual void ::PrepareTestObject(DesignerBase designer, Instance test);
6854    virtual void ::CreateObject(DesignerBase designer, Instance instance, ObjectInfo object, bool isClass, Instance _class);
6855    virtual void ::PostCreateObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6856    virtual void ::DroppedObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6857    virtual void ::DestroyObject(Instance object);
6858    virtual void ::FixProperty(Property prop, Instance object);
6859    virtual void ::CreateNew(EditBox editBox, Size clientSize, const char * name, const char * inherit);
6860 }
6861
6862 DesignerBase activeDesigner;
6863
6864 public void SetActiveDesigner(DesignerBase designer)
6865 {
6866    activeDesigner = designer;
6867 }
6868
6869 public DesignerBase GetActiveDesigner()
6870 {
6871    return activeDesigner;
6872 }
6873
6874
6875 bool poolingDisabled;
6876
6877 public dllexport void eSystem_SetPoolingDisabled(bool disabled)
6878 {
6879    poolingDisabled = disabled;
6880 }
6881
6882 namespace sys;
6883
6884 // constants
6885 define LEAD_OFFSET      = 0xD800 - (0x10000 >> 10);
6886 define SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00;
6887
6888 public bool UTF8Validate(const char * source)
6889 {
6890    if(source)
6891    {
6892       int c;
6893       for(c = 0; source[c];)
6894       {
6895          byte ch = source[c];
6896          unichar codePoint = 0;
6897          int numBytes = 1;
6898          int i;
6899          byte mask = 0x7F;
6900          if(ch & 0x80)
6901          {
6902             if(ch & 0x40)
6903             {
6904                mask >>= 2;
6905                numBytes++;
6906                if(ch & 0x20)
6907                {
6908                   numBytes++;
6909                   mask >>= 1;
6910                   if(ch & 0x10)
6911                   {
6912                      if(ch & 0x08)
6913                         return false;
6914                      numBytes++;
6915                      mask >>= 1;
6916                   }
6917                }
6918             }
6919             else
6920                return false;
6921          }
6922          for(i = 0; i<numBytes && (ch = source[c]); i++, c++)
6923          {
6924             codePoint <<= 6;
6925             codePoint |= ch & mask;
6926             mask = 0x3F;
6927             if(i > 1)
6928             {
6929                if(!(ch & 0x80) || (ch & 0x40))
6930                   return false;
6931             }
6932          }
6933          if(i < numBytes) return false;
6934
6935          if(codePoint > 0x10FFFF || (codePoint >= 0xD800 && codePoint <= 0xDFFF) ||
6936            (codePoint < 0x80 && numBytes > 1) ||
6937            (codePoint < 0x800 && numBytes > 2) ||
6938            (codePoint < 0x10000 && numBytes > 3))
6939             return false;
6940       }
6941    }
6942    return true;
6943 }
6944
6945 public int ISO8859_1toUTF8(const char * source, char * dest, int max)
6946 {
6947    int c;
6948    int d = 0;
6949    byte * byteDest = (byte *)dest;
6950    for(c = 0; source[c]; c++)
6951    {
6952       unichar ch = ((byte *)source)[c];
6953       switch(ch)
6954       {
6955          case 150: ch = (unichar)0x2012; break;
6956       }
6957       if(ch < 0x80)
6958       {
6959          if(d + 1 >= max) break;
6960          byteDest[d++] = (char)ch;
6961       }
6962       else if(ch < 0x800)
6963       {
6964          if(d + 2 >= max) break;
6965          byteDest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6966          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
6967       }
6968       else if(ch < 0x10000)
6969       {
6970          if(d + 3 >= max) break;
6971          byteDest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6972          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6973          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
6974       }
6975       else
6976       {
6977          if(d + 4 >= max) break;
6978          byteDest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6979          byteDest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6980          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6981          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
6982       }
6983    }
6984    dest[d] = 0;
6985    return d;
6986 }
6987
6988 public char * UTF16toUTF8(const uint16 * source)
6989 {
6990    int c;
6991    int d = 0;
6992    int len;
6993    byte * dest;
6994    uint16 u16;
6995    bool invert = false;
6996
6997    for(len = 0; source[len]; len++);
6998    dest = new byte[len * 3 + 1];
6999    for(c = 0; (u16 = source[c]); c++)
7000    {
7001       unichar ch;
7002       if(!c && (u16 == 0xFFFE || u16 == 0xFEFF))
7003       {
7004          if(u16 == 0xFFFE) invert = true;
7005          continue;
7006       }
7007       if(invert) { u16 = ((u16 & 0xFF00) >> 8) | ((u16 & 0x00FF) << 8); }
7008
7009       if(u16 < 0xD800 || u16 > 0xDBFF)
7010          ch = (unichar)u16;
7011       else
7012          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
7013
7014       if(ch < 0x80)
7015       {
7016          dest[d++] = (char)ch;
7017       }
7018       else if(ch < 0x800)
7019       {
7020          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
7021          dest[d++] = 0x80 | (byte)(ch & 0x03F);
7022       }
7023       else if(ch < 0x10000)
7024       {
7025          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
7026          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7027          dest[d++] = 0x80 | (byte)(ch & 0x03F);
7028       }
7029       else
7030       {
7031          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
7032          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
7033          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7034          dest[d++] = 0x80 | (byte)(ch & 0x03F);
7035       }
7036    }
7037    dest[d] = 0;
7038    dest = renew dest byte[d+1];
7039    return (char *)dest;
7040 }
7041
7042 public int UTF16toUTF8Buffer(const uint16 * source, char * dest, int max)
7043 {
7044    int c;
7045    int d = 0;
7046    uint16 u16;
7047    byte * byteDest = (byte *)dest;
7048    for(c = 0; (u16 = source[c]); c++)
7049    {
7050       unichar ch;
7051       if(u16 < 0xD800 || u16 > 0xDBFF)
7052          ch = (unichar)u16;
7053       else
7054          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
7055
7056       if(ch < 0x80)
7057       {
7058          if(d + 1 >= max) break;
7059          byteDest[d++] = (char)ch;
7060       }
7061       else if(ch < 0x800)
7062       {
7063          if(d + 2 >= max) break;
7064          byteDest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
7065          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7066       }
7067       else if(ch < 0x10000)
7068       {
7069          if(d + 3 >= max) break;
7070          byteDest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
7071          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7072          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7073       }
7074       else
7075       {
7076          if(d + 4 >= max) break;
7077          byteDest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
7078          byteDest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
7079          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7080          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7081       }
7082    }
7083    byteDest[d] = 0;
7084    return d;
7085 }
7086
7087 // NOTE: UTF8GetChar now returns 0 into numBytes for the null-terminating character ('\0')
7088 public unichar UTF8GetChar(const char * string, int * numBytes)
7089 {
7090    unichar ch;
7091    byte b = ((byte *)string)[0];
7092    int i;
7093    byte mask = 0x7F;
7094    int nb = b ? 1 : 0;
7095    ch = 0;
7096    if(b & 0x80)
7097    {
7098       if(b & 0x40)
7099       {
7100          mask >>= 2;
7101          nb++;
7102          if(b & 0x20)
7103          {
7104             nb++;
7105             mask >>= 1;
7106             if(b & 0x10)
7107             {
7108                if(b & 0x08) { nb = 0; }
7109                nb++;
7110                mask >>= 1;
7111             }
7112          }
7113       }
7114       else
7115          nb = 0;
7116    }
7117    for(i = 0; i<nb; i++)
7118    {
7119       ch <<= 6;
7120       ch |= (b = ((byte *)string)[i]) & mask;
7121       mask = 0x3F;
7122       if(i > 1 && (!(b & 0x80) || (b & 0x40)))
7123       {
7124          nb = 0;
7125          ch = 0;
7126       }
7127    }
7128
7129    if(i < nb ||
7130       ch > 0x10FFFF || (ch >= 0xD800 && ch <= 0xDFFF) ||
7131      (ch < 0x80 && nb > 1) ||
7132      (ch < 0x800 && nb > 2) ||
7133      (ch < 0x10000 && nb > 3))
7134    {
7135       ch = 0;
7136       nb = 0;
7137    }
7138    if(numBytes) *numBytes = nb;
7139    return ch;
7140 }
7141
7142 public int UTF8toUTF16Buffer(const char * source, uint16 * dest, int max)
7143 {
7144    if(source)
7145    {
7146       int c;
7147       int d = 0;
7148       for(c = 0; source[c];)
7149       {
7150          byte ch = source[c];
7151          unichar codePoint = 0;
7152          int numBytes = 1;
7153          int i;
7154          byte mask = 0x7F;
7155          if(ch & 0x80 && ch & 0x40)
7156          {
7157             mask >>= 2;
7158             numBytes++;
7159             if(ch & 0x20)
7160             {
7161                numBytes++;
7162                mask >>= 1;
7163                if(ch & 0x10)
7164                {
7165                   numBytes++;
7166                   mask >>= 1;
7167                }
7168             }
7169          }
7170          for(i = 0; i<numBytes; i++)
7171          {
7172             codePoint <<= 6;
7173             codePoint |= source[c++] & mask;
7174             mask = 0x3F;
7175          }
7176
7177          if(codePoint > 0xFFFF)
7178          {
7179             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
7180             uint16 trail = (uint16)(0xDC00 | (codePoint & 0x3FF));
7181             if(d >= max - 1) break;
7182             dest[d++] = lead;
7183             dest[d++] = trail;
7184          }
7185          else
7186          {
7187             if(d >= max) break;
7188             dest[d++] = (uint16)codePoint;
7189          }
7190       }
7191       dest[d] = 0;
7192       return d;
7193    }
7194    return 0;
7195 }
7196
7197 public int UTF32toUTF8Len(const unichar * source, int count, char * dest, int max)
7198 {
7199    int c;
7200    int d = 0;
7201    uint32 ch;
7202    byte * byteDest = (byte *)dest;
7203    for(c = 0; c<count && (ch = source[c]); c++)
7204    {
7205       if(ch < 0x80)
7206       {
7207          if(d + 1 >= max) break;
7208          byteDest[d++] = (char)ch;
7209       }
7210       else if(ch < 0x800)
7211       {
7212          if(d + 2 >= max) break;
7213          byteDest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
7214          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7215       }
7216       else if(ch < 0x10000)
7217       {
7218          if(d + 3 >= max) break;
7219          byteDest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
7220          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7221          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7222       }
7223       else
7224       {
7225          if(d + 4 >= max) break;
7226          byteDest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
7227          byteDest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
7228          byteDest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
7229          byteDest[d++] = 0x80 | (byte)(ch & 0x03F);
7230       }
7231    }
7232    byteDest[d] = 0;
7233    return d;
7234 }
7235
7236 public uint16 * UTF8toUTF16(const char * source, int * wordCount)
7237 {
7238    if(source)
7239    {
7240       int len = (int)strlen(source);
7241       uint16 * dest = new uint16[len + 1];
7242       int c;
7243       int d = 0;
7244       for(c = 0; source[c];)
7245       {
7246          byte ch = source[c];
7247          unichar codePoint = 0;
7248          int numBytes = 1;
7249          int i;
7250          byte mask = 0x7F;
7251          if(ch & 0x80 && ch & 0x40)
7252          {
7253             mask >>= 2;
7254             numBytes++;
7255             if(ch & 0x20)
7256             {
7257                numBytes++;
7258                mask >>= 1;
7259                if(ch & 0x10)
7260                {
7261                   numBytes++;
7262                   mask >>= 1;
7263                }
7264             }
7265          }
7266          for(i = 0; i<numBytes; i++)
7267          {
7268             codePoint <<= 6;
7269             codePoint |= source[c++] & mask;
7270             mask = 0x3F;
7271          }
7272
7273          if(codePoint > 0xFFFF)
7274          {
7275             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
7276             uint16 trail = (uint16)(0xDC00 | (codePoint & 0x3FF));
7277             dest[d++] = lead;
7278             dest[d++] = trail;
7279          }
7280          else
7281          {
7282             dest[d++] = (uint16)codePoint;
7283          }
7284       }
7285       dest[d] = 0;
7286       if(wordCount) *wordCount = d;
7287       return dest;
7288    }
7289    return null;
7290 }
7291
7292 namespace com;
7293
7294 #if !defined(MEMINFO) && defined(MEMTRACKING)
7295 import "Map"
7296
7297 Map<Class, int> blocksByClass { };
7298 Map<Class, uintsize> sizeByClass { };
7299 #endif
7300
7301 public void queryMemInfo(char * string)
7302 {
7303 #if !defined(MEMINFO) && defined(MEMTRACKING) && !defined(DISABLE_MEMMGR)
7304    char s[1024];
7305    int p;
7306    uint numBlocks = 0;
7307    uintsize totalMemUsed = 0;
7308    sprintf(s, "Total System Memory Usage: %.02f\n", TOTAL_MEM / 1048576.0f);
7309    strcat(string, s);
7310
7311    for(p = 0; pools && p < NUM_POOLS; p++)
7312    {
7313       BlockPool * pool = &pools[p];
7314       if(pool->totalSize)
7315       {
7316          numBlocks += pool->totalSize;
7317          sprintf(s, "%8d bytes: %d blocks in %d parts (%.02f mb used; taking up %.02f mb space)\n",
7318             pool->blockSize, pool->numBlocks, pool->numParts, pool->usedSpace / 1048576.0f, pool->totalSize * pool->blockSpace / 1048576.0f);
7319          totalMemUsed += pool->usedSpace;
7320          strcat(string, s);
7321       }
7322    }
7323
7324
7325    blocksByClass.Free();
7326    sizeByClass.Free();
7327    memMutex.Wait();
7328    for(p = 0; pools && p < NUM_POOLS; p++)
7329    {
7330       BlockPool * pool = &pools[p];
7331       MemBlock block;
7332       for(block = pool->first; block; block = block.next)
7333       {
7334          Class c = block._class;
7335          blocksByClass[c]++;
7336          sizeByClass[c] += block.size;
7337       }
7338    }
7339    memMutex.Release();
7340
7341    //for(c : blocksByClass)
7342    {
7343       MapIterator<Class, int> it { map = blocksByClass };
7344       while(it.Next())
7345       {
7346          int c = it.data;
7347          Class _class = it.key; //&c;
7348          uintsize size = sizeByClass[_class];
7349          float totalSize = (float) size / 1048576.0f;
7350          if(totalSize > 1)
7351          {
7352             sprintf(s, "%s (%d bytes): %d instances (%.02f mb used)\n", _class ? _class.name : "(none)", (int)size, c, totalSize);
7353             strcat(string, s);
7354          }
7355       }
7356    }
7357
7358    sprintf(s, "Non-pooled memory: %.02f\n", OUTSIDE_MEM / 1048576.0f);
7359    strcat(string, s);
7360    sprintf(s, "Total Memory in use: %.02f\n", (float)(totalMemUsed + OUTSIDE_MEM) / 1048576.0f);
7361    strcat(string, s);
7362
7363    sprintf(s, "Total Blocks Count: %d (%.02f mb overhead)\n", numBlocks, (float)sizeof(struct MemBlock) * numBlocks / 1048576.0f);
7364    strcat(string, s);
7365 #ifdef MEMORYGUARD
7366    sprintf(s, "MemoryGuard: %d blocks (%.02f mb RedZone, %.02f mb MemInfo)\n", memBlocks.count,
7367       numBlocks * 2 * REDZONE / 1048576.0f, sizeof(struct MemInfo) * memBlocks.count / 1048576.0f);
7368    strcat(string, s);
7369 #endif
7370 #endif
7371 }