Index: trunk/ppStats/src/ppStats.c
===================================================================
--- trunk/ppStats/src/ppStats.c	(revision 13677)
+++ trunk/ppStats/src/ppStats.c	(revision 13993)
@@ -1,65 +1,91 @@
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+# include "ppStatsInternal.h"
 
-#include <stdio.h>
-#include <pslib.h>
-#include <psmodules.h>
+int main(int argc, char **argv) {
 
-#include "ppStats.h"
+    psExit status = PS_EXIT_SUCCESS;
 
-psMetadata *ppStats(psMetadata *out,
-		    pmFPA *fpa,         // FPA for which to get statistics
-                    pmFPAview *view,    // View for analysis
-                    psMaskType maskVal, // Value to mask
-                    pmConfig *config    // Configuration
-    )
-{
-    PS_ASSERT_PTR_NON_NULL(fpa, NULL)
-    PS_ASSERT_PTR_NON_NULL(view, NULL);
-    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    psLibInit(NULL);
+    psTimerStart("PPSTATS");
 
-    ppStatsData *data = ppStatsDataAlloc(); // All the input data
+    // Parse the configuration and arguments
+    pmConfig *config = pmConfigRead(&argc, argv, PPSTATS_RECIPE);
+    if (!config) {
+        psErrorStackPrint(stderr, "Unable to read configuration.\n");
+        exit(PS_EXIT_CONFIG_ERROR);
+    }
 
     // Get the options, open the files
-    if (!ppStatsSetupFromRecipe(data, config)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to get ppStats options from recipe.");
-        psFree(data);
-        return NULL;
+    ppStatsData *data = ppStatsSetupFromArgs(&argc, argv, config);
+    if (!data) {
+        psErrorStackPrint(stderr, "Unable to parse command-line arguments.\n");
+        exit(PS_EXIT_CONFIG_ERROR);
     }
 
-    // Override recipe mask value if one is provided
-    if (maskVal != 0) {
-        data->maskVal = maskVal;
+    // Output filename is optional
+    const char *outName = NULL;         // Output file name
+    FILE *outFile = stdout;             // Output file
+    if (argc == 2) {
+        outName = argv[1];
+        psString resolved = pmConfigConvertFilename(outName, config, true); // Resolved filename
+
+        if (resolved && strlen(resolved) > 0) {
+            outFile = fopen(resolved, "w");
+            if (!outFile) {
+                psLogMsg("ppStats", PS_LOG_ERROR, "Unable to open output file %s\n", resolved);
+                psFree(resolved);
+                // XXX this could be a system or config error, but not a data error
+                status = PS_EXIT_CONFIG_ERROR;
+                goto die;
+            }
+        } else {
+            psErrorStackPrint(stderr, "Unable to open output file %s.\n", resolved);
+            exit(PS_EXIT_CONFIG_ERROR);
+        }
+        psFree(resolved);
     }
 
-    if (data->fpa) {
-        psFree(data->fpa);
+    // Go through the FPA and do the hard work
+    psMetadata *results = ppStatsLoop(&status, data, config);
+    if (status != PS_EXIT_SUCCESS) {
+        psErrorStackPrint(stderr, "Error in stats loop.\n");
+        exit (status);
     }
-    data->fpa = psMemIncrRefCounter(fpa);
-
-    if (data->view) {
-        psFree(data->view);
-    }
-    data->view = psMemIncrRefCounter(view);
-
-    // Go through the FPA and do the hard work
-    psExit status;                      // Status of statistics loop
-    psMetadata *result = ppStatsLoop(&status, data, config);
-    if (status != PS_EXIT_SUCCESS) {
-        psError (PS_ERR_UNKNOWN, false, "Not able to measure FPA statistics.\n");
-        psFree(result);
-        psFree(data);
-        return (NULL);
+    if (psListLength(results->list) == 0) {
+        psErrorStackPrint(stderr, "No output.\n");
+        exit (status);
     }
 
-    if (out != NULL) {
-	psMetadataCopy (out, result);
-	psFree(result);
-	psFree(data);
-	return out;
+    if (data->fileLevel) {
+        const char *level = pmFPALevelToName(pmFPAPHULevel(config->format)); // Level for file
+        psMetadataAddStr(results, PS_LIST_HEAD, "FILE.LEVEL", 0, "File level", level);
     }
 
+    // Format and print the output
+    psString output = psMetadataConfigFormat(results);
+    if (!output) {
+        psErrorStackPrint(stderr, "Unable to generate configuration file with result.\n");
+        psFree(results);
+        exit(PS_EXIT_CONFIG_ERROR);
+    }
+    fprintf(outFile, "%s", output);
+    psFree(output);
+
+    // Clean up
+    psFree(results);
+    if (outName) {
+        fclose(outFile);
+    }
+
+    // Common code for the death.
+die:
+    if (status) {
+        psErrorStackPrint (stderr, "failure in %s", __func__);
+    }
     psFree(data);
-    return result;
+    psFree(config);
+    pmConceptsDone();
+    pmConfigDone();
+    psLibFinalize();
+
+    return status;
 }
