Index: trunk/psModules/src/config/pmConfigCamera.c
===================================================================
--- trunk/psModules/src/config/pmConfigCamera.c	(revision 12639)
+++ trunk/psModules/src/config/pmConfigCamera.c	(revision 12696)
@@ -1,4 +1,4 @@
 #ifdef HAVE_CONFIG_H
-# include "config.h"
+#include <config.h>
 #endif
 
@@ -7,9 +7,9 @@
 #include <pslib.h>
 
+#include "pmHDU.h"
+#include "pmFPA.h"
 #include "pmFPALevel.h"
 #include "pmConcepts.h"
-
 #include "pmConfigCamera.h"
-
 
 #define TABLE_OF_CONTENTS "CONTENTS"    // Name for camera format metadata containing the contents
@@ -17,75 +17,82 @@
 #define CELL_TYPES "CELLS"              // Name for camera format metadata containing the cell types
 
-
-// Remove a concept from the list of sources.  Need to check to see if it exists first, to avoid a warning.
-static void removeConcept(psMetadata *source, // Source from which to remove concept
-                          const char *concept // Concept name to remove
-                         )
+// local helper functions defined below
+static void removeCellConceptsSources(psMetadata *source);
+static void removeChipConceptsSources(psMetadata *source);
+
+// Generate the Chip and FPA mosaicked version of a named camera configuration
+bool pmConfigCameraMosaickedVersions(psMetadata *site, // The site configuration
+                                     const char *name // Name of the un-mosaicked camera
+                                    )
 {
-    assert(source);
-    assert(concept && strlen(concept) > 0);
-
-    if (psMetadataLookup(source, concept)) {
-        psMetadataRemoveKey(source, concept);
-    }
-
-    return;
+    PS_ASSERT_METADATA_NON_NULL(site, false);
+    PS_ASSERT_STRING_NON_EMPTY(name, false);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *cameras = psMetadataLookupMetadata(&mdok, 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 (!pmConfigGenerateMosaickedVersion(cameras, cameras, name, PM_FPA_LEVEL_CHIP)) {
+        psError(PS_ERR_UNKNOWN, true, "Failed to build Chip mosaic camera description for %s\n", name);
+        return false;
+    }
+    if (!pmConfigGenerateMosaickedVersion(cameras, cameras, name, PM_FPA_LEVEL_FPA)) {
+        psError(PS_ERR_UNKNOWN, true, "Failed to build FPA mosaic camera description for %s\n", name);
+        return false;
+    }
+    return true;
 }
 
-// Remove certain concepts from the list of sources.  These concepts are important in the mosaicking process,
-// and are added explicitly to the defaults (elsewhere) so that the user can't get them wrong.
-static void removeCellConceptsSources(psMetadata *source // Source for concepts
+// the operation putting the new entries first is now implemented in pmConfigGenerateMosaickedVersion
+// Generate the Chip and FPA mosaicked version of a named camera configuration
+bool pmConfigCameraMosaickedVersionsAll(psMetadata *site)
+{
+    PS_ASSERT_METADATA_NON_NULL(site, false);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *cameras = psMetadataLookupMetadata(&mdok, 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;
+    }
+
+    psMetadataIterator *camerasIter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *camerasItem = NULL; // Item from iteration
+    psMetadata *new = psMetadataAlloc();// New cameras to add
+    while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
+        assert(camerasItem->type == PS_DATA_METADATA); // Only metadata are allowed here!
+        if (!pmConfigGenerateMosaickedVersion(cameras, new, camerasItem->name, PM_FPA_LEVEL_CHIP)) {
+	    psError(PS_ERR_UNKNOWN, true, "Failed to build Chip mosaic camera description for %s\n", camerasItem->name);
+	    return false;
+	}
+        if (!pmConfigGenerateMosaickedVersion(cameras, new, camerasItem->name, PM_FPA_LEVEL_FPA)) {
+	    psError(PS_ERR_UNKNOWN, true, "Failed to build FPA mosaic camera description for %s\n", camerasItem->name);
+	    return false;
+	}
+    }
+    psFree(camerasIter);
+
+    // Now put the new cameras at the top of the list of cameras, so they get recognised first
+    // Note: going from the top, and putting everything to the top as we get there, so that the last one on
+    // goes to the top.  This preserves the original order of the cameras, putting the mosaicked versions
+    // before the originals.
+    camerasIter = psMetadataIteratorAlloc(new, PS_LIST_HEAD, NULL); // Iterator
+    while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
+        psMetadataAddItem(cameras, camerasItem, PS_LIST_HEAD, 0);
+    }
+    psFree(camerasIter);
+    psFree(new);
+
+    return true;
+}
+
+// Generate a mosaicked version of a camera configuration
+bool pmConfigGenerateMosaickedVersion(psMetadata *oldCameras, // Old list of camera configurations
+				      psMetadata *newCameras, // New list of camera configurations
+				      const char *name, // Name of original camera configuration
+				      pmFPALevel mosaicLevel // Level to which we are mosaicking
     )
-{
-    if (!source) {
-        return;
-    }
-
-    removeConcept(source, "CELL.BIASSEC");
-    removeConcept(source, "CELL.TRIMSEC");
-    removeConcept(source, "CELL.XPARITY");
-    removeConcept(source, "CELL.YPARITY");
-    removeConcept(source, "CELL.X0");
-    removeConcept(source, "CELL.Y0");
-
-    // For the sake of the defaults, include the .DEPEND
-    removeConcept(source, "CELL.XPARITY.DEPEND");
-    removeConcept(source, "CELL.YPARITY.DEPEND");
-    removeConcept(source, "CELL.X0.DEPEND");
-    removeConcept(source, "CELL.Y0.DEPEND");
-
-    return;
-}
-
-// Remove certain concepts from the list of sources.  These concepts are important in the mosaicking process,
-// and are added explicitly to the defaults (elsewhere) so that the user can't get them wrong.
-static void removeChipConceptsSources(psMetadata *source // Source for concepts
-    )
-{
-    if (!source) {
-        return;
-    }
-
-    removeConcept(source, "CHIP.XPARITY");
-    removeConcept(source, "CHIP.YPARITY");
-    removeConcept(source, "CHIP.X0");
-    removeConcept(source, "CHIP.Y0");
-
-    // For the sake of the defaults, include the .DEPEND
-    removeConcept(source, "CHIP.XPARITY.DEPEND");
-    removeConcept(source, "CHIP.YPARITY.DEPEND");
-    removeConcept(source, "CHIP.X0.DEPEND");
-    removeConcept(source, "CHIP.Y0.DEPEND");
-
-    return;
-}
-
-// Generate a mosaicked version of a camera configuration
-// XXX EAM : the error states of this function need to be more carefully considered
-static bool mosaickedVersion(psMetadata *oldCameras, // Old list of camera configurations
-                             psMetadata *newCameras, // New list of camera configurations
-                             const char *name, // Name of original camera configuration
-                             pmFPALevel mosaicLevel // Level to which we are mosaicking
-                            )
 {
     assert(oldCameras);
@@ -97,5 +104,4 @@
     psMetadata *camera = psMetadataLookupMetadata(NULL, oldCameras, name); // The camera configuration
     if (!camera) {
-        // XXX is this an error?
         psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find camera to be mosaicked in camera list.");
         return false;
@@ -485,57 +491,66 @@
 }
 
-// Generate the chip mosaicked version of a camera configuration
-bool pmConfigCameraMosaickedVersions(psMetadata *site, // The site configuration
-                                     const char *name // Name of the un-mosaicked camera
-                                    )
+/*** Helper Functions ***/
+
+// Remove a concept from the list of sources.  Need to check to see if it exists first, to avoid a warning.
+static void removeConcept(psMetadata *source, // Source from which to remove concept
+                          const char *concept // Concept name to remove
+                         )
 {
-    PS_ASSERT_METADATA_NON_NULL(site, false);
-    PS_ASSERT_STRING_NON_EMPTY(name, false);
-
-    bool mdok;                          // Status of MD lookup
-    psMetadata *cameras = psMetadataLookupMetadata(&mdok, 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;
-    }
-    return mosaickedVersion(cameras, cameras, name, PM_FPA_LEVEL_CHIP) &&
-           mosaickedVersion(cameras, cameras, name, PM_FPA_LEVEL_FPA);
+    assert(source);
+    assert(concept && strlen(concept) > 0);
+
+    if (psMetadataLookup(source, concept)) {
+        psMetadataRemoveKey(source, concept);
+    }
+
+    return;
 }
 
-// XXX EAM : shouldn't this loop over the unmosaicked camera names, calling the above function?
-// the operation putting the new entries first is now implemented in mosaickedVersion
-bool pmConfigCameraMosaickedVersionsAll(psMetadata *site)
+// Remove certain concepts from the list of sources.  These concepts are important in the mosaicking process,
+// and are added explicitly to the defaults (elsewhere) so that the user can't get them wrong.
+static void removeCellConceptsSources(psMetadata *source // Source for concepts
+    )
 {
-    PS_ASSERT_METADATA_NON_NULL(site, false);
-
-    bool mdok;                          // Status of MD lookup
-    psMetadata *cameras = psMetadataLookupMetadata(&mdok, 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;
-    }
-
-    psMetadataIterator *camerasIter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL); // Iterator
-    psMetadataItem *camerasItem = NULL; // Item from iteration
-    psMetadata *new = psMetadataAlloc();// New cameras to add
-    while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
-        assert(camerasItem->type == PS_DATA_METADATA); // Only metadata are allowed here!
-        mosaickedVersion(cameras, new, camerasItem->name, PM_FPA_LEVEL_CHIP);
-        mosaickedVersion(cameras, new, camerasItem->name, PM_FPA_LEVEL_FPA);
-    }
-    psFree(camerasIter);
-
-    // Now put the new cameras at the top of the list of cameras, so they get recognised first
-    // Note: going from the top, and putting everything to the top as we get there, so that the last one on
-    // goes to the top.  This preserves the original order of the cameras, putting the mosaicked versions
-    // before the originals.
-    camerasIter = psMetadataIteratorAlloc(new, PS_LIST_HEAD, NULL); // Iterator
-    while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
-        psMetadataAddItem(cameras, camerasItem, PS_LIST_HEAD, 0);
-    }
-    psFree(camerasIter);
-    psFree(new);
-
-    return true;
+    if (!source) {
+        return;
+    }
+
+    removeConcept(source, "CELL.BIASSEC");
+    removeConcept(source, "CELL.TRIMSEC");
+    removeConcept(source, "CELL.XPARITY");
+    removeConcept(source, "CELL.YPARITY");
+    removeConcept(source, "CELL.X0");
+    removeConcept(source, "CELL.Y0");
+
+    // For the sake of the defaults, include the .DEPEND
+    removeConcept(source, "CELL.XPARITY.DEPEND");
+    removeConcept(source, "CELL.YPARITY.DEPEND");
+    removeConcept(source, "CELL.X0.DEPEND");
+    removeConcept(source, "CELL.Y0.DEPEND");
+
+    return;
 }
 
+// Remove certain concepts from the list of sources.  These concepts are important in the mosaicking process,
+// and are added explicitly to the defaults (elsewhere) so that the user can't get them wrong.
+static void removeChipConceptsSources(psMetadata *source // Source for concepts
+    )
+{
+    if (!source) {
+        return;
+    }
+
+    removeConcept(source, "CHIP.XPARITY");
+    removeConcept(source, "CHIP.YPARITY");
+    removeConcept(source, "CHIP.X0");
+    removeConcept(source, "CHIP.Y0");
+
+    // For the sake of the defaults, include the .DEPEND
+    removeConcept(source, "CHIP.XPARITY.DEPEND");
+    removeConcept(source, "CHIP.YPARITY.DEPEND");
+    removeConcept(source, "CHIP.X0.DEPEND");
+    removeConcept(source, "CHIP.Y0.DEPEND");
+
+    return;
+}
