Index: branches/tap_branches/ppStack/src/ppStack.c
===================================================================
--- branches/tap_branches/ppStack/src/ppStack.c	(revision 25900)
+++ branches/tap_branches/ppStack/src/ppStack.c	(revision 27838)
@@ -15,21 +15,15 @@
 int main(int argc, char *argv[])
 {
-    psExit exitValue = PS_EXIT_SUCCESS; // Exit value
+    psLibInit(NULL);
     psTimerStart(TIMER_NAME);
     psTimerStart("PPSTACK_STEPS");
-    psLibInit(NULL);
+
+    pmErrorRegister();
+    ppStackErrorRegister();
+    psphotErrorRegister();
 
     pmConfig *config = pmConfigRead(&argc, argv, PPSTACK_RECIPE); // Configuration
+    ppStackOptions *options = NULL;                               // Options for stacking
     if (!config) {
-        psErrorStackPrint(stderr, "Error reading configuration.");
-        exitValue = PS_EXIT_CONFIG_ERROR;
-        goto die;
-    }
-
-    (void) psTraceSetLevel("ppStack", 5);
-
-    if (!ppStackArgumentsSetup(argc, argv, config)) {
-        psErrorStackPrint(stderr, "Error reading arguments.\n");
-        exitValue = PS_EXIT_CONFIG_ERROR;
         goto die;
     }
@@ -38,45 +32,100 @@
 
     if (!pmModelClassInit()) {
-        psErrorStackPrint(stderr, "Error initialising model classes.\n");
-        exitValue = PS_EXIT_PROG_ERROR;
+        psError(PPSTACK_ERR_PROG, false, "Unable to initialise model classes.");
         goto die;
     }
 
     if (!psphotInit()) {
-        psErrorStackPrint(stderr, "Error initialising psphot.\n");
-        exitValue = PS_EXIT_PROG_ERROR;
+        psError(PPSTACK_ERR_PROG, false, "Error initialising psphot.");
+        goto die;
+    }
+
+    (void)psTraceSetLevel("ppStack", 5);
+
+    if (!ppStackArgumentsSetup(argc, argv, config)) {
         goto die;
     }
 
     if (!ppStackCamera(config)) {
-        psErrorStackPrint(stderr, "Error setting up input files.\n");
-        exitValue = PS_EXIT_CONFIG_ERROR;
         goto die;
     }
 
     if (!ppStackArgumentsParse(config)) {
-        psErrorStackPrint(stderr, "Error reading arguments.\n");
-        exitValue = PS_EXIT_CONFIG_ERROR;
         goto die;
     }
 
-    if (!ppStackLoop(config)) {
-        psErrorStackPrint(stderr, "Error performing combination.\n");
-        exitValue = PS_EXIT_DATA_ERROR;
+    options = ppStackOptionsAlloc();
+    if (!ppStackLoop(config, options)) {
         goto die;
     }
 
 
-     // Common code for the death.
-die:
-    psTrace("ppStack", 1, "Finished at %f sec\n", psTimerMark(TIMER_NAME));
-    psTimerStop();
+ die:
+    // Common code for the death.
+    {
+        psExit exitValue = ppStackExitCode(PS_EXIT_SUCCESS); // Exit code
 
-    psFree(config);
-    pmModelClassCleanup();
-    pmConfigDone();
-    psLibFinalize();
-    pmVisualClose();
-    exit(exitValue);
+        // Ensure everything closes
+        if (config) {
+            ppStackFileActivation(config, PPSTACK_FILES_PREPARE, true);
+            ppStackFileActivation(config, PPSTACK_FILES_CONVOLVE, true);
+            ppStackFileActivation(config, PPSTACK_FILES_STACK, true);
+            ppStackFileActivation(config, PPSTACK_FILES_UNCONV, true);
+            ppStackFileActivation(config, PPSTACK_FILES_PHOT, true);
+            if (!ppStackFilesIterateUp(config)) {
+                psError(psErrorCodeLast(), false, "Unable to close files.");
+                exitValue = ppStackExitCode(exitValue);
+                pmFPAfileFreeSetStrict(false);
+            }
+        }
+
+        // Write out summary statistics
+        if (options && options->stats) {
+
+            psMetadataAddS32(options->stats, PS_LIST_TAIL, "QUALITY", PS_META_REPLACE,
+                             "Bad data quality flag", options->quality);
+            psMetadataAddF32(options->stats, PS_LIST_TAIL, "TIME_STACK", 0,
+                             "Total time", psTimerClear("PPSTACK_TOTAL"));
+
+            const char *statsMDC = psMetadataConfigFormat(options->stats);
+            if (!statsMDC || strlen(statsMDC) == 0) {
+                psError(PS_ERR_IO, false, "Unable to get statistics MDC file.");
+                return false;
+            }
+            if (fprintf(options->statsFile, "%s", statsMDC) != strlen(statsMDC)) {
+                psError(PS_ERR_IO, false, "Unable to write statistics MDC file.");
+                return false;
+            }
+            psFree(statsMDC);
+            if (fclose(options->statsFile) == EOF) {
+                psError(PS_ERR_IO, false, "Unable to close statistics MDC file.");
+                return false;
+            }
+            options->statsFile = NULL;
+            pmConfigRunFilenameAddWrite(config, "STATS",
+                                        psMetadataLookupStr(NULL, config->arguments, "STATS"));
+        }
+        psFree(options);
+
+        // Dump configuration
+        bool mdok;                                                                    // Status of MD lookup
+        psString dump = psMetadataLookupStr(&mdok, config->arguments, "DUMP_CONFIG"); // File for config
+        if (dump && !pmConfigDump(config, dump)) {
+            psError(psErrorCodeLast(), false, "Unable to dump configuration.");
+            exitValue = ppStackExitCode(exitValue);
+        }
+
+        psTrace("ppStack", 1, "Finished at %f sec\n", psTimerMark(TIMER_NAME));
+        psTimerStop();
+
+        psFree(config);
+        pmModelClassCleanup();
+        pmConfigDone();
+        psLibFinalize();
+        pmVisualClose();
+
+        exitValue = ppStackExitCode(exitValue);
+        exit(exitValue);
+    }
 }
 
