compiler/bootstrap: Fully automated (make updatebootstrap)
[sdk] / compiler / libec / src / pass3.ec
index b4a84bc..b411fae 100644 (file)
@@ -177,9 +177,10 @@ static int ReplaceClassSpec(OldList specs, Specifier spec, bool param)
    }
    else if(spec.type == baseSpecifier)
    {
-      if(spec.specifier == ANY_OBJECT)
+      if(spec.specifier == ANY_OBJECT || spec.specifier == CLASS)
       {
-         spec.specifier = VOID;
+         spec.specifier = CONST;
+         specs.Add(MkSpecifier(VOID));
          return 1;
       }
    }
@@ -213,7 +214,7 @@ static void ReplaceByInstancePtr(Specifier spec, Declarator * declPtr, int type)
    }
 }
 
-static void InstDeclPassSpecifier(Specifier spec)
+static void InstDeclPassSpecifier(Specifier spec, bool byRefTypedObject)
 {
    switch(spec.type)
    {
@@ -221,7 +222,10 @@ static void InstDeclPassSpecifier(Specifier spec)
          if(spec.specifier == TYPED_OBJECT)
          {
             spec.type = extendedSpecifier;
-            spec.extDecl = MkExtDeclString(CopyString("struct __ecereNameSpace__ecere__com__Class * class, void *"));
+            spec.extDecl = MkExtDeclString(CopyString(byRefTypedObject ?
+               "struct __ecereNameSpace__ecere__com__Class * class, void *" :
+               "struct __ecereNameSpace__ecere__com__Class * class, const void *"));
+            DeclareStruct(curExternal, "ecere::com::Class", false, true);
          }
          break;
       case nameSpecifier:
@@ -281,10 +285,7 @@ static void InstDeclPassSpecifier(Specifier spec)
                !strcmp(spec.extDecl.s, "__stdcall") || !strcmp(spec.extDecl.s, "__stdcall__"))
             {
                delete spec.extDecl.s;
-               if(targetPlatform == win32)
-                  spec.extDecl.s = CopyString("__attribute__((__stdcall__))");
-               else
-                  spec.extDecl.s = CopyString("");
+               spec.extDecl.s = CopyString("stdcall");
             }
          }
          break;
@@ -341,6 +342,7 @@ static void InstDeclPassDeclarator(Declarator decl)
                      qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
                      declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
                   };
+                  DeclareStruct(curExternal, "ecere::com::Class", false, true);
                   decl.function.parameters->Insert(spec.prev, _class);
                }
             }
@@ -365,10 +367,7 @@ static void InstDeclPassDeclarator(Declarator decl)
                !strcmp(decl.extended.extended.s, "__stdcall") || !strcmp(decl.extended.extended.s, "__stdcall__")))
             {
                delete decl.extended.extended.s;
-               if(targetPlatform == win32)
-                  decl.extended.extended.s = CopyString("__attribute__((__stdcall__))");
-               else
-                  decl.extended.extended.s = CopyString("");
+               decl.extended.extended.s = CopyString("stdcall");
             }
          }
          if(decl.declarator)
@@ -394,7 +393,7 @@ static void InstDeclPassDeclarator(Declarator decl)
                (classSym.registered.type == enumClass || classSym.registered.type == bitClass || classSym.registered.type == unitClass))))
                ReplaceByInstancePtr(spec, &type.declarator, 2);
          }
-         InstDeclPassSpecifier(spec);
+         InstDeclPassSpecifier(spec, type.declarator && type.declarator.type == pointerDeclarator);
       }
    }
    if(type.declarator)
@@ -424,6 +423,106 @@ static void InstDeclPassIdentifier(Identifier id)
    }
 }
 
+/*static */bool IsVoidPtrCast(TypeName typeName)
+{
+   bool result = false;
+   Declarator d = typeName.declarator;
+   if(d && d.type == pointerDeclarator && d.pointer.pointer && !d.pointer.pointer.pointer)
+   {
+      if(typeName.qualifiers)
+      {
+         Specifier s;
+         for(s = typeName.qualifiers->first; s; s = s.next)
+         {
+            if(s.type == baseSpecifier && s.specifier == VOID)
+               result = true;
+         }
+      }
+   }
+   return result;
+}
+
+static void AddPointerCast(Expression e)
+{
+   Type src = e.expType;
+
+   if(src && (src.kind == templateType || src.kind == classType))
+   {
+      if(e.type != castExp || !IsVoidPtrCast(e.cast.typeName))
+      {
+         if(src) src.refCount++;
+         if(src.kind == templateType && src.templateParameter && src.templateParameter.type == type)
+         {
+            Type newType = null;
+            if(src.templateParameter.dataTypeString)
+               newType = ProcessTypeString(src.templateParameter.dataTypeString, false);
+            else if(src.templateParameter.dataType)
+               newType = ProcessType(src.templateParameter.dataType.specifiers, src.templateParameter.dataType.decl);
+            if(newType)
+            {
+               FreeType(src);
+               src = newType;
+            }
+         }
+         if(src && src.kind == classType && src._class)
+         {
+            Class sc = src._class.registered;
+            if(src.thisClassFrom && src.thisClassFrom.base)
+               sc = src.thisClassFrom;
+
+            if(sc && (sc.type == structClass || sc.type == noHeadClass))
+            {
+               Type dest = e.destType;
+
+               if(dest && (dest.kind == templateType || dest.kind == classType))
+               {
+                  if(dest) dest.refCount++;
+
+                  if(dest.kind == templateType && dest.templateParameter && dest.templateParameter.type == type)
+                  {
+                     Type newType = null;
+                     if(dest.templateParameter.dataTypeString)
+                        newType = ProcessTypeString(dest.templateParameter.dataTypeString, false);
+                     else if(dest.templateParameter.dataType)
+                        newType = ProcessType(dest.templateParameter.dataType.specifiers, dest.templateParameter.dataType.decl);
+                     if(newType)
+                     {
+                        FreeType(dest);
+                        dest = newType;
+                     }
+                  }
+                  if(!dest.passAsTemplate && dest.kind == classType && dest._class && dest._class.registered)
+                  {
+                     Class dc = dest._class.registered;
+
+                     if(sc.templateClass) sc = sc.templateClass;
+                     if(dc.templateClass) dc = dc.templateClass;
+                     if(dc.base && sc != dc)
+                     {
+                        e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
+                        e.type = castExp;
+                        e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
+                     }
+                  }
+                  FreeType(dest);
+               }
+            }
+         }
+         FreeType(src);
+      }
+   }
+   else if(src && src.kind == intPtrType && e.destType && e.destType.classObjectType)
+   {
+      Expression nbExp = GetNonBracketsExp(e);
+      if(nbExp.type != castExp || !IsVoidPtrCast(nbExp.cast.typeName))
+      {
+         e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
+         e.type = castExp;
+         e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
+      }
+   }
+}
+
 static void InstDeclPassExpression(Expression exp)
 {
    switch(exp.type)
@@ -442,7 +541,24 @@ static void InstDeclPassExpression(Expression exp)
          if(exp.op.exp1)
             InstDeclPassExpression(exp.op.exp1);
          if(exp.op.exp2)
+         {
             InstDeclPassExpression(exp.op.exp2);
+            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 &&
+               exp.op.exp2.expType && exp.op.exp2.expType.kind == pointerType && exp.op.exp2.expType.type && exp.op.exp2.expType.type.kind == templateType)
+            {
+               Expression e = exp.op.exp2;
+               e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
+               e.type = castExp;
+               e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
+
+               e = exp.op.exp1;
+               e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
+               e.type = castExp;
+               e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
+            }
+            else if(exp.op.exp1 && (exp.op.op == '=' || exp.op.op == EQ_OP || exp.op.op == NE_OP))
+               AddPointerCast(exp.op.exp2);
+         }
          break;
       case extensionExpressionExp:
       case bracketsExp:
@@ -467,7 +583,26 @@ static void InstDeclPassExpression(Expression exp)
          if(exp.call.arguments)
          {
             for(e = exp.call.arguments->first; e; e = e.next)
+            {
+               bool addCast = false;
                InstDeclPassExpression(e);
+               AddPointerCast(e);
+
+               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)) &&
+                  e.destType && e.destType.kind == pointerType && e.destType.type && e.destType.type.kind == pointerType && e.destType.type.type && e.destType.type.type.kind == voidType)
+                  addCast = true;
+               // Fix for adding a cast to Unserialize with a struct passed as a parameter:
+               else if(e.expType && e.expType.kind == classType && e.expType._class && e.expType._class.registered && e.expType._class.registered.type == structClass && e.byReference &&
+                  e.destType && e.destType.kind == classType && e.destType.classObjectType && e.destType.byReference)
+                  addCast = true;
+
+               if(addCast && (e.type != castExp || !IsVoidPtrCast(e.cast.typeName)))
+               {
+                  e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
+                  e.type = castExp;
+                  e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
+               }
+            }
          }
          break;
       }
@@ -490,25 +625,46 @@ static void InstDeclPassExpression(Expression exp)
       {
          Type type = exp.expType;
          // Remove casts to simple structs... (Watch out for pointers later...)
-         if(type && type.kind == classType && type._class.registered && type._class.registered.type == structClass)
-         {
-            Expression castExp = exp.cast.exp;
-            Expression prev = exp.prev, next = exp.next;
-            exp.cast.exp = null;
-            FreeExpContents(exp);
-            FreeType(exp.expType);
-            FreeType(exp.destType);
-            *exp = *castExp;
-            delete castExp;
-            exp.prev = prev;
-            exp.next = next;
-            InstDeclPassExpression(exp);
+         if(type && type.kind == classType && type._class.registered && type._class.registered.type == structClass && !exp.needCast)
+         {
+            if(exp.destType && exp.destType.classObjectType == typedObject && exp.destType.byReference)
+            {
+               // For Unserialize with a StaticString
+               FreeTypeName(exp.cast.typeName);
+               exp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, MkPointer(null, null)), null));
+            }
+            else
+            {
+               Expression castExp = exp.cast.exp;
+               Expression prev = exp.prev, next = exp.next;
+               exp.cast.exp = null;
+               FreeExpContents(exp);
+               FreeType(exp.expType);
+               FreeType(exp.destType);
+               *exp = *castExp;
+               delete castExp;
+               exp.prev = prev;
+               exp.next = next;
+               InstDeclPassExpression(exp);
+            }
          }
          else
          {
-            InstDeclPassTypeName(exp.cast.typeName, false);
+            if(exp.expType && exp.expType.kind == pointerType)
+            {
+               if(exp.cast.exp && exp.cast.exp.expType && exp.cast.exp.expType.kind == templateType && !exp.cast.exp.expType.isPointerType)
+                  exp.cast.exp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), exp.cast.exp);
+            }
+
+            InstDeclPassTypeName(exp.cast.typeName, exp.usage.usageArg /*false*/);
             if(exp.cast.exp)
+            {
+               if(exp.expType && exp.expType.kind == templateType && exp.destType &&
+                  (exp.destType.passAsTemplate || (!exp.destType.templateParameter || (!exp.destType.templateParameter.dataType && !exp.destType.templateParameter.dataTypeString))) &&
+                  exp.cast.exp.expType && !exp.cast.exp.expType.passAsTemplate && exp.cast.exp.expType.isPointerType)
+                  exp.cast.exp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), exp.cast.exp);
                InstDeclPassExpression(exp.cast.exp);
+            }
          }
          break;
       }
@@ -546,7 +702,10 @@ static void InstDeclPassInitializer(Initializer init)
    {
       case expInitializer:
          if(init.exp)
+         {
             InstDeclPassExpression(init.exp);
+            AddPointerCast(init.exp);
+         }
          break;
       case listInitializer:
       {
@@ -579,7 +738,7 @@ static void InstDeclPassDeclaration(Declaration decl)
                         ReplaceByInstancePtr(spec, &d.declarator, type);
                   }
                }
-               InstDeclPassSpecifier(spec);
+               InstDeclPassSpecifier(spec, false);
             }
          }
          if(decl.declarators)
@@ -611,7 +770,7 @@ static void InstDeclPassDeclaration(Declaration decl)
                         ReplaceByInstancePtr(spec, &d, type);
                   }
                }
-               InstDeclPassSpecifier(spec);
+               InstDeclPassSpecifier(spec, false);
             }
          }
 
@@ -757,6 +916,7 @@ static void InstDeclPassStatement(Statement stmt)
          {
             for(exp = stmt.expressions->first; exp; exp = exp.next)
                InstDeclPassExpression(exp);
+            AddPointerCast(stmt.expressions->last);
          }
          break;
       }
@@ -786,6 +946,504 @@ static void InstDeclPassStatement(Statement stmt)
    }
 }
 
+void TopoSort(OldList * input)
+{
+   OldList L { };
+   OldList S { };
+   OldList B { };
+   External n, next;
+   //External x;
+
+   for(n = input->first; n; n = next)
+   {
+      next = n.next;
+      if(n.type == declarationExternal && !n.declaration)
+      {
+         input->Remove(n);
+         if(n.symbol && n.symbol.structExternal == n)
+            n.symbol.structExternal = null;
+         FreeExternal(n);
+      }
+      else if(!n.incoming.count)
+      {
+         input->Remove(n);
+         S.Add(n);
+      }
+      else if(!n.nonBreakableIncoming)
+      {
+         input->Remove(n);
+         B.Add(n);
+      }
+   }
+/*
+         for(x = input->first; x; x = x.next)
+         {
+            int count = 0;
+            for(e : x.incoming; !e.breakable)
+               count++;
+            if(count != x.nonBreakableIncoming)
+               printf("Bug in input");
+
+            if(!x.incoming.count)
+               printf("This node should be in S!\n");
+            for(e : x.incoming)
+            {
+               External y, from = e.from;
+               for(y = input->first; y; y = y.next)
+                  if(y == from)
+                     break;
+               if(!y)
+               {
+                  for(y = B.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+
+               if(!y)
+               {
+                  for(y = S.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+               if(!y)
+               {
+                  printf("This node is nowhere!\n");
+               }
+            }
+         }*/
+
+   while(true)
+   {
+      TopoEdge e, ne;
+      if((n = S.first))
+      {
+         /*
+         for(x = input->first; x; x = x.next)
+         {
+            int count = 0;
+            for(e : x.incoming; !e.breakable)
+               count++;
+            if(count != x.nonBreakableIncoming)
+               printf("Bug in input");
+            if(!x.incoming.count)
+               printf("This node should be in S!\n");
+            for(e : x.incoming)
+            {
+               External y, from = e.from;
+               for(y = input->first; y; y = y.next)
+                  if(y == from)
+                     break;
+               if(!y)
+               {
+                  for(y = B.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+
+               if(!y)
+               {
+                  for(y = S.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+               if(!y)
+               {
+                  printf("This node is nowhere!\n");
+               }
+            }
+         }*/
+
+         //DebugPrint("*** Free Node: [", n.id, "]\n\t", n.output);
+         S.Remove((IteratorPointer)n);
+
+         /*
+         if(n && n.symbol && n.symbol.string && !strcmp(n.symbol.string, "ecere::com::Instance"))
+            printf("Adding Instance\n");
+         */
+
+         L.Add(n);
+         for(e = n.outgoing.first; e; e = ne)
+         {
+            External m = e.to;
+            OldList * list;
+
+            //DebugPrint(" This Free Node has an edge to [", m.id, "] ", m.output);
+            if(m.nonBreakableIncoming)
+            {
+               //DebugPrint("... which we think is in input");
+               list = input;
+            }
+            else
+            {
+               //DebugPrint("... which we think is in B");
+               list = &B;
+            }
+
+            if(!list->count)
+               PrintLn("!!! Something's wrong !!!");
+            ne = e.out.next;
+
+            if(!e.breakable)
+            {
+#ifdef _DEBUG
+               if(!m.nonBreakableIncoming)
+                  printf("Bug");
+#endif
+               m.nonBreakableIncoming--;
+               //DebugPrint("Reducing non breakable incoming, now ", m.nonBreakableIncoming);
+            }
+
+            n.outgoing.Remove((IteratorPointer)e);
+            m.incoming.Remove((IteratorPointer)e);
+            delete e;
+
+            if(!m.incoming.count)
+            {
+               //DebugPrint("Last edge to this node taken out, moving to S...");
+               list->Remove(m);
+               S.Add(m);
+            }
+            else if(!m.nonBreakableIncoming)
+            {
+               //DebugPrint("Last non-breakable edge to this node taken out, moving to B...");
+               list->Remove(m);
+               B.Add(m);
+            }
+         }
+      }
+      else if((n = B.first))
+      {
+         //DebugPrint("Breaking some of the ", n.incoming.count, " incoming edges to [", n.id, "] ", n.output);
+         B.Remove((IteratorPointer)n);
+
+         // Break the edges of this node
+         for(e = n.incoming.first; e; e = ne)
+         {
+            TopoEdge e2, n2;
+            External m = e.from;
+            External f;
+/*
+         for(x = input->first; x; x = x.next)
+         {
+            int count = 0;
+            for(e : x.incoming; !e.breakable)
+               count++;
+            if(count != x.nonBreakableIncoming)
+               printf("Bug in input");
+            if(!x.incoming.count)
+               printf("This node should be in S!\n");
+            for(e : x.incoming)
+            {
+               External y, from = e.from;
+               for(y = input->first; y; y = y.next)
+                  if(y == from)
+                     break;
+               if(!y)
+               {
+                  for(y = B.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+
+               if(!y)
+               {
+                  for(y = S.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+               if(!y && from != n)
+               {
+                  printf("This node is nowhere!\n");
+               }
+            }
+         }*/
+
+            f = m.ForwardDeclare();
+            ne = e.in.next;
+/*
+         for(x = input->first; x; x = x.next)
+         {
+            int count = 0;
+            for(e : x.incoming; !e.breakable)
+               count++;
+            if(count != x.nonBreakableIncoming)
+               printf("Bug in input");
+            if(!x.incoming.count)
+               printf("This node should be in S!\n");
+            for(e : x.incoming)
+            {
+               External y, from = e.from;
+               for(y = input->first; y; y = y.next)
+                  if(y == from)
+                     break;
+               if(!y)
+               {
+                  for(y = B.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+
+               if(!y)
+               {
+                  for(y = S.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+               if(!y && from != n && from != f)
+               {
+                  printf("This node is nowhere!\n");
+               }
+            }
+         }
+*/
+            // Recheck input for edges created by forward declaration
+            {
+               External c, next;
+               for(c = input->first; c; c = next)
+               {
+                  next = c.next;
+                  if(!c.incoming.count)
+                  {
+                     input->Remove(c);
+                     S.Add(c);
+                  }
+                  else if(!c.nonBreakableIncoming)
+                  {
+                     input->Remove(c);
+                     B.Add(c);
+                  }
+               }
+            }
+
+            //DebugPrint("Breaking edge from ", e.from.id, " to ", e.to.id);
+            //DebugPrint("Creating a forward decl node [", f.id, "] for [", m.id, "]");
+
+            for(e2 = m.outgoing.first; e2; e2 = n2)
+            {
+               n2 = e2.out.next;
+               if(e2.breakable)
+               {
+                  External to = e2.to;
+
+                  if(e2 == e)
+                     ;//DebugPrint("Breaking this particular connection");
+                  else
+                     ;//DebugPrint("Also redirecting connection from ", m.id, " to ", to.id, " to come from ", f.id, " instead.");
+                  e2.breakable = false;
+                  e2.from = f;
+                  m.outgoing.Remove((IteratorPointer)e2);
+                  f.outgoing.Add(e2);
+                  to.nonBreakableIncoming++;
+                  if(e2 != e && to.nonBreakableIncoming == 1)
+                  {
+                     // If this node was previously in B, move it to input
+                     B.Remove(to);
+                     input->Add(to);
+                  }
+
+                  //DebugPrint("Node ", e2.to.id, " now has ", e2.to.nonBreakableIncoming, " non-breakable incoming edges.");
+               }
+            }
+/*
+         for(x = input->first; x; x = x.next)
+         {
+            int count = 0;
+            for(e : x.incoming; !e.breakable)
+               count++;
+            if(count != x.nonBreakableIncoming)
+               printf("Bug in input");
+            if(!x.incoming.count)
+               printf("This node should be in S!\n");
+            for(e : x.incoming)
+            {
+               External y, from = e.from;
+               for(y = input->first; y; y = y.next)
+                  if(y == from)
+                     break;
+               if(!y)
+               {
+                  for(y = B.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+
+               if(!y)
+               {
+                  for(y = S.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+               if(!y && from != n && from != f)
+               {
+                  printf("This node is nowhere!\n");
+               }
+            }
+         }*/
+            if(!f.incoming.count)
+               S.Add(f);
+            else if(!f.nonBreakableIncoming)
+               B.Add(f);
+            else
+               input->Add(f);
+/*
+         for(x = input->first; x; x = x.next)
+         {
+            int count = 0;
+            for(e : x.incoming; !e.breakable)
+               count++;
+            if(count != x.nonBreakableIncoming)
+               printf("Bug in input");
+            if(!x.incoming.count)
+               printf("This node should be in S!\n");
+            for(e : x.incoming)
+            {
+               External y, from = e.from;
+               for(y = input->first; y; y = y.next)
+                  if(y == from)
+                     break;
+               if(!y)
+               {
+                  for(y = B.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+
+               if(!y)
+               {
+                  for(y = S.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+
+               if(!y)
+               {
+                  for(y = L.first; y; y = y.next)
+                     if(y == from)
+                     {
+                        PrintLn("This node is already in L!");
+                        break;
+                     }
+               }
+
+               if(!y && from != n)
+               {
+                  ConsoleFile file { };
+                  printf("This node is nowhere!\n");
+                  OutputExternal(from, file);
+                  delete file;
+               }
+            }
+         }
+*/
+            // Avoid needless edge breaking by processing a node as soon as one shows up in S
+            if(S.first)
+               break;
+         }
+
+         // Put n back in input because it now has unbreakable edges
+         input->Add(n);
+      }
+      else
+      {
+         if(input->count)
+         {
+#ifdef _DEBUG
+            ConsoleFile f { };
+            External e = input->first;
+#endif
+            Compiler_Error("declarations cycles found\n");
+#ifdef _DEBUG
+            //OutputTree(input, f);
+/*
+         for(x = input->first; x; x = x.next)
+         {
+            int count = 0;
+            for(e : x.incoming; !e.breakable)
+               count++;
+            if(count != x.nonBreakableIncoming)
+               printf("Bug in input");
+            if(!x.incoming.count)
+               printf("This node should be in S!\n");
+
+            for(e : x.incoming)
+            {
+               External y, from = e.from;
+               for(y = input->first; y; y = y.next)
+                  if(y == from)
+                     break;
+               if(!y)
+               {
+                  for(y = B.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+
+               if(!y)
+               {
+                  for(y = S.first; y; y = y.next)
+                     if(y == from)
+                        break;
+               }
+               if(!y)
+               {
+                  printf("This node is nowhere!\n");
+               }
+            }
+         }
+*/
+            SetOutputLineNumbers(false);
+            OutputExternal(e, f);
+
+            PrintLn("\nDepends on:\n");
+            { TopoEdge i; for(i = e.incoming.last; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
+
+            OutputExternal(e, f);
+
+            PrintLn("\nWhile that depends on:\n");
+            { TopoEdge i; for(i = e.incoming.first; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
+
+            OutputExternal(e, f);
+
+            PrintLn("\nWhile that depends on:\n");
+            { TopoEdge i; for(i = e.incoming.first; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
+
+            OutputExternal(e, f);
+
+            PrintLn("\nWhile that depends on:\n");
+            { TopoEdge i; for(i = e.incoming.first; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
+
+            OutputExternal(e, f);
+            delete f;
+
+            system("pause");
+
+            while((e = input->first))
+            {
+               input->Remove(e);
+               L.Add(e);
+            }
+            *input = L;
+#endif
+         }
+         else
+            *input = L;
+         break;
+      }
+   }
+
+   for(n = input->first; n; n = next)
+   {
+      next = n.next;
+      if(n.type == declarationExternal && (!n.declaration || ((!n.declaration.specifiers || !n.declaration.specifiers->count) && (!n.declaration.declarators || !n.declaration.declarators->count))))
+      {
+         input->Remove(n);
+         if(n.symbol && n.symbol.structExternal == n)
+            n.symbol.structExternal = null;
+         FreeExternal(n);
+      }
+   }
+}
+
 public void ProcessInstanceDeclarations()
 {
    External external;
@@ -804,7 +1462,7 @@ public void ProcessInstanceDeclarations()
                int type;
                if((type = ReplaceClassSpec(func.specifiers, spec, false)))
                   ReplaceByInstancePtr(spec, &func.declarator, type);
-               InstDeclPassSpecifier(spec);
+               InstDeclPassSpecifier(spec, false);
             }
          }
          InstDeclPassDeclarator(func.declarator);
@@ -817,4 +1475,7 @@ public void ProcessInstanceDeclarations()
             InstDeclPassDeclaration(external.declaration);
       }
    }
+
+   // Perform topological sort
+   TopoSort(ast);
 }