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