Index: trunk/psphot/src/psphotOutput.c
===================================================================
--- trunk/psphot/src/psphotOutput.c	(revision 6117)
+++ trunk/psphot/src/psphotOutput.c	(revision 6311)
@@ -1,8 +1,146 @@
 # include "psphot.h"
 
+static int   extNumber  = -1;
+
+static char *outputName = NULL;
+static char *outputRoot = NULL;
+static char *outputMode = NULL;
+static char *outputFormat = NULL;
+
+static char *extNumberFormat = NULL;
+static char *extNameKey = NULL;
+static char *extRoot    = NULL;
+
+void psphotOutputPrep (ppFile *file, ppConfig *config) {
+
+    bool status;
+
+    outputRoot   = psMetadataLookupPtr (&status, config->arguments, "OUTPUT_ROOT");
+    if (!status) psAbort ("psphot", "output file not specified");
+
+    outputName   = psMetadataLookupPtr (&status, config->recipe, "OUTPUT_NAME");
+    outputMode   = psMetadataLookupPtr (&status, config->recipe, "OUTPUT_MODE");
+    outputFormat = psMetadataLookupPtr (&status, config->recipe, "OUTPUT_FORMAT");
+
+    // rules to construct output names
+    extNumberFormat = psMetadataLookupPtr (&status, config->recipe, "EXTNUMBER_FORMAT");
+    extNameKey      = psMetadataLookupPtr (&status, config->recipe, "EXTNAME");
+    extRoot         = psMetadataLookupPtr (&status, config->recipe, "EXTROOT");
+
+    if (extNumberFormat == NULL) {
+	extNumberFormat = psStringCopy ("%02d");
+    }
+
+    psStringStrip (outputName);
+    psStringStrip (extNameKey);
+    psStringStrip (extRoot);
+
+    // validate the outputMode and outputFormat
+    status = false;
+    status |= !strcasecmp (outputFormat, "TEXT");
+    status |= !strcasecmp (outputFormat, "OBJ");
+    status |= !strcasecmp (outputFormat, "SX");
+    status |= !strcasecmp (outputFormat, "CMP");
+    status |= !strcasecmp (outputFormat, "CMF");
+    if (!status) {
+	psLogMsg ("psphot", PS_LOG_ERROR, "invalid output format %s", outputFormat);
+	exit (1);
+    }
+
+    // validate the outputMode and outputFormat
+    status = false;
+    status |= !strcasecmp (outputMode, "MEF");
+    status |= !strcasecmp (outputMode, "SPLIT");
+    if (!status) {
+	psLogMsg ("psphot", PS_LOG_ERROR, "invalid output mode %s", outputMode);
+	exit (1);
+    }
+
+    // for MEF output, we need to open a file up front
+    if (!strcasecmp (outputMode, "MEF")) {
+	psLogMsg ("psphot", PS_LOG_ERROR, "MEF output mode unavailable");
+	exit (1);
+    }
+
+    return;
+}
+
+// generate the SPLIT filenames
+char *psphotSplitName (psMetadata *header) {
+
+    bool status;
+
+    char *newName = NULL;     // destination for resulting name
+    char *extNameWord = NULL; // this contains the per-extension word to add
+    char  extNumberWord[16];  // this will store the string-formatted number
+
+    // extNumberFormat must be set to a valid entry in psphotOutputPrep
+    sprintf (extNumberWord, extNumberFormat, extNumber);
+
+    // find the extname:
+    char *extNameVal = psMetadataLookupPtr (&status, header, extNameKey);
+	    
+    extNameWord = extNameVal;
+    if ((extRoot != NULL) && (extNameVal != NULL)) {
+	// check that the extNameVal matches the expected root 
+	if (strncmp (extNameVal, extRoot, strlen(extRoot))) {
+	    psLogMsg ("psphotSplitName", PS_LOG_WARN, "header entry does not match expected format");
+	}
+	extNameWord = extNameVal + strlen(extRoot);
+    }
+
+    if (extNameWord != NULL) {
+	psStringStrip (extNameWord);
+    }
+
+    // note : if the user mis-specifies the output name, we will happily overwrite files
+    newName = psStringCopy (outputName);
+    newName = psphotNameSubstitute (newName, outputRoot, "%r");
+    newName = psphotNameSubstitute (newName, extNameWord, "%x");
+    newName = psphotNameSubstitute (newName, extNumberWord, "%n");
+
+    return newName;
+}
+
+
+// given the input string, search for the key, and replace with the replacement
+// the input string may be freed if not needed
+char *psphotNameSubstitute (char *input, char *replace, char *key) {
+
+    char *p;
+
+    if (key == NULL) return input;
+    if (strlen(key) == 0) return input;
+
+    p = strstr (input, key);
+    if (p == NULL) return input;
+
+    // we have input = xxxkeyxxx
+    // we want output = xxxreplacexxx
+
+    // this is safe since we will subtract strlen(key) elements from input
+    char *output = psAlloc(strlen(input) + strlen(replace) + 1);
+    int Nc = p - input;
+
+    // copy the first segement into 'output'
+    strncpy (output, input, Nc);
+
+    // copy the key replacement to the start of the key
+
+    strcpy (&output[Nc], replace);
+    Nc += strlen (replace);
+    
+    // copy the remainder to the end of the replacement
+    strcpy (&output[Nc], p + strlen(key));
+
+    psFree (input);
+    return output;
+}
+
 // output functions: we have several fixed modes (sx, obj, cmp)
-void psphotOutput (pmReadout *readout, psMetadata *config) {
+void psphotOutput (pmReadout *readout, psMetadata *arguments) {
 
     bool status;
+    char *outputFile;
 
     psTimerStart ("psphot");
@@ -13,11 +151,24 @@
     pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF");
 
-    char *outputMode = psMetadataLookupPtr (&status, config, "OUTPUT_MODE");
-    char *outputFile = psMetadataLookupPtr (&status, config, "OUTPUT_FILE");
-    char *residImage = psMetadataLookupPtr (&status, config, "RESID_IMAGE");
-    char *psfFile    = psMetadataLookupPtr (&status, config, "PSF_OUTPUT_FILE");
-
+    // starting value is -1
+    extNumber ++;
+
+    // for SPLIT output, we need to open a file for each output call
+    if (!strcasecmp (outputMode, "SPLIT")) {
+	outputFile = psphotSplitName (header);
+    } else {
+	// construct appropriate extname
+	psAbort ("psphotOutput", "programming error");
+    }
+    
+    fprintf (stderr, "output file: %s\n", outputFile);
+    return;
+
+    char *psfFile    = psMetadataLookupPtr (&status, arguments, "PSF_OUTPUT_FILE");
+    char *psfSample  = psMetadataLookupPtr (&status, arguments, "PSF_SAMPLE_FILE");
+    char *residImage = psMetadataLookupPtr (&status, arguments, "RESID_IMAGE");
+
+    if (psfSample != NULL) psphotSamplePSFs (psf, readout->image, psfSample);
     if (residImage != NULL) psphotSaveImage (header, readout->image, residImage);
-    psphotSamplePSFs (config, psf, readout->image);
 
     if (psfFile != NULL) {
@@ -30,30 +181,30 @@
 	return;
     }
-    if (outputMode == NULL) {
-	psLogMsg ("output", 3, "no data output mode selected");
+    if (outputFormat == NULL) {
+	psLogMsg ("output", 3, "no data output format selected");
 	return;
     }
-    if (!strcasecmp (outputMode, "SX")) {
+    if (!strcasecmp (outputFormat, "SX")) {
 	pmSourcesWriteSX (sources, outputFile);
 	return;
     }
-    if (!strcasecmp (outputMode, "OBJ")) {
+    if (!strcasecmp (outputFormat, "OBJ")) {
 	pmSourcesWriteOBJ (sources, outputFile);
 	return;
     }
-    if (!strcasecmp (outputMode, "CMP")) {
+    if (!strcasecmp (outputFormat, "CMP")) {
 	pmSourcesWriteCMP (sources, outputFile, header);
 	return;
     }
-    if (!strcasecmp (outputMode, "CMF")) {
+    if (!strcasecmp (outputFormat, "CMF")) {
 	pmSourcesWriteCMF (sources, outputFile, header);
 	return;
     }
-    if (!strcasecmp (outputMode, "TEXT")) {
+    if (!strcasecmp (outputFormat, "TEXT")) {
 	pmSourcesWriteText (sources, outputFile);
 	return;
     }
 
-    psAbort ("psphot", "unknown output mode %s", outputMode);
+    psAbort ("psphot", "unknown output mode %s", outputFormat);
 }
 
@@ -560,8 +711,5 @@
 }
 
-
-bool psphotSamplePSFs (psMetadata *config, pmPSF *psf, psImage *image) {
-
-    bool status;
+bool psphotSamplePSFs (pmPSF *psf, psImage *image, char *output) {
 
     // make sample PSFs for 4 corners and the center
@@ -569,7 +717,4 @@
 
     // optional dump of all rough source data
-    char *output = psMetadataLookupPtr (&status, config, "PSF_SAMPLE_FILE");
-    if (!status) return false;
-    if (output == NULL) return false;
     if (output[0] == 0) return false;
 
@@ -580,4 +725,5 @@
     psFits *fits = psFitsOpen (output, "w");
 
+    // the centers are in parent coordinates; they do not need to correspond to valid pixels...
     sample = pmModelPSFatXY (image, modelEXT, psf, 25, 25, 25, 25);
     psFitsWriteImage (fits, NULL, sample, 0);
