Index: trunk/ppMerge/src/ppMerge.c
===================================================================
--- trunk/ppMerge/src/ppMerge.c	(revision 15631)
+++ trunk/ppMerge/src/ppMerge.c	(revision 17227)
@@ -4,15 +4,9 @@
 
 #include <stdio.h>
+#include <string.h>
 #include <pslib.h>
 #include <psmodules.h>
 
 #include "ppMerge.h"
-#include "ppMergeConfig.h"
-#include "ppMergeData.h"
-#include "ppMergeOptions.h"
-#include "ppMergeCheckInputs.h"
-#include "ppMergeCombine.h"
-#include "ppMergeScaleZero.h"
-#include "ppMergeMask.h"
 
 //#include "ppMem.h"
@@ -27,17 +21,81 @@
 {
     psLibInit(NULL);
-    psMemSetThreadSafety(false);           // Turn off thread safety, for more
+    psMemSetThreadSafety(false);
     psTimerStart(TIMERNAME);
 
-    // Parse the configuration and arguments
-    // Open the input image(s)
-    // Determine camera, format from header if not already defined
-    // Construct camera in preparation for reading
-    pmConfig *config = ppMergeConfig(argc, argv);
+    psExit exitValue = PS_EXIT_SUCCESS; // Exit value for program
+
+    pmConfig *config = pmConfigRead(&argc, argv, PPMERGE_RECIPE); // Configuration
     if (!config) {
-        psErrorStackPrint(stderr, "Unable to get configuration.");
-        exit(EXIT_FAILURE);
+        psErrorStackPrint(stderr, "Error reading configuration.");
+        exitValue = PS_EXIT_CONFIG_ERROR;
+        goto die;
     }
 
+    if (!ppMergeArguments(argc, argv, config)) {
+        psErrorStackPrint(stderr, "Error reading arguments.");
+        exitValue = PS_EXIT_CONFIG_ERROR;
+        goto die;
+    }
+
+    ppMergeType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); // Type of frame
+    switch (type) {
+      case PPMERGE_TYPE_MASK:
+        if (!ppMergeMask(config)) {
+            psErrorStackPrint(stderr, "Error generating mask.");
+            exitValue = PS_EXIT_DATA_ERROR;
+            goto die;
+        }
+        break;
+      case PPMERGE_TYPE_BIAS:
+      case PPMERGE_TYPE_DARK:
+      case PPMERGE_TYPE_SHUTTER:
+      case PPMERGE_TYPE_FLAT:
+      case PPMERGE_TYPE_FRINGE:
+        if (!ppMergeScaleZero(config)) {
+            psErrorStackPrint(stderr, "Error getting scale and zero-points.");
+            exitValue = PS_EXIT_DATA_ERROR;
+            goto die;
+        }
+        if (!ppMergeLoop(config)) {
+            psErrorStackPrint(stderr, "Error performing merge.");
+            exitValue = PS_EXIT_PROG_ERROR;
+            goto die;
+        }
+        break;
+      default:
+        psAbort("Invalid frame type: %x", type);
+    }
+
+
+    // Output the statistics
+    bool mdok;                          // Status of MD lookup
+    psString statsName = psMetadataLookupStr(&mdok, config->arguments, "STATS.NAME"); // Statistics file name
+    if (mdok && statsName && strlen(statsName) > 0) {
+        psString resolved = pmConfigConvertFilename(statsName, config, true); // Resolved filename
+        FILE *statsFile = fopen(resolved, "w"); // Output statistics file
+        if (!statsFile) {
+            psError(PS_ERR_IO, true, "Unable to open statistics file %s for writing.", resolved);
+            psFree(resolved);
+            exitValue = PS_EXIT_CONFIG_ERROR;
+            goto die;
+        }
+        psFree(resolved);
+        psMetadata *stats = psMetadataLookupMetadata(&mdok, config->arguments, "STATS.DATA"); // Statistics
+        if (!stats) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find statistics");
+            exitValue = PS_EXIT_PROG_ERROR;
+            goto die;
+        }
+        psString statsOut = psMetadataConfigFormat(stats); // String to write out
+        fprintf(statsFile, "%s", statsOut);
+        psFree(statsOut);
+        fclose(statsFile);
+    }
+
+
+
+
+#if 0
     // Set various tasks (define optional operations)
     ppMergeOptions *options = ppMergeOptionsParse(config);
@@ -81,19 +139,17 @@
     }
 
-#if 0
-    pmFPAPrint(stdout, data->out, true, true);
-#endif
-
     // Cleaning up
     psFree(data);
     psFree(options);
+#endif
+
+ die:
+    psTrace("ppSub", 1, "Finished at %f sec\n", psTimerMark("ppSub"));
+    psTimerStop();
+
     psFree(config);
-
-    pmConceptsDone();
     pmConfigDone();
     psLibFinalize();
 
-//    ppMemCheck();
-
-    return EXIT_SUCCESS;
+    exit(exitValue);
 }
