#include <stdlib.h>
 #include <string.h>
+#include <stdarg.h>
 
 /* common */
 #include "abend.h"
 #include "cpu.h"
 #include "debugflag.h"
 #include "print.h"
+#include "strbuf.h"
 #include "xmalloc.h"
 #include "xsprintf.h"
 
 #include "asmlabel.h"
 #include "codeent.h"
 #include "codeinfo.h"
+#include "codeopt.h"
 #include "coptadd.h"
 #include "coptc02.h"
 #include "coptcmp.h"
 #include "copttest.h"
 #include "error.h"
 #include "global.h"
-#include "codeopt.h"
+#include "output.h"
 
 
 
 
 
 
+static void OpenDebugFile (const CodeSeg* S)
+/* Open the debug file for the given segment if the flag is on */
+{
+    if (DebugOptOutput) {
+        StrBuf Name = AUTO_STRBUF_INITIALIZER;
+        if (S->Func) {
+            SB_CopyStr (&Name, S->Func->Name);
+        } else {
+            SB_CopyStr (&Name, "global");
+        }
+        SB_AppendStr (&Name, ".opt");
+        SB_Terminate (&Name);
+        OpenDebugOutputFile (SB_GetConstBuf (&Name));
+        SB_Done (&Name);
+    }
+}
+
+
+
+static void WriteDebugOutput (CodeSeg* S, const char* Step)
+/* Write a separator line into the debug file if the flag is on */
+{
+    if (DebugOptOutput) {
+        /* Output a separator */
+        WriteOutput ("=========================================================================\n");
+
+        /* Output a header line */
+        if (Step == 0) {
+            /* Initial output */
+            WriteOutput ("Initial code for function `%s':\n",
+                         S->Func? S->Func->Name : "<global>");
+        } else {
+            WriteOutput ("Code after applying `%s':\n", Step);
+        }
+
+        /* Output the code segment */
+        CS_Output (S);
+    }
+}
+
+
+
 static unsigned RunOptFunc (CodeSeg* S, OptFunc* F, unsigned Max)
 /* Run one optimizer function Max times or until there are no more changes */
 {
 
        /* Run the function */
        C = F->Func (S);
-        if (Debug && C > 0) {
-            printf ("Applied %s: %u changes\n", F->Name, C);
-        }
        Changes += C;
 
        /* Do statistics */
        F->TotalChanges += C;
        F->LastChanges  += C;
 
-        /* If we had changes, regenerate register info */
+        /* If we had changes, output stuff and regenerate register info */
         if (C) {
+            if (Debug) {
+                printf ("Applied %s: %u changes\n", F->Name, C);
+            }
+            WriteDebugOutput (S, F->Name);
             CS_GenRegInfo (S);
         }
 
        Print (stdout, 1, "Running optimizer for global code segment\n");
     }
 
+    /* If requested, open an output file */
+    OpenDebugFile (S);
+    WriteDebugOutput (S, 0);
+
     /* Generate register info for all instructions */
     CS_GenRegInfo (S);
 
     /* Free register info */
     CS_FreeRegInfo (S);
 
+    /* Close output file if necessary */
+    if (DebugOptOutput) {
+        CloseOutputFile ();
+    }
+
     /* Write statistics */
     if (StatFileName) {
-       WriteOptStats (StatFileName);
+       WriteOptStats (StatFileName);
     }
 }
 
 
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
 unsigned char AddSource                = 0;    /* Add source lines as comments */
 unsigned char DebugInfo                = 0;    /* Add debug info to the obj */
 unsigned char PreprocessOnly    = 0;    /* Just preprocess the input */
+unsigned char DebugOptOutput    = 0;    /* Output debug stuff */
 unsigned      RegisterSpace     = 6;    /* Space available for register vars */
 
 /* Stackable options */
 IntStack Optimize                  = INTSTACK(0);  /* Optimize flag */
 IntStack CodeSizeFactor            = INTSTACK(100);/* Size factor for generated code */
 IntStack DataAlignment      = INTSTACK(1);  /* Alignment for data */
-                
+
 /* File names */
 StrBuf DepName     = STATIC_STRBUF_INITIALIZER; /* Name of dependencies file */
 StrBuf FullDepName = STATIC_STRBUF_INITIALIZER; /* Name of full dependencies file */
 
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
 extern unsigned char   AddSource;              /* Add source lines as comments */
 extern unsigned char   DebugInfo;              /* Add debug info to the obj */
 extern unsigned char    PreprocessOnly;         /* Just preprocess the input */
+extern unsigned char    DebugOptOutput;         /* Output debug stuff */
 extern unsigned         RegisterSpace;          /* Space available for register vars */
 
 /* Stackable options */
 
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2011, Ullrich von Bassewitz                                      */
+/* (C) 2000-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
 
 
 
+static void OptDebugOptOutput (const char* Opt attribute ((unused)), 
+                               const char* Arg attribute ((unused)))
+/* Output optimization steps */
+{
+    DebugOptOutput = 1;
+}
+
+
+
 static void OptDepTarget (const char* Opt attribute ((unused)), const char* Arg)
 /* Handle the --dep-target option */
 {
                { "--debug",            0,      OptDebug                },
        { "--debug-info",       0,      OptDebugInfo            },
         { "--debug-opt",        1,      OptDebugOpt             },
+        { "--debug-opt-output", 0,      OptDebugOptOutput       },
         { "--dep-target",       1,      OptDepTarget            },
        { "--disable-opt",      1,      OptDisableOpt           },
        { "--enable-opt",       1,      OptEnableOpt            },
 
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2009,     Ullrich von Bassewitz                                       */
-/*               Roemerstrasse 52                                            */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2009-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 
 
 
+void OpenDebugOutputFile (const char* Name)
+/* Open an output file for debugging purposes. Will call Fatal() in case of
+ * failures.
+ */
+{
+    /* Output file must not be open and we must have a name*/
+    PRECONDITION (OutputFile == 0);
+
+    /* Open the file */
+    OutputFile = fopen (Name, "w");
+    if (OutputFile == 0) {
+        Fatal ("Cannot open debug output file `%s': %s", Name, strerror (errno));
+    }
+    Print (stdout, 1, "Opened debug output file `%s'\n", Name);
+}
+
+
+
 void CloseOutputFile ()
 /* Close the output file. Will call Fatal() in case of failures. */
 {
         Fatal ("Cannot write to output file (disk full?)");
     }
     Print (stdout, 1, "Closed output file `%s'\n", OutputFilename);
+
+    OutputFile = 0;
 }
 
 
 
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2009,     Ullrich von Bassewitz                                       */
-/*               Roemerstrasse 52                                            */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2009-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 
 
 /*****************************************************************************/
-/*                                          Data                                    */
+/*                                          Data                                    */
 /*****************************************************************************/
 
 
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                          Code                                    */
 /*****************************************************************************/
 
 
 void OpenOutputFile ();
 /* Open the output file. Will call Fatal() in case of failures. */
 
+void OpenDebugOutputFile (const char* Name);
+/* Open an output file for debugging purposes. Will call Fatal() in case of 
+ * failures. 
+ */
+
 void CloseOutputFile ();
 /* Close the output file. Will call Fatal() in case of failures. */