compiler/libec: Null checks
[sdk] / compiler / libec / src / pass3.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4 #include "grammar.h"
5
6 extern External curExternal;
7 ///////////////// INSTANCE DECLARATION PASS ///////////////////////
8
9 // Returns true if we should add a * to the declarator
10 static int ReplaceClassSpec(OldList specs, Specifier spec, bool param)
11 {
12    if(spec.type == templateTypeSpecifier)
13    {
14       TemplateParameter parameter = spec.templateParameter;
15
16       if(!param && parameter.dataTypeString)
17       {
18          OldList * newSpecs = MkList();
19          Declarator decl = SpecDeclFromString(parameter.dataTypeString, newSpecs, null);
20          if(newSpecs->first)
21          {
22             Specifier newSpec = CopySpecifier(newSpecs->first);
23             *spec = *newSpec;
24             delete newSpec;
25          }
26          FreeList(newSpecs, FreeSpecifier);
27
28          if(decl)
29          {
30             bool isPointer = decl.type == pointerDeclarator;
31             if(decl)
32                FreeDeclarator(decl);
33             if(isPointer)
34                return 1;
35          }
36       }
37       else if(!param && parameter.dataType)
38       {
39          OldList * newSpecs = parameter.dataType.specifiers;
40          Declarator decl = parameter.dataType.decl;
41          if(newSpecs->first)
42          {
43             Specifier newSpec = CopySpecifier(newSpecs->first);
44             *spec = *newSpec;
45             delete newSpec;
46          }
47
48          if(decl)
49          {
50             bool isPointer = decl.type == pointerDeclarator;
51             if(isPointer)
52                return 1;
53          }
54       }
55       else
56       {
57          spec.type = nameSpecifier;
58          spec.name = CopyString("uint64");
59          spec.symbol = FindClass("uint64");
60       }
61    }
62
63    if(spec.type == nameSpecifier || spec.type == subClassSpecifier)
64    {
65       // TODO: Apply more care because nameSpecifier / subClassSpecifier use different parts of the union!
66       Symbol classSym = spec.symbol;
67       if(spec.type == subClassSpecifier)
68       {
69          classSym = FindClass("ecere::com::Class");
70       }
71
72       if(classSym)
73       {
74          Class _class = classSym.registered;
75
76          FreeSpecifierContents(spec);
77
78          spec.type = nameSpecifier;
79          if(_class && _class.type == structClass)
80          {
81             //Externalexternal;
82             char name[1024];
83             name[0] = 0;
84             FullClassNameCat(name, _class.fullName, false);
85             FreeSpecifierContents(spec);
86             spec.type = structSpecifier;
87             spec.baseSpecs = null;
88             spec.id = MkIdentifier(name);
89             spec.list = null;
90             spec.definitions = null;
91             spec.ctx = null;
92             spec.addNameSpace = false;
93          }
94          else if(_class && _class.type == noHeadClass)
95          {
96             char name[1024] = "";
97             FullClassNameCat(name, _class.fullName, false);
98             spec.type = structSpecifier;
99             spec.baseSpecs = null;
100             spec.id = MkIdentifier(name);
101             spec.list = null;
102             spec.definitions = null;
103             spec.ctx = null;
104             spec.addNameSpace = false;
105          }
106          else if(_class)
107          {
108             if((_class.type != systemClass ||
109                !strcmp(_class.fullName, "enum") ||
110                (_class.dataTypeString && !strcmp(_class.dataTypeString, "char *")) ||
111                //strcmp(_class.fullName, "bool") &&
112                !strcmp(_class.fullName, "uint64") ||
113                !strcmp(_class.fullName, "uint32") ||
114                !strcmp(_class.fullName, "uint16") ||
115                !strcmp(_class.fullName, "uintptr") ||
116                !strcmp(_class.fullName, "intptr") ||
117                !strcmp(_class.fullName, "uintsize") ||
118                !strcmp(_class.fullName, "intsize") ||
119                !strcmp(_class.fullName, "uint") ||
120                !strcmp(_class.fullName, "byte")))
121             {
122                if(_class.dataTypeString)
123                {
124                   if(!strcmp(_class.dataTypeString, "uint64") ||
125                      !strcmp(_class.dataTypeString, "uint32") ||
126                      !strcmp(_class.dataTypeString, "uint16") ||
127                      !strcmp(_class.dataTypeString, "uintptr") ||
128                      !strcmp(_class.dataTypeString, "intptr") ||
129                      !strcmp(_class.dataTypeString, "uintsize") ||
130                      !strcmp(_class.dataTypeString, "intsize") ||
131                      !strcmp(_class.dataTypeString, "uint") ||
132                      !strcmp(_class.dataTypeString, "byte"))
133                   {
134                      if(!_class.dataType)
135                         _class.dataType = ProcessTypeString(_class.dataTypeString, false);
136                      if(_class.dataType && _class.dataType.kind == classType)
137                         classSym = _class.dataType._class;
138                      else
139                         classSym = FindClass(_class.dataTypeString);
140                      _class = classSym ? classSym.registered : null;
141                   }
142
143                   spec.name = CopyString(!strcmp(_class.dataTypeString, "char *") ? "char" : _class.dataTypeString);
144                   spec.symbol = null;
145                }
146                else
147                {
148                   spec.name = CopyString(null);
149                   spec.symbol = null;
150                }
151             }
152             else if(!_class.base)
153             {
154                spec.type = baseSpecifier;
155                spec.specifier = VOID;
156                return 1;
157             }
158          }
159          else
160          {
161             spec.type = structSpecifier;
162             spec.id = MkIdentifier("__ecereNameSpace__ecere__com__Instance");
163             spec.list = null;
164             spec.baseSpecs = null;
165             spec.definitions = null;
166             spec.ctx = null;
167             spec.addNameSpace = false;
168          }
169
170          if(_class && _class.dataTypeString && !strcmp(_class.dataTypeString, "char *"))
171             return 1; //false;
172          if(!_class || _class.type == normalClass || _class.type == noHeadClass)
173             return 1;
174          else if(param && _class.type == structClass)
175             return 2;
176       }
177    }
178    else if(spec.type == baseSpecifier)
179    {
180       if(spec.specifier == ANY_OBJECT || spec.specifier == CLASS)
181       {
182          spec.specifier = CONST;
183          specs.Add(MkSpecifier(VOID));
184          return 1;
185       }
186    }
187    return 0;
188 }
189
190 static void ReplaceByInstancePtr(Specifier spec, Declarator * declPtr, int type)
191 {
192    Declarator decl = *declPtr;
193    if(decl && decl.type == pointerDeclarator)
194    {
195       // Pointers to simple classes shouldn't be added pointers
196       if(type == 2);
197       else
198       // Add pointer
199          decl.pointer.pointer = MkPointer(null, decl.pointer.pointer);
200    }
201    else
202    {
203       Declarator newDecl { };
204       if(decl)
205       {
206          *newDecl = *decl;
207          decl.declarator = newDecl;
208       }
209       else
210          decl = newDecl;
211       decl.type = pointerDeclarator;
212       decl.pointer.pointer = MkPointer(null, null);
213       *declPtr = decl;
214    }
215 }
216
217 static void InstDeclPassSpecifier(Specifier spec, bool byRefTypedObject)
218 {
219    switch(spec.type)
220    {
221       case baseSpecifier:
222          if(spec.specifier == TYPED_OBJECT)
223          {
224             spec.type = extendedSpecifier;
225             spec.extDecl = MkExtDeclString(CopyString(byRefTypedObject ?
226                "struct __ecereNameSpace__ecere__com__Class * class, void *" :
227                "struct __ecereNameSpace__ecere__com__Class * class, const void *"));
228             DeclareStruct(curExternal, "ecere::com::Class", false, true);
229          }
230          break;
231       case nameSpecifier:
232          break;
233       case enumSpecifier:
234       {
235          Enumerator e;
236          if(spec.list)
237          {
238             for(e = spec.list->first; e; e = e.next)
239             {
240
241             }
242          }
243          break;
244       }
245       case structSpecifier:
246       case unionSpecifier:
247       {
248          if(spec.definitions)
249          {
250             ClassDef def;
251             for(def = spec.definitions->first; def; def = def.next)
252                if(def.decl)
253                   InstDeclPassDeclaration(def.decl);
254          }
255          if(spec.id)
256             InstDeclPassIdentifier(spec.id);
257          break;
258       }
259       case extendedSpecifier:
260          if(spec.extDecl && spec.extDecl.type == extDeclString && spec.extDecl.s)
261          {
262             if(!strcmp(spec.extDecl.s, "dllexport"))
263             {
264                Specifier prevSpec;
265                delete spec.extDecl.s;
266                for(prevSpec = spec.prev; prevSpec; prevSpec = prevSpec.prev)
267                   if(prevSpec.type == baseSpecifier && prevSpec.specifier == EXTERN)
268                      break;
269                if(prevSpec)
270                {
271                   if(targetPlatform == win32)
272                      spec.extDecl.s = CopyString("__declspec(dllexport)");
273                   else
274                      spec.extDecl.s = CopyString("__attribute__ ((visibility(\"default\")))");
275                }
276                else
277                {
278                   if(targetPlatform == win32)
279                      spec.extDecl.s = CopyString("extern __declspec(dllexport)");
280                   else
281                      spec.extDecl.s = CopyString("extern __attribute__ ((visibility(\"default\")))");
282                }
283             }
284             else if(!strcmp(spec.extDecl.s, "stdcall") || !strcmp(spec.extDecl.s, "_stdcall") ||
285                !strcmp(spec.extDecl.s, "__stdcall") || !strcmp(spec.extDecl.s, "__stdcall__"))
286             {
287                delete spec.extDecl.s;
288                spec.extDecl.s = CopyString("ecere_stdcall");
289             }
290          }
291          break;
292    }
293 }
294
295 static void InstDeclPassDeclarator(Declarator decl)
296 {
297    switch(decl.type)
298    {
299       case structDeclarator:
300          if(decl.declarator)
301             InstDeclPassDeclarator(decl.declarator);
302          break;
303       case identifierDeclarator:
304       {
305          if(decl.identifier)
306             InstDeclPassIdentifier(decl.identifier);
307          break;
308       }
309       case bracketsDeclarator:
310          if(decl.declarator)
311             InstDeclPassDeclarator(decl.declarator);
312          break;
313       case arrayDeclarator:
314          if(decl.declarator)
315             InstDeclPassDeclarator(decl.declarator);
316          break;
317       case functionDeclarator:
318       {
319          if(decl.declarator)
320             InstDeclPassDeclarator(decl.declarator);
321          if(decl.function.parameters)
322          {
323             TypeName type;
324             if(decl.declarator)
325                InstDeclPassDeclarator(decl.declarator);
326             for(type = decl.function.parameters->first; type; type = type.next)
327             {
328                bool typedObject = false;
329                Specifier spec = null;
330                if(type.qualifiers)
331                {
332                   spec = (Specifier)type.qualifiers->first;
333                   if(spec && spec.type == nameSpecifier && !strcmp(spec.name, "class"))
334                      typedObject = true;
335                }
336
337                InstDeclPassTypeName(type, true);
338                if(typedObject)
339                {
340                   TypeName _class
341                   {
342                      qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
343                      declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
344                   };
345                   DeclareStruct(curExternal, "ecere::com::Class", false, true);
346                   decl.function.parameters->Insert(spec.prev, _class);
347                }
348             }
349          }
350          break;
351       }
352       case pointerDeclarator:
353       case extendedDeclarator:
354       case extendedDeclaratorEnd:
355          if((decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd) && decl.extended.extended)
356          {
357             if(decl.extended.extended.type == extDeclString && decl.extended.extended.s && !strcmp(decl.extended.extended.s, "dllexport"))
358             {
359                delete decl.extended.extended.s;
360                if(targetPlatform == win32)
361                   decl.extended.extended.s = CopyString("extern __declspec(dllexport)");
362                else
363                   decl.extended.extended.s = CopyString("extern __attribute__ ((visibility(\"default\")))");
364             }
365             else if(decl.extended.extended.type == extDeclString && decl.extended.extended.s &&
366                (!strcmp(decl.extended.extended.s, "stdcall") || !strcmp(decl.extended.extended.s, "_stdcall") ||
367                !strcmp(decl.extended.extended.s, "__stdcall") || !strcmp(decl.extended.extended.s, "__stdcall__")))
368             {
369                delete decl.extended.extended.s;
370                decl.extended.extended.s = CopyString("ecere_stdcall");
371             }
372          }
373          if(decl.declarator)
374             InstDeclPassDeclarator(decl.declarator);
375          break;
376    }
377 }
378
379 /*static */void InstDeclPassTypeName(TypeName type, bool param)
380 {
381    if(type.qualifiers)
382    {
383       Specifier spec;
384       for(spec = type.qualifiers->first; spec; spec = spec.next)
385       {
386          int result;
387          if((result = ReplaceClassSpec(type.qualifiers, spec, param)))
388             ReplaceByInstancePtr(spec, &type.declarator, result);
389          else
390          {
391             Symbol classSym = (spec.type == nameSpecifier) ? spec.symbol /*FindClass(spec.name)*/ : null;
392             if(type.classObjectType && (!classSym || (classSym && classSym.registered &&
393                (classSym.registered.type == enumClass || classSym.registered.type == bitClass || classSym.registered.type == unitClass))))
394                ReplaceByInstancePtr(spec, &type.declarator, 2);
395          }
396          InstDeclPassSpecifier(spec, type.declarator && type.declarator.type == pointerDeclarator);
397       }
398    }
399    if(type.declarator)
400       InstDeclPassDeclarator(type.declarator);
401 }
402
403 static void InstDeclPassIdentifier(Identifier id)
404 {
405    if(strchr(id.string, ':'))
406    {
407       char newID[1024];
408       int c;
409       char ch;
410       int len;
411       strcpy(newID, "__ecereNameSpace__");
412       len = strlen(newID);
413
414       for(c = 0; (ch = id.string[c]); c++)
415       {
416          if(ch == ':') ch = '_';
417
418          newID[len++] = ch;
419       }
420       newID[len] = 0;
421       delete id.string;
422       id.string = CopyString(newID);
423    }
424 }
425
426 /*static */bool IsVoidPtrCast(TypeName typeName)
427 {
428    bool result = false;
429    Declarator d = typeName.declarator;
430    if(d && d.type == pointerDeclarator && d.pointer.pointer && !d.pointer.pointer.pointer)
431    {
432       if(typeName.qualifiers)
433       {
434          Specifier s;
435          for(s = typeName.qualifiers->first; s; s = s.next)
436          {
437             if(s.type == baseSpecifier && s.specifier == VOID)
438                result = true;
439          }
440       }
441    }
442    return result;
443 }
444
445 static void AddPointerCast(Expression e)
446 {
447    Type src = e.expType;
448
449    if(src && (src.kind == templateType || src.kind == classType))
450    {
451       if(e.type != castExp || !IsVoidPtrCast(e.cast.typeName))
452       {
453          if(src) src.refCount++;
454          if(src.kind == templateType && src.templateParameter && src.templateParameter.type == type)
455          {
456             Type newType = null;
457             if(src.templateParameter.dataTypeString)
458                newType = ProcessTypeString(src.templateParameter.dataTypeString, false);
459             else if(src.templateParameter.dataType)
460                newType = ProcessType(src.templateParameter.dataType.specifiers, src.templateParameter.dataType.decl);
461             if(newType)
462             {
463                FreeType(src);
464                src = newType;
465             }
466          }
467          if(src && src.kind == classType && src._class)
468          {
469             Class sc = src._class.registered;
470             if(src.thisClassFrom && src.thisClassFrom.base)
471                sc = src.thisClassFrom;
472
473             if(sc && (sc.type == structClass || sc.type == noHeadClass))
474             {
475                Type dest = e.destType;
476
477                if(dest && (dest.kind == templateType || dest.kind == classType))
478                {
479                   if(dest) dest.refCount++;
480
481                   if(dest.kind == templateType && dest.templateParameter && dest.templateParameter.type == type)
482                   {
483                      Type newType = null;
484                      if(dest.templateParameter.dataTypeString)
485                         newType = ProcessTypeString(dest.templateParameter.dataTypeString, false);
486                      else if(dest.templateParameter.dataType)
487                         newType = ProcessType(dest.templateParameter.dataType.specifiers, dest.templateParameter.dataType.decl);
488                      if(newType)
489                      {
490                         FreeType(dest);
491                         dest = newType;
492                      }
493                   }
494                   if(!dest.passAsTemplate && dest.kind == classType && dest._class && dest._class.registered)
495                   {
496                      Class dc = dest._class.registered;
497
498                      if(sc.templateClass) sc = sc.templateClass;
499                      if(dc.templateClass) dc = dc.templateClass;
500                      if(dc.base && sc != dc)
501                      {
502                         e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
503                         e.type = castExp;
504                         e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
505                      }
506                   }
507                   FreeType(dest);
508                }
509             }
510          }
511          FreeType(src);
512       }
513    }
514    else if(src && src.kind == intPtrType && e.destType && e.destType.classObjectType)
515    {
516       Expression nbExp = GetNonBracketsExp(e);
517       if(nbExp.type != castExp || !IsVoidPtrCast(nbExp.cast.typeName))
518       {
519          e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
520          e.type = castExp;
521          e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
522       }
523    }
524 }
525
526 static void InstDeclPassExpression(Expression exp)
527 {
528    switch(exp.type)
529    {
530       case identifierExp:
531       {
532          if(exp.identifier)
533             InstDeclPassIdentifier(exp.identifier);
534          break;
535       }
536       case constantExp:
537          break;
538       case stringExp:
539          break;
540       case opExp:
541          if(exp.op.exp1)
542             InstDeclPassExpression(exp.op.exp1);
543          if(exp.op.exp2)
544          {
545             InstDeclPassExpression(exp.op.exp2);
546             if(exp.op.op != '=' && exp.op.exp1 && exp.op.exp1.expType && exp.op.exp1.expType.kind == pointerType && exp.op.exp1.expType.type && exp.op.exp1.expType.type.kind == templateType &&
547                exp.op.exp2.expType && exp.op.exp2.expType.kind == pointerType && exp.op.exp2.expType.type && exp.op.exp2.expType.type.kind == templateType)
548             {
549                Expression e = exp.op.exp2;
550                e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
551                e.type = castExp;
552                e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
553
554                e = exp.op.exp1;
555                e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
556                e.type = castExp;
557                e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
558             }
559             else if(exp.op.exp1 && (exp.op.op == '=' || exp.op.op == EQ_OP || exp.op.op == NE_OP))
560                AddPointerCast(exp.op.exp2);
561          }
562          break;
563       case extensionExpressionExp:
564       case bracketsExp:
565       {
566          Expression e;
567          for(e = exp.list->first; e; e = e.next)
568             InstDeclPassExpression(e);
569          break;
570       }
571       case indexExp:
572       {
573          Expression e;
574          InstDeclPassExpression(exp.index.exp);
575          for(e = exp.index.index->first; e; e = e.next)
576             InstDeclPassExpression(e);
577          break;
578       }
579       case callExp:
580       {
581          Expression e;
582          InstDeclPassExpression(exp.call.exp);
583          if(exp.call.arguments)
584          {
585             for(e = exp.call.arguments->first; e; e = e.next)
586             {
587                bool addCast = false;
588                InstDeclPassExpression(e);
589                AddPointerCast(e);
590
591                if(e.expType && e.expType.kind == pointerType && e.expType.type && (e.expType.type.kind == classType || (e.expType.type.kind == pointerType && e.expType.type.type && e.expType.type.type.kind != voidType)) &&
592                   e.destType && e.destType.kind == pointerType && e.destType.type && e.destType.type.kind == pointerType && e.destType.type.type && e.destType.type.type.kind == voidType)
593                   addCast = true;
594                // Fix for adding a cast to Unserialize with a struct passed as a parameter:
595                else if(e.expType && e.expType.kind == classType && e.expType._class && e.expType._class.registered && e.expType._class.registered.type == structClass && e.byReference &&
596                   e.destType && e.destType.kind == classType && e.destType.classObjectType && e.destType.byReference)
597                   addCast = true;
598
599                if(addCast && (e.type != castExp || !IsVoidPtrCast(e.cast.typeName)))
600                {
601                   e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
602                   e.type = castExp;
603                   e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
604                }
605             }
606          }
607          break;
608       }
609       case memberExp:
610       {
611          if(exp.member.exp)
612             InstDeclPassExpression(exp.member.exp);
613          break;
614       }
615       case pointerExp:
616       {
617          if(exp.member.exp)
618             InstDeclPassExpression(exp.member.exp);
619          break;
620       }
621       case typeSizeExp:
622          InstDeclPassTypeName(exp.typeName, false);
623          break;
624       case castExp:
625       {
626          Type type = exp.expType;
627          // Remove casts to simple structs... (Watch out for pointers later...)
628          if(type && type.kind == classType && type._class.registered && type._class.registered.type == structClass && !exp.needCast)
629          {
630             if(exp.destType && exp.destType.classObjectType == typedObject && exp.destType.byReference)
631             {
632                // For Unserialize with a StaticString
633                FreeTypeName(exp.cast.typeName);
634                exp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, MkPointer(null, null)), null));
635             }
636             else
637             {
638                Expression castExp = exp.cast.exp;
639                Expression prev = exp.prev, next = exp.next;
640                exp.cast.exp = null;
641                FreeExpContents(exp);
642                FreeType(exp.expType);
643                FreeType(exp.destType);
644                *exp = *castExp;
645                delete castExp;
646                exp.prev = prev;
647                exp.next = next;
648                InstDeclPassExpression(exp);
649             }
650          }
651          else
652          {
653             if(exp.expType && exp.expType.kind == pointerType)
654             {
655                if(exp.cast.exp && exp.cast.exp.expType && exp.cast.exp.expType.kind == templateType && !exp.cast.exp.expType.isPointerType)
656                   exp.cast.exp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), exp.cast.exp);
657             }
658
659             InstDeclPassTypeName(exp.cast.typeName, exp.usage.usageArg /*false*/);
660             if(exp.cast.exp)
661             {
662                if(exp.expType && exp.expType.kind == templateType && exp.destType &&
663                   (exp.destType.passAsTemplate || (!exp.destType.templateParameter || (!exp.destType.templateParameter.dataType && !exp.destType.templateParameter.dataTypeString))) &&
664                   exp.cast.exp.expType && !exp.cast.exp.expType.passAsTemplate && exp.cast.exp.expType.isPointerType)
665                   exp.cast.exp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), exp.cast.exp);
666                InstDeclPassExpression(exp.cast.exp);
667             }
668          }
669          break;
670       }
671       case conditionExp:
672       {
673          Expression e;
674          InstDeclPassExpression(exp.cond.cond);
675          for(e = exp.cond.exp->first; e; e = e.next)
676             InstDeclPassExpression(e);
677          if(exp.cond.elseExp)
678             InstDeclPassExpression(exp.cond.elseExp);
679          break;
680       }
681       case extensionCompoundExp:
682       {
683          InstDeclPassStatement(exp.compound);
684          break;
685       }
686       case vaArgExp:
687       {
688          InstDeclPassExpression(exp.vaArg.exp);
689          break;
690       }
691       case extensionInitializerExp:
692       {
693          InstDeclPassTypeName(exp.initializer.typeName, false);
694          InstDeclPassInitializer(exp.initializer.initializer);
695          break;
696       }
697    }
698 }
699
700 static void InstDeclPassInitializer(Initializer init)
701 {
702    switch(init.type)
703    {
704       case expInitializer:
705          if(init.exp)
706          {
707             InstDeclPassExpression(init.exp);
708             AddPointerCast(init.exp);
709          }
710          break;
711       case listInitializer:
712       {
713          Initializer i;
714          for(i = init.list->first; i; i = i.next)
715             InstDeclPassInitializer(i);
716          break;
717       }
718    }
719 }
720
721 static void InstDeclPassDeclaration(Declaration decl)
722 {
723    switch(decl.type)
724    {
725       case initDeclaration:
726       {
727          if(decl.specifiers)
728          {
729             Specifier spec;
730             for(spec = decl.specifiers->first; spec; spec = spec.next)
731             {
732                int type;
733                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
734                {
735                   InitDeclarator d;
736                   if(decl.declarators)
737                   {
738                      for(d = decl.declarators->first; d; d = d.next)
739                         ReplaceByInstancePtr(spec, &d.declarator, type);
740                   }
741                }
742                InstDeclPassSpecifier(spec, false);
743             }
744          }
745          if(decl.declarators)
746          {
747             InitDeclarator d;
748             for(d = decl.declarators->first; d; d = d.next)
749             {
750                InstDeclPassDeclarator(d.declarator);
751                if(d.initializer)
752                   InstDeclPassInitializer(d.initializer);
753             }
754          }
755          break;
756       }
757       case structDeclaration:
758       {
759          if(decl.specifiers)
760          {
761             Specifier spec;
762             for(spec = decl.specifiers->first; spec; spec = spec.next)
763             {
764                int type;
765                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
766                {
767                   if(decl.declarators)
768                   {
769                      Declarator d;
770                      for(d = decl.declarators->first; d; d = d.next)
771                         ReplaceByInstancePtr(spec, &d, type);
772                   }
773                }
774                InstDeclPassSpecifier(spec, false);
775             }
776          }
777
778          if(decl.declarators)
779          {
780             Declarator d;
781             for(d = decl.declarators->first; d; d = d.next)
782                InstDeclPassDeclarator(d);
783          }
784          break;
785       }
786       // This should be removed by now?
787       case instDeclaration:
788          // InstDeclPassInstantiation(decl.inst);
789          break;
790    }
791 }
792
793 static void InstDeclPassStatement(Statement stmt)
794 {
795    switch(stmt.type)
796    {
797       case badDeclarationStmt:
798          if(stmt.decl)
799             InstDeclPassDeclaration(stmt.decl);
800          break;
801       case labeledStmt:
802          InstDeclPassStatement(stmt.labeled.stmt);
803          break;
804       case caseStmt:
805          // This expression should be constant...
806          if(stmt.caseStmt.exp)
807             InstDeclPassExpression(stmt.caseStmt.exp);
808          if(stmt.caseStmt.stmt)
809             InstDeclPassStatement(stmt.caseStmt.stmt);
810          break;
811       case compoundStmt:
812       {
813          Declaration decl;
814          Statement s;
815          Context prevContext = curContext;
816
817          if(!stmt.compound.isSwitch)
818             curContext = stmt.compound.context;
819
820          if(stmt.compound.declarations)
821          {
822             for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
823                InstDeclPassDeclaration(decl);
824          }
825          if(stmt.compound.statements)
826          {
827             for(s = stmt.compound.statements->first; s; s = s.next)
828                InstDeclPassStatement(s);
829          }
830          curContext = prevContext;
831          break;
832       }
833       case expressionStmt:
834       {
835          if(stmt.expressions)
836          {
837             Expression exp;
838             for(exp = stmt.expressions->first; exp; exp = exp.next)
839                InstDeclPassExpression(exp);
840          }
841          break;
842       }
843       case ifStmt:
844       {
845          if(stmt.ifStmt.exp)
846          {
847             Expression exp;
848             for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
849                InstDeclPassExpression(exp);
850          }
851          if(stmt.ifStmt.stmt)
852             InstDeclPassStatement(stmt.ifStmt.stmt);
853          if(stmt.ifStmt.elseStmt)
854             InstDeclPassStatement(stmt.ifStmt.elseStmt);
855          break;
856       }
857       case switchStmt:
858       {
859          Expression exp;
860          if(stmt.switchStmt.exp)
861          {
862             for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
863                InstDeclPassExpression(exp);
864          }
865          InstDeclPassStatement(stmt.switchStmt.stmt);
866          break;
867       }
868       case whileStmt:
869       {
870          Expression exp;
871          if(stmt.whileStmt.exp)
872          {
873             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
874                InstDeclPassExpression(exp);
875          }
876          InstDeclPassStatement(stmt.whileStmt.stmt);
877          break;
878       }
879       case doWhileStmt:
880       {
881          if(stmt.doWhile.exp)
882          {
883             Expression exp;
884             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
885                InstDeclPassExpression(exp);
886          }
887          if(stmt.doWhile.stmt)
888             InstDeclPassStatement(stmt.doWhile.stmt);
889          break;
890       }
891       case forStmt:
892       {
893          Expression exp;
894          if(stmt.forStmt.init)
895             InstDeclPassStatement(stmt.forStmt.init);
896          if(stmt.forStmt.check)
897             InstDeclPassStatement(stmt.forStmt.check);
898          if(stmt.forStmt.increment)
899          {
900             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
901                InstDeclPassExpression(exp);
902          }
903          if(stmt.forStmt.stmt)
904             InstDeclPassStatement(stmt.forStmt.stmt);
905          break;
906       }
907       case gotoStmt:
908          break;
909       case continueStmt:
910          break;
911       case breakStmt:
912          break;
913       case returnStmt:
914       {
915          Expression exp;
916          if(stmt.expressions)
917          {
918             for(exp = stmt.expressions->first; exp; exp = exp.next)
919                InstDeclPassExpression(exp);
920             AddPointerCast(stmt.expressions->last);
921          }
922          break;
923       }
924       case asmStmt:
925       {
926          AsmField field;
927          if(stmt.asmStmt.inputFields)
928          {
929             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
930                if(field.expression)
931                   InstDeclPassExpression(field.expression);
932          }
933          if(stmt.asmStmt.outputFields)
934          {
935             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
936                if(field.expression)
937                   InstDeclPassExpression(field.expression);
938          }
939          if(stmt.asmStmt.clobberedFields)
940          {
941             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
942                if(field.expression)
943                   InstDeclPassExpression(field.expression);
944          }
945          break;
946       }
947    }
948 }
949
950 void TopoSort(OldList * input)
951 {
952    OldList L { };
953    OldList S { };
954    OldList B { };
955    External n, next;
956    //External x;
957
958    for(n = input->first; n; n = next)
959    {
960       next = n.next;
961       if(n.type == declarationExternal && !n.declaration)
962       {
963          input->Remove(n);
964          if(n.symbol && n.symbol.structExternal == n)
965             n.symbol.structExternal = null;
966          FreeExternal(n);
967       }
968       else if(!n.incoming.count)
969       {
970          input->Remove(n);
971          S.Add(n);
972       }
973       else if(!n.nonBreakableIncoming)
974       {
975          input->Remove(n);
976          B.Add(n);
977       }
978    }
979 /*
980          for(x = input->first; x; x = x.next)
981          {
982             int count = 0;
983             for(e : x.incoming; !e.breakable)
984                count++;
985             if(count != x.nonBreakableIncoming)
986                printf("Bug in input");
987
988             if(!x.incoming.count)
989                printf("This node should be in S!\n");
990             for(e : x.incoming)
991             {
992                External y, from = e.from;
993                for(y = input->first; y; y = y.next)
994                   if(y == from)
995                      break;
996                if(!y)
997                {
998                   for(y = B.first; y; y = y.next)
999                      if(y == from)
1000                         break;
1001                }
1002
1003                if(!y)
1004                {
1005                   for(y = S.first; y; y = y.next)
1006                      if(y == from)
1007                         break;
1008                }
1009                if(!y)
1010                {
1011                   printf("This node is nowhere!\n");
1012                }
1013             }
1014          }*/
1015
1016    while(true)
1017    {
1018       TopoEdge e, ne;
1019       if((n = S.first))
1020       {
1021          /*
1022          for(x = input->first; x; x = x.next)
1023          {
1024             int count = 0;
1025             for(e : x.incoming; !e.breakable)
1026                count++;
1027             if(count != x.nonBreakableIncoming)
1028                printf("Bug in input");
1029             if(!x.incoming.count)
1030                printf("This node should be in S!\n");
1031             for(e : x.incoming)
1032             {
1033                External y, from = e.from;
1034                for(y = input->first; y; y = y.next)
1035                   if(y == from)
1036                      break;
1037                if(!y)
1038                {
1039                   for(y = B.first; y; y = y.next)
1040                      if(y == from)
1041                         break;
1042                }
1043
1044                if(!y)
1045                {
1046                   for(y = S.first; y; y = y.next)
1047                      if(y == from)
1048                         break;
1049                }
1050                if(!y)
1051                {
1052                   printf("This node is nowhere!\n");
1053                }
1054             }
1055          }*/
1056
1057          //DebugPrint("*** Free Node: [", n.id, "]\n\t", n.output);
1058          S.Remove((IteratorPointer)n);
1059
1060          /*
1061          if(n && n.symbol && n.symbol.string && !strcmp(n.symbol.string, "ecere::com::Instance"))
1062             printf("Adding Instance\n");
1063          */
1064
1065          L.Add(n);
1066          for(e = n.outgoing.first; e; e = ne)
1067          {
1068             External m = e.to;
1069             OldList * list;
1070
1071             //DebugPrint(" This Free Node has an edge to [", m.id, "] ", m.output);
1072             if(m.nonBreakableIncoming)
1073             {
1074                //DebugPrint("... which we think is in input");
1075                list = input;
1076             }
1077             else
1078             {
1079                //DebugPrint("... which we think is in B");
1080                list = &B;
1081             }
1082
1083             if(!list->count)
1084                PrintLn("!!! Something's wrong !!!");
1085             ne = e.out.next;
1086
1087             if(!e.breakable)
1088             {
1089 #ifdef _DEBUG
1090                if(!m.nonBreakableIncoming)
1091                   printf("Bug");
1092 #endif
1093                m.nonBreakableIncoming--;
1094                //DebugPrint("Reducing non breakable incoming, now ", m.nonBreakableIncoming);
1095             }
1096
1097             n.outgoing.Remove((IteratorPointer)e);
1098             m.incoming.Remove((IteratorPointer)e);
1099             delete e;
1100
1101             if(!m.incoming.count)
1102             {
1103                //DebugPrint("Last edge to this node taken out, moving to S...");
1104                list->Remove(m);
1105                S.Add(m);
1106             }
1107             else if(!m.nonBreakableIncoming)
1108             {
1109                //DebugPrint("Last non-breakable edge to this node taken out, moving to B...");
1110                list->Remove(m);
1111                B.Add(m);
1112             }
1113          }
1114       }
1115       else if((n = B.first))
1116       {
1117          //DebugPrint("Breaking some of the ", n.incoming.count, " incoming edges to [", n.id, "] ", n.output);
1118          B.Remove((IteratorPointer)n);
1119
1120          // Break the edges of this node
1121          for(e = n.incoming.first; e; e = ne)
1122          {
1123             TopoEdge e2, n2;
1124             External m = e.from;
1125             External f;
1126 /*
1127          for(x = input->first; x; x = x.next)
1128          {
1129             int count = 0;
1130             for(e : x.incoming; !e.breakable)
1131                count++;
1132             if(count != x.nonBreakableIncoming)
1133                printf("Bug in input");
1134             if(!x.incoming.count)
1135                printf("This node should be in S!\n");
1136             for(e : x.incoming)
1137             {
1138                External y, from = e.from;
1139                for(y = input->first; y; y = y.next)
1140                   if(y == from)
1141                      break;
1142                if(!y)
1143                {
1144                   for(y = B.first; y; y = y.next)
1145                      if(y == from)
1146                         break;
1147                }
1148
1149                if(!y)
1150                {
1151                   for(y = S.first; y; y = y.next)
1152                      if(y == from)
1153                         break;
1154                }
1155                if(!y && from != n)
1156                {
1157                   printf("This node is nowhere!\n");
1158                }
1159             }
1160          }*/
1161
1162             f = m.ForwardDeclare();
1163             ne = e.in.next;
1164 /*
1165          for(x = input->first; x; x = x.next)
1166          {
1167             int count = 0;
1168             for(e : x.incoming; !e.breakable)
1169                count++;
1170             if(count != x.nonBreakableIncoming)
1171                printf("Bug in input");
1172             if(!x.incoming.count)
1173                printf("This node should be in S!\n");
1174             for(e : x.incoming)
1175             {
1176                External y, from = e.from;
1177                for(y = input->first; y; y = y.next)
1178                   if(y == from)
1179                      break;
1180                if(!y)
1181                {
1182                   for(y = B.first; y; y = y.next)
1183                      if(y == from)
1184                         break;
1185                }
1186
1187                if(!y)
1188                {
1189                   for(y = S.first; y; y = y.next)
1190                      if(y == from)
1191                         break;
1192                }
1193                if(!y && from != n && from != f)
1194                {
1195                   printf("This node is nowhere!\n");
1196                }
1197             }
1198          }
1199 */
1200             // Recheck input for edges created by forward declaration
1201             {
1202                External c, next;
1203                for(c = input->first; c; c = next)
1204                {
1205                   next = c.next;
1206                   if(!c.incoming.count)
1207                   {
1208                      input->Remove(c);
1209                      S.Add(c);
1210                   }
1211                   else if(!c.nonBreakableIncoming)
1212                   {
1213                      input->Remove(c);
1214                      B.Add(c);
1215                   }
1216                }
1217             }
1218
1219             //DebugPrint("Breaking edge from ", e.from.id, " to ", e.to.id);
1220             //DebugPrint("Creating a forward decl node [", f.id, "] for [", m.id, "]");
1221
1222             for(e2 = m.outgoing.first; e2; e2 = n2)
1223             {
1224                n2 = e2.out.next;
1225                if(e2.breakable)
1226                {
1227                   External to = e2.to;
1228
1229                   if(e2 == e)
1230                      ;//DebugPrint("Breaking this particular connection");
1231                   else
1232                      ;//DebugPrint("Also redirecting connection from ", m.id, " to ", to.id, " to come from ", f.id, " instead.");
1233                   e2.breakable = false;
1234                   e2.from = f;
1235                   m.outgoing.Remove((IteratorPointer)e2);
1236                   f.outgoing.Add(e2);
1237                   to.nonBreakableIncoming++;
1238                   if(e2 != e && to.nonBreakableIncoming == 1)
1239                   {
1240                      // If this node was previously in B, move it to input
1241                      B.Remove(to);
1242                      input->Add(to);
1243                   }
1244
1245                   //DebugPrint("Node ", e2.to.id, " now has ", e2.to.nonBreakableIncoming, " non-breakable incoming edges.");
1246                }
1247             }
1248 /*
1249          for(x = input->first; x; x = x.next)
1250          {
1251             int count = 0;
1252             for(e : x.incoming; !e.breakable)
1253                count++;
1254             if(count != x.nonBreakableIncoming)
1255                printf("Bug in input");
1256             if(!x.incoming.count)
1257                printf("This node should be in S!\n");
1258             for(e : x.incoming)
1259             {
1260                External y, from = e.from;
1261                for(y = input->first; y; y = y.next)
1262                   if(y == from)
1263                      break;
1264                if(!y)
1265                {
1266                   for(y = B.first; y; y = y.next)
1267                      if(y == from)
1268                         break;
1269                }
1270
1271                if(!y)
1272                {
1273                   for(y = S.first; y; y = y.next)
1274                      if(y == from)
1275                         break;
1276                }
1277                if(!y && from != n && from != f)
1278                {
1279                   printf("This node is nowhere!\n");
1280                }
1281             }
1282          }*/
1283             if(!f.incoming.count)
1284                S.Add(f);
1285             else if(!f.nonBreakableIncoming)
1286                B.Add(f);
1287             else
1288                input->Add(f);
1289 /*
1290          for(x = input->first; x; x = x.next)
1291          {
1292             int count = 0;
1293             for(e : x.incoming; !e.breakable)
1294                count++;
1295             if(count != x.nonBreakableIncoming)
1296                printf("Bug in input");
1297             if(!x.incoming.count)
1298                printf("This node should be in S!\n");
1299             for(e : x.incoming)
1300             {
1301                External y, from = e.from;
1302                for(y = input->first; y; y = y.next)
1303                   if(y == from)
1304                      break;
1305                if(!y)
1306                {
1307                   for(y = B.first; y; y = y.next)
1308                      if(y == from)
1309                         break;
1310                }
1311
1312                if(!y)
1313                {
1314                   for(y = S.first; y; y = y.next)
1315                      if(y == from)
1316                         break;
1317                }
1318
1319                if(!y)
1320                {
1321                   for(y = L.first; y; y = y.next)
1322                      if(y == from)
1323                      {
1324                         PrintLn("This node is already in L!");
1325                         break;
1326                      }
1327                }
1328
1329                if(!y && from != n)
1330                {
1331                   ConsoleFile file { };
1332                   printf("This node is nowhere!\n");
1333                   OutputExternal(from, file);
1334                   delete file;
1335                }
1336             }
1337          }
1338 */
1339             // Avoid needless edge breaking by processing a node as soon as one shows up in S
1340             if(S.first)
1341                break;
1342          }
1343
1344          // Put n back in input because it now has unbreakable edges
1345          input->Add(n);
1346       }
1347       else
1348       {
1349          if(input->count)
1350          {
1351 #ifdef _DEBUG
1352             ConsoleFile f { };
1353             External e = input->first;
1354 #endif
1355             Compiler_Error("declarations cycles found\n");
1356 #ifdef _DEBUG
1357             //OutputTree(input, f);
1358 /*
1359          for(x = input->first; x; x = x.next)
1360          {
1361             int count = 0;
1362             for(e : x.incoming; !e.breakable)
1363                count++;
1364             if(count != x.nonBreakableIncoming)
1365                printf("Bug in input");
1366             if(!x.incoming.count)
1367                printf("This node should be in S!\n");
1368
1369             for(e : x.incoming)
1370             {
1371                External y, from = e.from;
1372                for(y = input->first; y; y = y.next)
1373                   if(y == from)
1374                      break;
1375                if(!y)
1376                {
1377                   for(y = B.first; y; y = y.next)
1378                      if(y == from)
1379                         break;
1380                }
1381
1382                if(!y)
1383                {
1384                   for(y = S.first; y; y = y.next)
1385                      if(y == from)
1386                         break;
1387                }
1388                if(!y)
1389                {
1390                   printf("This node is nowhere!\n");
1391                }
1392             }
1393          }
1394 */
1395             SetOutputLineNumbers(false);
1396             OutputExternal(e, f);
1397
1398             PrintLn("\nDepends on:\n");
1399             { TopoEdge i; for(i = e.incoming.last; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
1400
1401             OutputExternal(e, f);
1402
1403             PrintLn("\nWhile that depends on:\n");
1404             { TopoEdge i; for(i = e.incoming.first; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
1405
1406             OutputExternal(e, f);
1407
1408             PrintLn("\nWhile that depends on:\n");
1409             { TopoEdge i; for(i = e.incoming.first; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
1410
1411             OutputExternal(e, f);
1412
1413             PrintLn("\nWhile that depends on:\n");
1414             { TopoEdge i; for(i = e.incoming.first; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
1415
1416             OutputExternal(e, f);
1417             delete f;
1418
1419             system("pause");
1420
1421             while((e = input->first))
1422             {
1423                input->Remove(e);
1424                L.Add(e);
1425             }
1426             *input = L;
1427 #endif
1428          }
1429          else
1430             *input = L;
1431          break;
1432       }
1433    }
1434
1435    for(n = input->first; n; n = next)
1436    {
1437       next = n.next;
1438       if(n.type == declarationExternal && (!n.declaration || ((!n.declaration.specifiers || !n.declaration.specifiers->count) && (!n.declaration.declarators || !n.declaration.declarators->count))))
1439       {
1440          input->Remove(n);
1441          if(n.symbol && n.symbol.structExternal == n)
1442             n.symbol.structExternal = null;
1443          FreeExternal(n);
1444       }
1445    }
1446 }
1447
1448 public void ProcessInstanceDeclarations()
1449 {
1450    External external;
1451    curContext = globalContext;
1452    for(external = ast->first; external; external = external.next)
1453    {
1454       curExternal = external;
1455       if(external.type == functionExternal)
1456       {
1457          FunctionDefinition func = external.function;
1458          if(func.specifiers)
1459          {
1460             Specifier spec;
1461             for(spec = func.specifiers->first; spec; spec = spec.next)
1462             {
1463                int type;
1464                if((type = ReplaceClassSpec(func.specifiers, spec, false)))
1465                   ReplaceByInstancePtr(spec, &func.declarator, type);
1466                InstDeclPassSpecifier(spec, false);
1467             }
1468          }
1469          InstDeclPassDeclarator(func.declarator);
1470          if(func.body)
1471             InstDeclPassStatement(func.body);
1472       }
1473       else if(external.type == declarationExternal)
1474       {
1475          if(external.declaration)
1476             InstDeclPassDeclaration(external.declaration);
1477       }
1478    }
1479
1480    // Perform topological sort
1481    TopoSort(ast);
1482 }