Index: /branches/rel10_ifa/psModules/src/config/pmConfig.c
===================================================================
--- /branches/rel10_ifa/psModules/src/config/pmConfig.c	(revision 6552)
+++ /branches/rel10_ifa/psModules/src/config/pmConfig.c	(revision 6553)
@@ -3,6 +3,6 @@
  *  @author PAP, IfA
  *
- *  @version $Revision: 1.7.4.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-02-24 04:02:19 $
+ *  @version $Revision: 1.7.4.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-03-09 03:09:28 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -12,4 +12,5 @@
 #include <string.h>
 #include <unistd.h>
+#include <assert.h>
 #include "pslib.h"
 #include "pmConfig.h"
@@ -17,4 +18,29 @@
 #define PS_SITE "PS_SITE"               // Name of the environment variable containing the site config file
 #define PS_DEFAULT_SITE "ipprc.config"  // Default site config file
+
+static void configFree(pmConfig *config)
+{
+    psFree(config->site);
+    psFree(config->camera);
+    psFree(config->recipe);
+    psFree(config->arguments);
+    psFree(config->database);
+}
+
+pmConfig *pmConfigAlloc(void)
+{
+    pmConfig *config = psAlloc(sizeof(pmConfig));
+    (void)psMemSetDeallocator(config, (psFreeFunc)configFree);
+
+    // Initialise
+    config->site = NULL;
+    config->camera = NULL;
+    config->recipe = NULL;
+    config->arguments = NULL;
+    config->database = NULL;
+
+    return config;
+}
+
 
 /** readConfig
@@ -57,20 +83,13 @@
 XXX: Must load camera and recipe configuration if specified in the command line.
  *****************************************************************************/
-bool pmConfigRead(
-    psMetadata **site,
-    psMetadata **camera,
-    psMetadata **recipe,
+pmConfig *pmConfigRead(
     int *argc,
     char **argv,
     const char *recipeName)
 {
-    PS_ASSERT_PTR_NON_NULL(site, false);
-    // PS_ASSERT_PTR_NON_NULL(*site, false);
-    PS_ASSERT_PTR_NON_NULL(camera, false);
-    // PS_ASSERT_PTR_NON_NULL(*camera, false);
-    PS_ASSERT_PTR_NON_NULL(recipe, false);
-    // PS_ASSERT_PTR_NON_NULL(*recipe, false);
     PS_ASSERT_INT_POSITIVE(*argc, false);
     PS_ASSERT_PTR_NON_NULL(argv, false);
+
+    pmConfig *config = pmConfigAlloc(); // The configuration, containing site, camera and recipe
 
     //
@@ -120,6 +139,7 @@
     //
 
-    if (!readConfig(site, siteName, "site")) {
-        return false;
+    if (!readConfig(&config->site, siteName, "site")) {
+        psFree(config);
+        return NULL;
     }
     if (cleanupSiteName) {
@@ -127,4 +147,20 @@
     }
 
+
+    //
+    // Next, we do a similar thing for the camera configuration file.  The
+    // file is read and parsed into psMetadata struct "camera".
+    //
+    argNum = psArgumentGet(*argc, argv, "-camera");
+    if (argNum > 0) {
+        psArgumentRemove(argNum, argc, argv);
+        if (argNum >= *argc) {
+            psLogMsg(__func__, PS_LOG_WARN,
+                     "-camera command-line switch provided without the required filename --- ignored.\n");
+        } else {
+            psArgumentRemove(argNum, argc, argv);
+            readConfig(&config->camera, argv[argNum], "camera");
+        }
+    }
 
     //
@@ -141,30 +177,10 @@
         } else {
             psArgumentRemove(argNum, argc, argv);
-            readConfig(recipe, argv[argNum], "recipe");
+            readConfig(&config->recipe, argv[argNum], "recipe");
         }
     }
     // Or, load the recipe from the camera file, if appropriate
-    if (! *recipe && *camera && recipeName) {
-        *recipe = pmConfigRecipeFromCamera(*camera, recipeName);
-    }
-
-
-    //
-    // Next, we do a similar thing for the camera configuration file.  The
-    // file is read and parsed into psMetadata struct "camera".
-    //
-    argNum = psArgumentGet(*argc, argv, "-camera");
-    if (argNum > 0) {
-        psArgumentRemove(argNum, argc, argv);
-        if (argNum >= *argc) {
-            psLogMsg(__func__, PS_LOG_WARN,
-                     "-camera command-line switch provided without the required filename --- ignored.\n");
-        } else {
-            psArgumentRemove(argNum, argc, argv);
-            readConfig(camera, argv[argNum], "camera");
-        }
-    } else {
-        // XXX: Not sure is this is correct.
-        *camera = NULL;
+    if (! config->recipe && config->camera && recipeName) {
+        pmConfigRecipeFromCamera(config, recipeName);
     }
 
@@ -181,5 +197,5 @@
     // with a call to psTimeInitialize.
     //
-    psString timeName = psMetadataLookupStr(&mdok, *site, "TIME");
+    psString timeName = psMetadataLookupStr(&mdok, config->site, "TIME");
     if (mdok && timeName) {
         psTrace(__func__, 7, "Initialising psTime with file %s\n", timeName);
@@ -193,5 +209,5 @@
     // with a call to psLogSetLevel().
     //
-    int logLevel = psMetadataLookupS32(&mdok, *site, "LOGLEVEL");
+    int logLevel = psMetadataLookupS32(&mdok, config->site, "LOGLEVEL");
     if (mdok && logLevel >= 0) {
         psTrace(__func__, 7, "Setting log level to %d\n", logLevel);
@@ -204,5 +220,5 @@
     // with a call to psLogSetFormat().
     //
-    psString logFormat = psMetadataLookupStr(&mdok, *site, "LOGFORMAT");
+    psString logFormat = psMetadataLookupStr(&mdok, config->site, "LOGFORMAT");
     if (mdok && logFormat) {
         psTrace(__func__, 7, "Setting log format to %s\n", logFormat);
@@ -216,5 +232,5 @@
     // XXX: This is not spec'ed in the SDRS.
     //
-    psString logDest = psMetadataLookupStr(&mdok, *site, "LOGDEST");
+    psString logDest = psMetadataLookupStr(&mdok, config->site, "LOGDEST");
     if (mdok && logDest) {
         // XXX: Only stdout and stderr are provided for now; this section should be
@@ -240,5 +256,5 @@
     // XXX: This is not spec'ed in the SDRS.
     //
-    psMetadata *trace = psMetadataLookupMD(&mdok, *site, "TRACE");
+    psMetadata *trace = psMetadataLookupMD(&mdok, config->site, "TRACE");
     if (mdok && trace) {
         psMetadataIterator *traceIter = psMetadataIteratorAlloc(trace, PS_LIST_HEAD, NULL); // Iterator
@@ -268,17 +284,16 @@
         psLogSetLevel(saveLogLevel);
     }
-    return(true);
-}
-
-
-// XXX EAM : was trying headerItem when it was NULL
-// XXX EAM : should just free & return on first failure
-bool pmConfigValidateCamera(
-    const psMetadata *camera,
+
+    return config;
+}
+
+
+bool pmConfigValidateCameraFormat(
+    const psMetadata *cameraFormat,
     const psMetadata *header)
 {
-    // Read the rule for that camera
+    // Read the rule for that camera format
     bool mdStatus = true;
-    psMetadata *rule = psMetadataLookupMD(&mdStatus, camera, "RULE");
+    psMetadata *rule = psMetadataLookupMD(&mdStatus, cameraFormat, "RULE");
     if (! mdStatus || ! rule) {
         psLogMsg(__func__, PS_LOG_WARN, "Unable to read rule for camera.\n");
@@ -289,6 +304,5 @@
     psMetadataIterator *ruleIter = psMetadataIteratorAlloc(rule, PS_LIST_HEAD, NULL); // Rule iterator
     psMetadataItem *ruleItem = NULL;    // Item from the metadata
-    bool match = true;                  // Does it match?
-    while ((ruleItem = psMetadataGetAndIncrement(ruleIter)) && match) {
+    while ((ruleItem = psMetadataGetAndIncrement(ruleIter))) {
         // Check for the existence of the rule
         psMetadataItem *headerItem = psMetadataLookup((psMetadata*)header, ruleItem->name);
@@ -341,92 +355,149 @@
 
     psFree(ruleIter);
-    return match;
-}
-
-
-
-// Work out what camera we have, based on the FITS header and a set of
-// rules specified in the IPP configuration; return the camera configuration
-psMetadata *pmConfigCameraFromHeader(
-    const psMetadata *ipprc,            // The IPP configuration
-    const psMetadata *header)           // The FITS header
-{
-    bool mdStatus = false;  // Metadata lookup status
-    psMetadata *cameras = psMetadataLookupMD(&mdStatus, ipprc, "CAMERAS");
-    if (! mdStatus) {
-        psError(PS_ERR_IO, false, "Unable to find CAMERAS in the configuration.\n");
-        return NULL;
-    }
-    psMetadata *winner = NULL;       // The camera configuration whose rule first matches
-    //  the supplied header
-    // Iterate over the cameras
-    psMetadataIterator *iterator = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL);
-    psMetadataItem *cameraItem = NULL; // Item from the metadata
-
-    while ((cameraItem = psMetadataGetAndIncrement(iterator))) {
-        // Open the camera information
-        psTrace(__func__, 3, "Inspecting camera %s (%s)\n", cameraItem->name,
-                cameraItem->comment);
-        psMetadata *camera = NULL; // The camera metadata
-        if (cameraItem->type == PS_DATA_METADATA) {
-            camera = psMemIncrRefCounter(cameraItem->data.md);
-        } else if (cameraItem->type == PS_DATA_STRING) {
-            psTrace(__func__, 5, "Reading camera configuration for %s...\n", cameraItem->name);
+    return true;
+}
+
+
+static bool formatFromHeader(psMetadata **format, // Format to return
+                             psMetadata *camera, // Camera configuration
+                             const psMetadata *header, // FITS header
+                             const char *cameraName // Name of camera
+                            )
+{
+    assert(format);
+    assert(camera);
+    assert(header);
+
+    bool result = false;                // Did we find the first match?
+
+    // Read the list of formats
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *formats = psMetadataLookupMD(&mdok, camera, "FORMATS"); // List of formats
+    if (!mdok || !formats) {
+        psLogMsg(__func__, PS_LOG_WARN, "Unable to find list of FORMATS in camera %s --- ignored\n",
+                 cameraName);
+        return false;
+    }
+    // Iterate over the formats
+    psMetadataIterator *formatsIter = psMetadataIteratorAlloc(formats, PS_LIST_HEAD, NULL);
+    psMetadataItem *formatsItem = NULL; // Item from formats
+    while ((formatsItem = psMetadataGetAndIncrement(formatsIter))) {
+        if (formatsItem->type != PS_DATA_STRING) {
+            psLogMsg(__func__, PS_LOG_WARN, "In camera %s, camera format %s is not of type STR --- "
+                     "ignored.\n", cameraName, formatsItem->name);
+            continue;
+        }
+        psTrace(__func__, 5, "Reading camera format for %s...\n", formatsItem->name);
+        unsigned int badLines = 0;  // Number of bad lines in reading camera configuration
+        // Format to test against what we've got
+        psMetadata *testFormat = psMetadataConfigParse(NULL, &badLines, formatsItem->data.V, true);
+        if (badLines > 0) {
+            psLogMsg(__func__, PS_LOG_WARN, "%d bad lines encountered while reading camera"
+                     "format %s\n", badLines, formatsItem->name);
+        }
+        if (pmConfigValidateCameraFormat(testFormat, header)) {
+            if (!*format) {
+                psLogMsg(__func__, PS_LOG_INFO, "Camera %s, format %s matches header.\n", cameraName,
+                         formatsItem->name);
+                *format = psMemIncrRefCounter(testFormat);
+                result = true;
+            } else {
+                psLogMsg(__func__, PS_LOG_WARN, "Camera %s, format %s also matches header --- ignored.\n",
+                         cameraName, formatsItem->name);
+            }
+        }
+        psFree(testFormat);
+    }
+    psFree(formatsIter);
+
+    return result;
+}
+
+// Work out what camera we have, based on the FITS header and a set of rules specified in the IPP
+// configuration; return the camera configuration and format
+psMetadata *pmConfigCameraFormatFromHeader(
+    pmConfig *config,                   // The configuration
+    const psMetadata *header           // The FITS header
+)
+{
+    psMetadata *format = NULL;          // The winning format
+    bool mdok = false;                  // Metadata lookup status
+
+    // If we don't know what sort of camera we have, we try all that we know
+    if (! config->camera) {
+        psMetadata *cameras = psMetadataLookupMD(&mdok, config->site, "CAMERAS");
+        if (! mdok) {
+            psError(PS_ERR_IO, false, "Unable to find CAMERAS in the configuration.\n");
+            return false;
+        }
+
+        // Iterate over the cameras
+        psMetadataIterator *camerasIter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL);
+        psMetadataItem *camerasItem = NULL; // Item from the metadata
+        while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
+            // Open the camera information
+            psTrace(__func__, 3, "Inspecting camera %s (%s)\n", camerasItem->name, camerasItem->comment);
+            if (camerasItem->type != PS_DATA_STRING) {
+                psLogMsg(__func__, PS_LOG_WARN, "Camera configuration for %s in CAMERAS is not of type STR "
+                         "--- ignored.\n", camerasItem->name);
+                continue;
+            }
+
+            psTrace(__func__, 5, "Reading camera configuration for %s...\n", camerasItem->name);
             unsigned int badLines = 0;  // Number of bad lines in reading camera configuration
-            camera = psMetadataConfigParse(NULL, &badLines, cameraItem->data.V, true);
+            // Camera to test against what we've got:
+            psMetadata *testCamera = psMetadataConfigParse(NULL, &badLines, camerasItem->data.V, true);
             if (badLines > 0) {
                 psLogMsg(__func__, PS_LOG_WARN, "%d bad lines encountered while reading camera"
-                         "configuration %s\n", badLines, cameraItem->name);
-            }
-        }
-
-        if (! camera) {
-            psLogMsg(__func__, PS_LOG_WARN, "Unable to interpret camera configuration for %s (%s)\n",
-                     cameraItem->name, cameraItem->comment);
-            continue;
-        }
-
-        if (pmConfigValidateCamera(camera, header)) {
-            if (! winner) {
-                // This is the first match
-                winner = psMemIncrRefCounter(camera);
-                psLogMsg(__func__, PS_LOG_INFO, "FITS header matches camera %s\n",
-                         cameraItem->name);
-            } else {
-                // We have a duplicate match
-                psLogMsg(__func__, PS_LOG_WARN, "Additional camera found that matches the rules: %s\n",
-                         cameraItem->name);
-            }
-        } // Done inspecting the camera
-
-        psFree(camera);
-
-    } // Done looking at all cameras
-    if (! winner) {
-        psError(PS_ERR_IO, true, "Unable to find an camera that matches input FITS header!\n");
-    }
-
-    psFree(iterator);
-    return winner;
-}
-
-psMetadata *pmConfigRecipeFromCamera(
-    const psMetadata *camera,
+                         "configuration %s\n", badLines, camerasItem->name);
+            }
+            if (! testCamera) {
+                psLogMsg(__func__, PS_LOG_WARN, "Unable to interpret camera configuration for %s (%s) --- "
+                         "ignored\n", camerasItem->name, camerasItem->comment);
+                continue;
+            }
+
+            if (formatFromHeader(&format, testCamera, header, camerasItem->name)) {
+                config->camera = psMemIncrRefCounter(testCamera);
+            }
+            psFree(testCamera);
+        } // Done looking at all cameras
+        psFree(camerasIter);
+
+        if (! config->camera) {
+            psError(PS_ERR_IO, true, "Unable to find a camera that matches input FITS header!\n");
+            return NULL;
+        }
+
+        return format;
+    }
+
+    // Otherwise, try the specific camera
+    if (! formatFromHeader(&format, config->camera, header, "specified camera")) {
+        psError(PS_ERR_IO, true, "Unable to find a format with the specified camera that matches the "
+                "given header.\n");
+        return NULL;
+    }
+    return format;
+}
+
+bool pmConfigRecipeFromCamera(
+    pmConfig *config,
     const char *recipeName)
 {
-    PS_ASSERT_PTR_NON_NULL(camera, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(config->camera, false);
     PS_ASSERT_PTR_NON_NULL(recipeName, false);
 
-    psMetadata *recipe = NULL;          // Recipe to read
     bool mdok = true;                   // Status of MD lookup
-    psMetadata *recipes = psMetadataLookupMD(&mdok, camera, "RECIPES"); // The list of recipes
+    psMetadata *recipes = psMetadataLookupMD(&mdok, config->camera, "RECIPES"); // The list of recipes
     if (! mdok || ! recipes) {
         psLogMsg(__func__, PS_LOG_WARN, "RECIPES in the camera configuration file is not of type METADATA\n");
-    } else {
-        psString recipeFileName = psMetadataLookupStr(&mdok, recipes, recipeName);
-        (void)readConfig(&recipe, recipeFileName, "recipe");
-    }
-
-    return recipe;
+        return false;
+    }
+    psString recipeFileName = psMetadataLookupStr(&mdok, recipes, recipeName);
+    (void)readConfig(&config->recipe, recipeFileName, "recipe");
+
+    return true;
 }
 
Index: /branches/rel10_ifa/psModules/src/config/pmConfig.h
===================================================================
--- /branches/rel10_ifa/psModules/src/config/pmConfig.h	(revision 6552)
+++ /branches/rel10_ifa/psModules/src/config/pmConfig.h	(revision 6553)
@@ -3,6 +3,6 @@
  *  @author PAP, IfA
  *
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-02-02 04:51:14 $
+ *  @version $Revision: 1.3.4.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-03-09 03:09:28 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -15,7 +15,19 @@
 
 
+// Configuration information
+typedef struct
+{
+    psMetadata *site;                   // Site configuration
+    psMetadata *camera;                 // Camera specification
+    psMetadata *recipe;                 // Recipe for processing
+    psMetadata *arguments;              // Command-line arguments
+    psDB *database;                     // Database handle
+}
+pmConfig;
+
+pmConfig *pmConfigAlloc(void);
 
 /** pmConfigRead
- * 
+ *
  * pmConfigRead shall load the site configuration (according to the above rule
  * for determining the source). The camera configuration shall also be loaded if
@@ -32,62 +44,54 @@
  *
  */
-bool pmConfigRead(
-    psMetadata **site,
-    psMetadata **camera,
-    psMetadata **recipe,
+pmConfig *pmConfigRead(
     int *argc,
     char **argv,
-    const char *recipeName
-);
-
+    const char *recipeName);
 
 
 /** pmConfigValidateCamera
- * 
+ *
  * This function, used by pmConfigCameraFromHeader, shall return true if the
  * FITS header matches the rule contained in the camera configuration (see
  * x2.2.2.3); otherwise it shall return false.
- * 
+ *
  */
-bool pmConfigValidateCamera(
-    const psMetadata *camera,
-    const psMetadata *header
-);
-
+bool pmConfigValidateCameraFormat(
+    const psMetadata *cameraFormat,
+    const psMetadata *header);
 
 
 /** pmConfigCameraFromHeader
- * 
+ *
  * pmConfigCameraFromHeader shall load the camera configuration based on the
  * contents of the FITS header, using the list of known cameras contained in the
  * site configuration. If more than one camera matches the FITS header, a warning
  * shall be generated and the first matching camera returned.
- * 
+ *
  */
-psMetadata *pmConfigCameraFromHeader(
-    const psMetadata *site,
-    const psMetadata *header
+psMetadata *pmConfigCameraFormatFromHeader(
+    pmConfig *config,                   // The configuration
+    const psMetadata *header           // The FITS header
 );
 
 
-
 /** pmConfigRecipeFromCamera
- * 
+ *
  * pmConfigRecipeFromCamera shall load the recipe configuration based on the
- * recipeName and the list of known recipes contained in the camera 
+ * recipeName and the list of known recipes contained in the camera
  * configuration.
- * 
+ *
  */
-psMetadata *pmConfigRecipeFromCamera(
-    const psMetadata *camera,
+bool pmConfigRecipeFromCamera(
+    pmConfig *config,
     const char *recipeName
 );
 
 /** pmConfigDB
- * 
+ *
  * pmConfigDB shall use the site configuration data to open a database handle.
  * This is fairly straightforward at the moment, but will change when we beef up
  * security. (TBD)
- * 
+ *
  */
 #ifdef DOMIT_PSDB
