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