compiler/bootstrap: Fully automated (make updatebootstrap)
[sdk] / compiler / libec / src / pass3.ec
index 34df295..b411fae 100644 (file)
@@ -225,6 +225,7 @@ static void InstDeclPassSpecifier(Specifier spec, bool byRefTypedObject)
             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:
@@ -284,10 +285,7 @@ static void InstDeclPassSpecifier(Specifier spec, bool byRefTypedObject)
                !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;
@@ -344,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);
                }
             }
@@ -368,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)
@@ -446,6 +442,87 @@ static void InstDeclPassIdentifier(Identifier id)
    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)
@@ -464,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:
@@ -490,69 +584,23 @@ static void InstDeclPassExpression(Expression exp)
          {
             for(e = exp.call.arguments->first; e; e = e.next)
             {
-               Type src = e.expType;
-
+               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(src && (src.kind == templateType || src.kind == classType))
+               if(addCast && (e.type != castExp || !IsVoidPtrCast(e.cast.typeName)))
                {
-                  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(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 = MoveExpContents(e);
-                                    e.type = castExp;
-                                    e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
-                                 }
-                              }
-                              FreeType(dest);
-                           }
-                        }
-                     }
-                  }
-                  FreeType(src);
+                  e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
+                  e.type = castExp;
+                  e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
                }
             }
          }
@@ -579,23 +627,44 @@ static void InstDeclPassExpression(Expression exp)
          // Remove casts to simple structs... (Watch out for pointers later...)
          if(type && type.kind == classType && type._class.registered && type._class.registered.type == structClass && !exp.needCast)
          {
-            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(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
          {
+            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;
       }
@@ -633,7 +702,10 @@ static void InstDeclPassInitializer(Initializer init)
    {
       case expInitializer:
          if(init.exp)
+         {
             InstDeclPassExpression(init.exp);
+            AddPointerCast(init.exp);
+         }
          break;
       case listInitializer:
       {
@@ -844,6 +916,7 @@ static void InstDeclPassStatement(Statement stmt)
          {
             for(exp = stmt.expressions->first; exp; exp = exp.next)
                InstDeclPassExpression(exp);
+            AddPointerCast(stmt.expressions->last);
          }
          break;
       }
@@ -873,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;
@@ -904,4 +1475,7 @@ public void ProcessInstanceDeclarations()
             InstDeclPassDeclaration(external.declaration);
       }
    }
+
+   // Perform topological sort
+   TopoSort(ast);
 }