Index: trunk/psModules/src/config/pmConfig.c
===================================================================
--- trunk/psModules/src/config/pmConfig.c	(revision 10882)
+++ trunk/psModules/src/config/pmConfig.c	(revision 10965)
@@ -4,6 +4,6 @@
  *  @author EAM (IfA)
  *
- *  @version $Revision: 1.69 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-01-03 02:58:38 $
+ *  @version $Revision: 1.70 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-01-08 22:26:06 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -26,9 +26,18 @@
 #include "pmConfig.h"
 #include "pmConfigRecipes.h"
+#include "pmConfigCamera.h"
 
 #define PS_SITE "PS_SITE"         // Name of the environment variable containing the site config file
 #define PS_DEFAULT_SITE ".ipprc"  // Default site config file
 
+static bool readCameraConfig = true;    // Read the camera config on startup (with pmConfigRead)?
 static psArray *configPath = NULL;      // Search path for configuration files
+
+bool pmConfigReadParamsSet(bool newReadCameraConfig)
+{
+    bool oldReadCameraConfig = readCameraConfig;
+    readCameraConfig = newReadCameraConfig;
+    return oldReadCameraConfig;
+}
 
 static void configFree(pmConfig *config)
@@ -38,4 +47,6 @@
     psFree(config->camera);
     psFree(config->cameraName);
+    psFree(config->format);
+    psFree(config->formatName);
     psFree(config->recipes);
     psFree(config->recipeSymbols);
@@ -53,4 +64,6 @@
     config->camera = NULL;
     config->cameraName = NULL;
+    config->format = NULL;
+    config->formatName = NULL;
     config->recipes = psMetadataAlloc();
     config->recipesRead = PM_RECIPE_SOURCE_NONE;
@@ -207,4 +220,65 @@
 
     psFree (realName);
+    return true;
+}
+
+// Read metadata config files in a metadata
+// The metadata contains file names, which will be replaced with the metadata that are in the files.
+static bool metadataReadFiles(psMetadata *source, // Source metadata
+                              const char *description // Description, for error messages
+                             )
+{
+    assert(source);
+    psMetadataIterator *iter = psMetadataIteratorAlloc(source, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item;               // Item from iteration
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (item->type == PS_DATA_METADATA) {
+            continue;       // We've already read it
+        }
+        if (item->type != PS_DATA_STRING) {
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Element %s in %s metadata is not of type STR.\n",
+                    item->name, description);
+            continue;
+        }
+
+        psTrace("config", 2, "Reading %s %s: %s\n", description, item->name, item->data.str);
+        psMetadata *new = NULL;         // New metadata
+        if (!pmConfigFileRead(&new, item->data.str, item->name)) {
+            psLogMsg("psModules.config", PS_LOG_WARN, "Trouble reading reading %s %s --- "
+                     "ignored.\n", description, item->name);
+            psFree(new);
+            psMetadataRemoveKey(source, item->name); // Take it out, so it will not trouble us again
+            continue;
+        }
+
+        // Muck around under the hood to replace the filename with the metadata; don't try this at home, kids
+        item->type = PS_DATA_METADATA;
+        psFree(item->data.str);
+        item->data.md = new;
+    }
+    psFree(iter);
+
+    return true;
+}
+
+// Read the formats for a camera
+static bool cameraReadFormats(psMetadata *camera, // Camera for which to read the formats
+                              const char *name // Name of the camera, for error messages
+                             )
+{
+    assert(camera);
+    assert(name);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *formats = psMetadataLookupMetadata(&mdok, camera, "FORMATS"); // Formats
+    if (!mdok || !formats) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find FORMATS in camera configuration %s.\n", name);
+        return false;
+    }
+    if (!metadataReadFiles(formats, "camera format")) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read formats within camera configuration %s.\n", name);
+        return false;
+    }
+
     return true;
 }
@@ -274,6 +348,4 @@
     }
 
-
-
     // Set options based on the site configuration.
     {
@@ -437,4 +509,57 @@
             pmConfigFileRead(&config->camera, cameraFile, "camera");
             psArgumentRemove(argNum, config->argc, config->argv);
+
+            // Read in the formats
+            if (!cameraReadFormats(config->camera, cameraFile)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to read formats within camera configuration %s.\n",
+                        cameraFile);
+                psFree(config);
+                return NULL;
+            }
+
+            psMetadataAddMetadata(cameras, PS_LIST_HEAD, cameraFile, PS_META_REPLACE,
+                                  "Camera specified on command line", config->camera);
+
+            if (!pmConfigCameraMosaickedVersions(config->site, cameraFile)) {
+                psError(PS_ERR_UNKNOWN, false,
+                        "Unable to generate mosaicked versions of specified camera %s.\n",
+                        cameraFile);
+                psFree(config);
+                return NULL;
+            }
+        }
+    }
+
+    // Read the camera configurations, if not already defined, and not turned off
+    if (!config->camera && readCameraConfig) {
+        bool mdok;                      // Status of MD lookup
+        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->site, "CAMERAS"); // List of cameras
+        if (!mdok || !cameras) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the site configuration.\n");
+            return false;
+        }
+
+        if (!metadataReadFiles(cameras, "camera configuration")) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read cameras within site configuration.\n");
+            psFree(config);
+            return NULL;
+        }
+
+        // Now fill in the formats
+        psMetadataIterator *iter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL); // Iterator
+        psMetadataItem *item;           // Item from iteration
+        while ((item = psMetadataGetAndIncrement(iter))) {
+            assert(item->type == PS_DATA_METADATA);
+            if (!cameraReadFormats(item->data.md, item->name)) {
+                psWarning("Unable to read formats for camera %s: removed.\n", item->name);
+                psMetadataRemoveKey(cameras, item->name);
+            }
+        }
+        psFree(iter);
+
+        if (!pmConfigCameraMosaickedVersionsAll(config->site)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate mosaicked versions of cameras.\n");
+            psFree(config);
+            return NULL;
         }
     }
@@ -448,11 +573,11 @@
 
     // load command-line options of the form -recipe NAME RECIPE
-    pmConfigLoadRecipeArguments (config);
+    pmConfigLoadRecipeArguments(config);
 
     // read in command-line options to specific recipe values
-    pmConfigLoadRecipeOptions (config, "-D");
-    pmConfigLoadRecipeOptions (config, "-Di");
-    pmConfigLoadRecipeOptions (config, "-Df");
-    pmConfigLoadRecipeOptions (config, "-Db");
+    pmConfigLoadRecipeOptions(config, "-D");
+    pmConfigLoadRecipeOptions(config, "-Di");
+    pmConfigLoadRecipeOptions(config, "-Df");
+    pmConfigLoadRecipeOptions(config, "-Db");
 
 
@@ -589,6 +714,8 @@
 }
 
+
 // Given a camera and a header, see if any of the camera formats match the header
 static bool formatFromHeader(psMetadata **format, // Format to return
+                             psString *name, // Name to return
                              psMetadata *camera, // Camera configuration
                              const psMetadata *header, // FITS header
@@ -610,28 +737,27 @@
         return false;
     }
+
+    if (!metadataReadFiles(formats, "camera format")) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read cameras formats within camera configuration.\n");
+        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) {
-            psError(PS_ERR_UNKNOWN, false, "In camera %s, camera format %s is not of type STR", cameraName, formatsItem->name);
-            return false;
-        }
-        psTrace("psModules.config", 5, "Reading camera format for %s...\n", formatsItem->name);
-        psMetadata *testFormat = NULL;  // Format to test against what we've got
-        if (!pmConfigFileRead(&testFormat, formatsItem->data.V, formatsItem->name)) {
-            psError(PS_ERR_UNKNOWN, false, "Trouble reading reading camera format %s", formatsItem->name);
-            psFree(testFormat);
-            return false;
-        }
+        assert(formatsItem->type == PS_DATA_METADATA); // Since we have just read it in or deleted it
+        psMetadata *testFormat = formatsItem->data.md; // Format to test against
 
         if (pmConfigValidateCameraFormat(testFormat, header)) {
             if (!*format) {
-                psLogMsg("psModules.config", PS_LOG_INFO, "Camera %s, format %s matches header.\n", cameraName,
-                         formatsItem->name);
+                psLogMsg("psModules.config", PS_LOG_INFO, "Camera %s, format %s matches header.\n",
+                         cameraName, formatsItem->name);
                 *format = psMemIncrRefCounter(testFormat);
+                *name = psStringCopy(formatsItem->name);
                 result = true;
             } else {
-                psLogMsg("psModules.config", PS_LOG_WARN, "Camera %s, format %s also matches header --- ignored.\n",
+                psLogMsg("psModules.config", PS_LOG_WARN,
+                         "Camera %s, format %s also matches header --- ignored.\n",
                          cameraName, formatsItem->name);
             }
@@ -639,10 +765,10 @@
             psErr *error = psErrorLast();
             if (error->code != PS_ERR_NONE) {
-                psError (PS_ERR_UNKNOWN, false, "Error in config scripts for camera %s, format %s\n", cameraName, formatsItem->name);
+                psError (PS_ERR_UNKNOWN, false, "Error in config scripts for camera %s, format %s\n",\
+                         cameraName, formatsItem->name);
                 return false;
             }
             psFree(error);
         }
-        psFree(testFormat);
     }
     psFree(formatsIter);
@@ -657,13 +783,20 @@
     PS_ASSERT_PTR_NON_NULL(header, NULL);
 
+
     psMetadata *format = NULL;          // The winning format
-    bool mdok = false;                  // Metadata lookup status
+    psString name = NULL;               // Name of the winning format
 
     // If we don't know what sort of camera we have, we try all that we know
     if (! config->camera) {
+        bool mdok;                      // Metadata lookup status
         psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->site, "CAMERAS");
-        if (! mdok) {
+        if (! mdok || !cameras) {
             psError(PS_ERR_IO, true, "Unable to find CAMERAS in the configuration.");
-            return false;
+            return NULL;
+        }
+
+        if (!metadataReadFiles(cameras, "camera configuration")) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read cameras within site configuration.\n");
+            return NULL;
         }
 
@@ -675,23 +808,11 @@
             psTrace("psModules.config", 3, "Inspecting camera %s (%s)\n", camerasItem->name,
                     camerasItem->comment);
-            if (camerasItem->type != PS_DATA_STRING) {
-                psLogMsg("psModules.config", PS_LOG_WARN, "Camera configuration for %s in CAMERAS is not of type STR "
-                         "--- ignored.\n", camerasItem->name);
-                continue;
-            }
-
-            psTrace("psModules.config", 5, "Reading camera configuration for %s...\n", camerasItem->name);
-            psMetadata *testCamera = NULL; // Camera to test against what we've got:
-
-            if (!pmConfigFileRead(&testCamera, camerasItem->data.V, camerasItem->name)) {
-                psLogMsg("psModules.config", PS_LOG_WARN, "Trouble reading reading camera configuration %s --- "
-                         "ignored.\n", camerasItem->name);
-                psFree(testCamera);
-                continue;
-            }
-
-            if (formatFromHeader(&format, testCamera, header, camerasItem->name)) {
+            assert(camerasItem->type == PS_DATA_METADATA); // It should be because we've read it in or deleted
+            psMetadata *testCamera = camerasItem->data.md; // Camera to test against what we've got:
+            if (formatFromHeader(&format, &name, testCamera, header, camerasItem->name)) {
                 config->camera = psMemIncrRefCounter(testCamera);
                 config->cameraName = psStringCopy(camerasItem->name);
+                config->formatName = name;
+                config->format = psMemIncrRefCounter(format);
             } else {
                 psErr *error = psErrorLast();
@@ -702,5 +823,4 @@
                 psFree(error);
             }
-            psFree(testCamera);
         } // Done looking at all cameras
         psFree(camerasIter);
@@ -717,9 +837,11 @@
 
     // Otherwise, try the specific camera
-    if (!formatFromHeader(&format, config->camera, header, config->cameraName)) {
+    if (!formatFromHeader(&format, &name, config->camera, header, config->cameraName)) {
         psError(PS_ERR_IO, true, "Unable to find a format with the specified camera (%s) that matches the "
                 "given header.\n", config->cameraName);
         return NULL;
     }
+    config->formatName = name;
+    config->format = psMemIncrRefCounter(format);
     return format;
 }
