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