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