Index: /trunk/psModules/src/config/pmConfig.c
===================================================================
--- /trunk/psModules/src/config/pmConfig.c	(revision 12543)
+++ /trunk/psModules/src/config/pmConfig.c	(revision 12544)
@@ -4,6 +4,6 @@
  *  @author EAM (IfA)
  *
- *  @version $Revision: 1.79 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-03-20 01:30:45 $
+ *  @version $Revision: 1.80 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-03-22 18:07:18 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -829,5 +829,5 @@
             }
         } // Done looking at all cameras
-        psFree(camerasIter);
+	psFree(camerasIter);
 
         if (! config->camera) {
@@ -837,5 +837,8 @@
 
         // Now we have the camera, we can read the recipes
-        pmConfigReadRecipes(config, PM_RECIPE_SOURCE_CAMERA | PM_RECIPE_SOURCE_CL);
+        if (!pmConfigReadRecipes(config, PM_RECIPE_SOURCE_CAMERA | PM_RECIPE_SOURCE_CL)) {
+	    psError(PS_ERR_IO, false, "Error reading recipes from camera config for %s", config->cameraName);
+	    return NULL;
+	}
         return psMemIncrRefCounter(format);
     }
Index: /trunk/psModules/src/config/pmConfigRecipes.c
===================================================================
--- /trunk/psModules/src/config/pmConfigRecipes.c	(revision 12543)
+++ /trunk/psModules/src/config/pmConfigRecipes.c	(revision 12544)
@@ -15,8 +15,9 @@
 #include "pmConfigRecipes.h"
 
-static bool loadRecipeFiles(pmConfig *config, psMetadata *source, pmRecipeSource type, const char *name);
-static bool loadRecipeFromArguments(pmConfig *config);
-static bool loadRecipeSymbols(pmConfig *config);
-static bool loadRecipeOptions(pmConfig *config);
+static bool loadRecipeSite(bool *status, pmConfig *config, psMetadata *source);
+static bool loadRecipeCamera(bool *status, pmConfig *config, psMetadata *source);
+static bool loadRecipeFromArguments(bool *status, pmConfig *config);
+static bool loadRecipeSymbols(bool *status, pmConfig *config);
+static bool loadRecipeOptions(bool *status, pmConfig *config);
 
 // use this function to select the options structure for the specified recipe
@@ -24,38 +25,35 @@
 psMetadata *pmConfigRecipeOptions (pmConfig *config, char *recipeName)
 {
-
-    // if the recipe is already defined in config->arguments, supplement
+    bool success;
+
+    // select or create the OPTIONS folder
+    psMetadata *options = psMetadataLookupMetadata(&success, config->arguments, "OPTIONS");
+    if (!options) {
+        options = psMetadataAlloc ();
+        success = psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "OPTIONS",  PS_DATA_METADATA, "", options);
+	assert (success); // type mismatch : OPTIONS already defined but wrong type
+	psFree (options); // drop extra reference
+    }
+
+    // look for the recipe defined in recipes
+    // if the recipe is already defined in config->arguments:OPTIONS, supplement
     // save the recipe options onto config->arguments:RECIPES
-    psMetadata *options;
-    psMetadataItem *optionsItem = psMetadataLookup(config->arguments, "OPTIONS");
-    if (optionsItem) {
-        assert(optionsItem->type == PS_DATA_METADATA);
-        options = psMemIncrRefCounter(optionsItem->data.V);
-    } else {
-        options = psMetadataAlloc ();
-        psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "OPTIONS",  PS_DATA_METADATA, "", options);
-    }
-
-    // look for the recipe defined in recipes
-    psMetadata *recipe;
-    psMetadataItem *recipeItem = psMetadataLookup(options, recipeName);
-    psFree(options);                   // Drop reference
-    if (recipeItem) {
-        assert(recipeItem->type == PS_DATA_METADATA);
-        recipe = psMemIncrRefCounter(recipeItem->data.V);
-    } else {
+    psMetadata *recipe = psMetadataLookupMetadata(&success, options, recipeName);
+    if (!recipe) {
         recipe = psMetadataAlloc();
-        psMetadataAddPtr(options, PS_LIST_TAIL, recipeName,  PS_DATA_METADATA, "", recipe);
-    }
-
+        success = psMetadataAddPtr(options, PS_LIST_TAIL, recipeName,  PS_DATA_METADATA, "", recipe);
+	assert (success); // type mismatch : OPTIONS already defined but wrong type
+	psFree (recipe);  // drop extra reference
+    }
     return recipe;
 }
 
 // this function may be called several times.  it attempts to load the recipe data from one of
-// three locations: config->site, config->camera, and config->argv we cannot read the recipes
+// three locations: config->site, config->camera, and config->argv.  We cannot read the recipes
 // from config->camera until a camera has been read BUT, the argv recipes must override the
 // camera and site recipes.
 bool pmConfigReadRecipes(pmConfig *config, pmRecipeSource source)
 {
+    bool status;
     PS_ASSERT_PTR_NON_NULL(config, false);
 
@@ -65,12 +63,12 @@
 
     // Read the recipe file names from the site configuration and camera configuration
-    // XXX EAM : I think it should be an error for config->site:recipes not to exist
-    // for now, keep this as a warning
+    // It is an error for config->site:recipes not to exist.  all programs install their
+    // master recipe files in the site:recipe location when they are built.
     if (config->site && (source & PM_RECIPE_SOURCE_SITE)) {
-        if (!loadRecipeFiles(config, config->site, PM_RECIPE_SOURCE_SITE, "site configuration")) {
-            psLogMsg ("psModules.config", PS_LOG_WARN, "Failed to read recipes from site config");
-        } else {
-            psTrace ("psModules.config", 3, "read recipes from site config");
-        }
+	if (!loadRecipeSite(&status, config, config->site)) {
+            psError(PS_ERR_IO, false, "Failed to read recipes from site config");
+	    return false;
+        } 
+	psTrace ("psModules.config", 3, "read recipes from site config");
     }
 
@@ -80,35 +78,45 @@
     // set should not override the first set
     if (config->camera && (source & PM_RECIPE_SOURCE_CAMERA) && !(config->recipesRead & PM_RECIPE_SOURCE_CAMERA)) {
-        if (!loadRecipeFiles(config, config->camera, PM_RECIPE_SOURCE_CAMERA, "camera configuration")) {
-            psLogMsg ("psModules.config", PS_LOG_DETAIL, "no recipe supplied by camera config");
-        } else {
-            psTrace ("psModules.config", 3, "read recipes from camera config");
-        }
+        if (!loadRecipeCamera(&status, config, config->camera)) {
+            psError(PS_ERR_IO, false, "Failed to read recipes from camera config");
+	    return false;
+        } 
+	if (status) {
+	    psTrace ("psModules.config", 3, "read recipes from camera config");
+	} else {
+	    psLogMsg ("psModules.config", PS_LOG_DETAIL, "no recipe supplied by camera config");
+	}
     }
 
     // apply recipes loaded into config->arguments based on command-line arguments
     if (config->arguments && (source & PM_RECIPE_SOURCE_CL)) {
-        if (!loadRecipeFromArguments(config)) {
+        if (!loadRecipeFromArguments(&status, config)) {
+            psError(PS_ERR_IO, false, "Failed to read recipes from command-line arguments");
+	    return false;
+        } 
+	if (status) {
+	    psTrace ("psModules.config", 3, "read recipes from command-line arguments");
+	} else {
+	    psLogMsg ("psModules.config", PS_LOG_DETAIL, "no recipe supplied on command-line arguments");
+	}
+        if (!loadRecipeSymbols(&status, config)) {
+            psError(PS_ERR_IO, false, "Failed to read recipes from symbolic references");
+	    return false;
+        } 
+	if (status) {
+	    psTrace ("psModules.config", 3, "read recipes from symbolic references");
+	} else {
+	    psLogMsg ("psModules.config", PS_LOG_DETAIL, "no recipe supplied by symbolic reference");
+	}
+        if (!loadRecipeOptions(&status, config)) {
+            psError(PS_ERR_IO, false, "Failed to read recipes from symbolic references");
+	    return false;
+        } 
+	if (status) {
+            psTrace ("psModules.config", 3, "read recipes from command-line arguments");
+        } else {
             psLogMsg ("psModules.config", PS_LOG_DETAIL, "no recipe supplied on command-line arguments");
-        } else {
-            psTrace ("psModules.config", 3, "read recipes from command-line arguments");
-        }
-        if (!loadRecipeSymbols(config)) {
-            psLogMsg ("psModules.config", PS_LOG_DETAIL, "no recipe supplied on command-line arguments");
-        } else {
-            psTrace ("psModules.config", 3, "read recipes from command-line arguments");
-        }
-        if (!loadRecipeOptions(config)) {
-            psLogMsg ("psModules.config", PS_LOG_DETAIL, "no recipe supplied on command-line arguments");
-        } else {
-            psTrace ("psModules.config", 3, "read recipes from command-line arguments");
-        }
-    }
-    /*
-     * We may have seen real errors, but we also get false status returned by valid conditions (e.g. asking a
-     * file for a recipe when none was provided).  For now we'll never signal an error, but this should
-     * be reconsidered ASAP.
-     */
-    psErrorClear();
+        }
+    }
     return true;
 }
@@ -117,20 +125,15 @@
 bool pmConfigLoadRecipeOptions (pmConfig *config, char *flag)
 {
-
+    bool success;
     int argNum;
 
     // save the recipes onto config->arguments:RECIPES
-    // increment so we can free below (is a NOP is options is NULL)
-    psMetadata *options;                // OPTIONS on the arguments
-    psMetadataItem *optionsItem = psMetadataLookup(config->arguments, "OPTIONS");
-    if (optionsItem) {
-        if (optionsItem->type != PS_DATA_METADATA) {
-            psAbort("OPTIONS is not of type METADATA.");
-        }
-        options = psMemIncrRefCounter(optionsItem->data.V);
-    } else {
+    // increment so we can free below (is a NOP if 'options' is NULL)
+    psMetadata *options = psMetadataLookupMetadata(&success, config->arguments, "OPTIONS");
+    if (!options) {
         options = psMetadataAlloc();
-        psMetadataAddPtr(config->arguments, PS_LIST_TAIL, "OPTIONS",  PS_DATA_METADATA,
-                         "Command-line options specified with -D", options);
+        success = psMetadataAddPtr(config->arguments, PS_LIST_TAIL, "OPTIONS",  PS_DATA_METADATA, "Command-line options specified with -D", options);
+	assert (success); // type mismatch : OPTIONS already defined but wrong type
+	psFree (options); // drop extra reference
     }
 
@@ -168,12 +171,10 @@
 
         // if this recipe is already defined in options, supplement
-        psMetadata *recipe;
-        psMetadataItem *recipeItem = psMetadataLookup(options, recipeName);
-        if (recipeItem) {
-            assert(recipeItem->type == PS_DATA_METADATA);
-            recipe = psMemIncrRefCounter(recipeItem->data.V);
-        } else {
+        psMetadata *recipe = psMetadataLookupMetadata(&success, options, recipeName);
+        if (!recipe) {
             recipe = psMetadataAlloc();
-            psMetadataAddPtr(options, PS_LIST_TAIL, recipeName,  PS_DATA_METADATA, "", recipe);
+            success = psMetadataAddPtr(options, PS_LIST_TAIL, recipeName,  PS_DATA_METADATA, "", recipe);
+	    assert (success); // type mismatch : recipe already defined but wrong type
+	    psFree (recipe); // drop extra reference
         }
 
@@ -200,5 +201,4 @@
         }
         psFree (words);
-        psFree (recipe);
         assert (valid);  // flag may be: -D, -Df, -Di, -Db
 
@@ -206,5 +206,4 @@
         psArgumentRemove (argNum, config->argc, config->argv);
     }
-    psFree (options);
     return true;
 }
@@ -216,16 +215,13 @@
 bool pmConfigLoadRecipeArguments (pmConfig *config)
 {
-    psMetadata *recipes;                // Recipes in the arguments list
-    psMetadataItem *recipesItem = psMetadataLookup(config->arguments, "RECIPES");
-    if (recipesItem) {
-        if (recipesItem->type != PS_DATA_METADATA) {
-            psAbort("RECIPES is not of type METADATA.");
-        }
-        recipes = psMemIncrRefCounter(recipesItem->data.V);
-    } else {
+    bool success; 
+
+    psMetadata *recipes = psMetadataLookupMetadata(&success, config->arguments, "RECIPES");
+    if (!recipes) {
         recipes = psMetadataAlloc();
-        psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "RECIPES",  PS_DATA_METADATA, "", recipes);
-    }
-
+        success = psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "RECIPES",  PS_DATA_METADATA, "", recipes);
+	assert (success);
+	psFree (recipes);
+    }
 
     // Go through the command-line arguments
@@ -238,7 +234,7 @@
         }
 
-        const char *recipeName = psStringCopy(config->argv[argNum]); // Name of the recipe
+        char *recipeName = psStringCopy(config->argv[argNum]); // Name of the recipe
         psArgumentRemove(argNum, config->argc, config->argv);
-        const char *recipeSource = psStringCopy(config->argv[argNum]); // Source of the recipe
+        char *recipeSource = psStringCopy(config->argv[argNum]); // Source of the recipe
         psArgumentRemove(argNum, config->argc, config->argv);
 
@@ -265,29 +261,24 @@
         }
         psTrace ("psModules.config", 3, "read recipe %s from %s", recipeName, recipeSource);
-        psFree((void *)recipeName);
-        psFree((void *)recipeSource);
+        psFree(recipeName);
+        psFree(recipeSource);
     } // Iterating through the command-line arguments
 
-    psFree(recipes);                    // Drop reference
-    return true;
-}
-
-// Load the recipe files (valid for SITE | CAMERA)
-// each time we load a specific recipe, it overrides the existing metadata for that recipe
-// for sourceType == SITE | CAMERA, RECIPES contains a list of files to be read (pmConfigFileRead)
-static bool loadRecipeFiles(pmConfig *config, // The configuration into which to read the recipes
-                            psMetadata *source, // The source configuration, from which to read the filenames
-                            pmRecipeSource sourceType, // The source type
-                            const char *sourceName // The name of the source, for error messages
-                           )
-{
+    return true;
+}
+
+// Load the recipe files for SITE : REQUIRED
+static bool loadRecipeSite(bool *status,
+			   pmConfig *config, // The configuration into which to read the recipes
+			   psMetadata *source // The source configuration, from which to read the filenames
+    )
+{
+    assert(status);
     assert(config);
-    if ((sourceType != PM_RECIPE_SOURCE_SITE) && (sourceType != PM_RECIPE_SOURCE_CAMERA)) {
-        psAbort("invalid source for loadRecipes");
-    }
+    *status = false;
+
     if (!source) {
-        psTrace("psModules.config", 4, "The %s has not been read --- cannot read recipes from this "
-                "location.\n", sourceName);
-        config->recipesRead &= ~sourceType;
+        psError(PS_ERR_IO, true, "The site configuration has not been read --- cannot read recipes from this location.\n");
+        config->recipesRead &= ~PM_RECIPE_SOURCE_SITE;
         return false;
     }
@@ -295,6 +286,5 @@
     psMetadata *recipes = psMetadataLookupMetadata(NULL, source, "RECIPES"); // The list of recipes
     if (!recipes) {
-        psLogMsg("psModules.config", PS_LOG_WARN, "RECIPES not found in the %s\n", sourceName);
-        config->recipesRead &= ~sourceType;
+        psError(PS_ERR_IO, false, "RECIPES not found in the site configuration\n");
         return false;
     }
@@ -308,5 +298,6 @@
         // type mismatch is a serious error
         if (fileItem->type != PS_DATA_STRING) {
-            psAbort("%s in %s RECIPES is not of type STR", fileItem->name, sourceName);
+            psError(PS_ERR_IO, true, "%s in site configuration RECIPES is not of type STR", fileItem->name);
+	    return false;
         }
 
@@ -314,27 +305,88 @@
         psMetadata *recipe = NULL;
         if (!pmConfigFileRead(&recipe, fileItem->data.V, "recipe")) {
-            psWarning("Failed to read recipe file %s listed in %s\n", (char *)fileItem->data.V, sourceName);
-            continue;
+            psError(PS_ERR_IO, false, "Failed to read recipe file %s listed in site configuration\n", (char *)fileItem->data.V);
+	    return false;
         }
 
         // if this named recipe exists, supplement it
-        psMetadata *current = NULL;     // Current, extant recipe of the same name, to be supplemented
-        psMetadataItem *currentItem = psMetadataLookup(config->recipes, fileItem->name);
-        if (currentItem) {
-            if (currentItem->type != PS_DATA_METADATA) {
-                psAbort("Item from recipes is not of type METADATA.");
-            }
-            current = psMemIncrRefCounter(currentItem->data.V);
-            psTrace("psModules.config", 3, "Supplementing %s from %s within %s.\n", currentItem->name,
-                    fileItem->name, sourceName);
-        }
-        current = psMetadataCopy(current, recipe);
+	psMetadataAdd(config->recipes, PS_LIST_TAIL, fileItem->name, PS_DATA_METADATA | PS_META_REPLACE,
+		      fileItem->comment, recipe);
         psFree(recipe);  // Drop reference
-        psMetadataAdd(config->recipes, PS_LIST_TAIL, fileItem->name, PS_DATA_METADATA | PS_META_REPLACE,
-                      fileItem->comment, current);
-        psFree(current);  // Drop reference
     }
     psFree(recipesIter);
-    config->recipesRead |= sourceType;
+    config->recipesRead |= PM_RECIPE_SOURCE_SITE;
+
+    *status = true;
+    return true;
+}
+
+// Load the recipe files (valid for SITE | CAMERA)
+// each time we load a specific recipe, it overrides the existing metadata for that recipe
+// for sourceType == SITE | CAMERA, RECIPES contains a list of files to be read (pmConfigFileRead)
+static bool loadRecipeCamera(bool *status, // status variable
+			     pmConfig *config, // The configuration into which to read the recipes
+			     psMetadata *source // The source configuration, from which to read the filenames
+    )
+{
+    bool success;
+
+    assert(status);
+    assert(config);
+    *status = false;
+
+    if (!source) {
+        psError(PS_ERR_IO, true, "The camera configuration has not been read --- cannot read recipes from this location.\n");
+        config->recipesRead &= ~PM_RECIPE_SOURCE_CAMERA;
+        return false;
+    }
+
+    // it is not necessary to define any local recipes in the camera config
+    psMetadata *recipes = psMetadataLookupMetadata(&success, source, "RECIPES"); // The list of recipes
+    if (!recipes) {
+	psTrace ("psModules.config", 3, "RECIPES not found in the camera configuration\n");
+        return true;
+    }
+
+    // Copy contents of the filenames to config->recipes from the "RECIPES" metadata in the source.
+    // We could use psMetadataCopy for this, but it's better to check that everything's of the correct type.
+    // If it's not of the correct type, we can tell the user which file it's in, so they can find it easier.
+    psMetadataIterator *recipesIter = psMetadataIteratorAlloc(recipes, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *fileItem = NULL;    // MD item containing the filename, from recipe iteration
+    while ((fileItem = psMetadataGetAndIncrement(recipesIter))) {
+	char *recipeName = fileItem->name;
+	char *recipeFile = fileItem->data.V;
+
+	psTrace("psModules.config", 3, "Supplementing %s from %s within camera configuration.\n", recipeName, recipeFile);
+
+        // type mismatch is a serious error
+        if (fileItem->type != PS_DATA_STRING) {
+            psAbort("%s in camera configuration RECIPES is not of type STR", recipeName);
+        }
+
+        // Read the recipe file. if we fail on a file, give a warning, but continue
+        psMetadata *recipe = NULL;
+        if (!pmConfigFileRead(&recipe, recipeFile, "recipe")) {
+            psError(PS_ERR_IO, false, "Failed to read recipe file %s listed in camera configuration\n", recipeFile);
+	    return false;
+        }
+
+        // the named recipe must exist; supplement it
+	psMetadata *current = psMetadataLookupMetadata(NULL, config->recipes, recipeName);
+	if (!current) {
+	    psError(PS_ERR_IO, false, "Failed to find recipe for %s in master recipe list", recipeName);
+	    psFree(recipe);  // Drop reference
+	    return false;
+	}
+
+	if (!psMetadataUpdate(current, recipe)) {
+	    psError(PS_ERR_IO, false, "Failed to update recipe for %s from camera recipe", recipeName);
+	    psFree(recipe);  // Drop reference
+	    return false;
+	}
+        psFree(recipe);  // Drop reference
+    }
+    psFree(recipesIter);
+    config->recipesRead |= PM_RECIPE_SOURCE_CAMERA;
+    *status = true;
     return true;
 }
@@ -343,11 +395,15 @@
 // Load the recipes: each time we load a specific recipe, it overrides the metadata
 // entries for an existing recipe metadata
-static bool loadRecipeFromArguments(pmConfig *config // The configuration into which to read the recipes
-                                   )
-{
+static bool loadRecipeFromArguments(bool *status,
+				    pmConfig *config // The configuration into which to read the recipes
+    )
+{
+    assert(status);
     assert(config);
+    *status = false;
+
     if (!config->arguments) {
         psTrace("psModules.config", 4, "no config->arguments metadata, nothing to read here");
-        return false;
+        return true;
     }
 
@@ -355,5 +411,5 @@
     if (!recipes) {
         psTrace("psModules.config", 4, "no RECIPES in config->arguments, nothing to read here");
-        return false;
+        return true;
     }
 
@@ -371,16 +427,19 @@
 
         // if this named recipe exists, supplement it
-        psMetadata *current = NULL;
-        psMetadataItem *currentItem = psMetadataLookup(config->recipes, item->name);
-        if (currentItem) {
-            assert(currentItem->type == PS_DATA_METADATA);
-            current = psMemIncrRefCounter(currentItem->data.V);
-        }
-        current = psMetadataCopy (current, recipe);
-        psMetadataAdd(config->recipes, PS_LIST_TAIL, item->name, PS_DATA_METADATA | PS_META_REPLACE,
-                      "added from command-line recipe", current);
-        psFree(current);  // Drop reference
+        psMetadata *current = psMetadataLookupMetadata(NULL, config->recipes, item->name);
+        if (!current) {
+	    psError(PS_ERR_IO, false, "Failed to find recipe for %s in master recipe list", item->name);
+	    psFree(recipe);  // Drop reference
+	    return false;
+	}
+	psTrace("psModules.config", 3, "Supplementing %s from arguments.\n", item->name);
+
+        if (!psMetadataUpdate (current, recipe)) {
+	    psError(PS_ERR_IO, false, "Failed to update recipe for %s from camera recipe", item->name);
+	    return false;
+	}
     }
     psFree(recipesIter);
+    *status = true;
     return true;
 }
@@ -388,59 +447,50 @@
 // Load the recipes: each time we load a specific recipe, it overrides the metadata
 // entries for an existing recipe metadata
-static bool loadRecipeSymbols(pmConfig *config // The configuration into which to read the recipes
-                             )
-{
+static bool loadRecipeSymbols(bool *status,
+			      pmConfig *config // The configuration into which to read the recipes
+    )
+{
+    bool found = false;
+
+    assert(status);
     assert(config);
+    *status = false;
 
     // check to see if any symbolic names need to be resolved
-    // each entry in recipeSymbols are of the form NAME=REF where NAME is an existing
+    // each entry in recipeSymbols are of the form TARGET=SOURCE where TARGET is an existing
     // recipe MD and REF is a MD to load over that recipe
-    psMetadataIterator *recipesIter = psMetadataIteratorAlloc(config->recipeSymbols, PS_LIST_HEAD, NULL);
+    psMetadataIterator *iter = psMetadataIteratorAlloc(config->recipeSymbols, PS_LIST_HEAD, NULL);
     psMetadataItem *item = NULL;  // Item containing source, from iteration
-    while ((item = psMetadataGetAndIncrement(recipesIter))) {
+    while ((item = psMetadataGetAndIncrement(iter))) {
         assert(item->type == PS_DATA_STRING); // It should be this type: we put it in ourselves
-        const char *symbolRef = item->data.V; // The name of the symbolic reference
-        const char *symbolName = item->name;
-
-        // search for linkName in config->recipes
-        psMetadataItem *recipeItem = psMetadataLookup(config->recipes, symbolRef);
-        if (recipeItem) {
-            // if this named recipe exists, supplement it
-            assert(recipeItem->type == PS_DATA_METADATA);
-            psMetadata *recipe = recipeItem->data.V;
-            psTrace("psModules.config", 3, "Supplementing %s from %s.\n", symbolName, symbolRef);
-
-            psMetadata *current = NULL;
-            psMetadataItem *currentItem = psMetadataLookup(config->recipes, symbolName);
-            if (currentItem) {
-                assert(currentItem->type == PS_DATA_METADATA);
-                current = psMemIncrRefCounter(currentItem->data.V);
-            }
-
-            current = psMetadataCopy(current, recipe);
-            psMetadataAdd(config->recipes, PS_LIST_TAIL, symbolName, PS_DATA_METADATA | PS_META_REPLACE,
-                          symbolRef, current);
-            psFree(current);  // Drop reference
-            continue;
-        }
-
-        // search for linkName in config->recipes:NAME
-        psMetadata *current = psMetadataLookupMetadata(NULL, config->recipes, symbolName); // The source
-        if (current) {
-            psMetadataItem *recipeItem = psMetadataLookup(current, symbolRef);
-            if (recipeItem) {
-                assert(recipeItem->type == PS_DATA_METADATA);
-                psMetadata *recipe = recipeItem->data.V;
-                psTrace("psModules.config", 3, "Supplementing %s from %s metadata within %s.\n",
-                        symbolName, symbolRef, symbolRef);
-                psMetadataCopy (current, recipe);
-                psMetadataAdd(config->recipes, PS_LIST_TAIL, symbolName, PS_DATA_METADATA | PS_META_REPLACE,
-                              symbolRef, current);
-                continue;
-            }
-        }
-        // symbol is not found: ERROR
-    }
-    psFree(recipesIter);
+        const char *sourceName = item->data.V; // The name of the symbolic reference
+        const char *targetName = item->name;
+	psTrace("psModules.config", 3, "Supplementing %s from %s.\n", targetName, sourceName);
+
+	// the target recipe must exist; select it
+	psMetadata *targetMD = psMetadataLookupMetadata(&found, config->recipes, targetName);
+	if (!targetMD) {
+	    psError(PS_ERR_IO, true, "Failed to find recipe for %s in master recipe list", targetName);
+	    return false;
+	}
+
+        // search for sourceName : it may be in config->recipes or target MD
+        psMetadata *sourceMD = NULL;
+	sourceMD = psMetadataLookupMetadata(&found, config->recipes, sourceName);
+        if (!sourceMD) {
+	    sourceMD = psMetadataLookupMetadata(&found, targetMD, sourceName);
+	    if (!sourceMD) {
+		psError(PS_ERR_IO, false, "Selected symbolic name %s does not exist in recipes", sourceName);
+		return false;
+	    }
+	}
+
+	if (!psMetadataUpdate(targetMD, sourceMD)) {
+	    psError(PS_ERR_IO, false, "Failed to update recipe for %s from camera recipe", targetName);
+	    return false;
+	}
+    }
+    psFree(iter);
+    *status = true;
     return true;
 }
@@ -449,17 +499,22 @@
 // Load the recipes: each time we load a specific recipe, it overrides the metadata
 // entries for an existing recipe metadata
-static bool loadRecipeOptions(pmConfig *config // The configuration into which to read the recipes
-                             )
-{
+static bool loadRecipeOptions(bool *status,
+			      pmConfig *config // The configuration into which to read the recipes
+    )
+{
+    bool found;
+    assert(status);
     assert(config);
+    *status = false;
+
     if (!config->arguments) {
         psTrace("psModules.config", 4, "no config->arguments metadata, nothing to read here");
-        return false;
-    }
-
-    psMetadata *recipes = psMetadataLookupMetadata(NULL, config->arguments, "OPTIONS"); // The list of recipes
+        return true;
+    }
+
+    psMetadata *recipes = psMetadataLookupMetadata(&found, config->arguments, "OPTIONS"); // The list of recipes
     if (!recipes) {
         psTrace("psModules.config", 4, "no OPTIONS in config->arguments, nothing to read here");
-        return false;
+        return true;
     }
 
@@ -468,27 +523,25 @@
     psMetadataItem *item = NULL;    // MD item containing the filename, from recipe iteration
     while ((item = psMetadataGetAndIncrement(recipesIter))) {
+	char *recipeName = item->name;
+        psMetadata *recipe = item->data.V;
+
         // type mismatch is a serious error
         if (item->type != PS_DATA_METADATA) {
-            psAbort("%s in config arguments OPTIONS is not of type METADATA", item->name);
-        }
-        // increment the ref counter to protect the data
-        psMetadata *recipe = psMemIncrRefCounter (item->data.V);
+            psAbort("%s in config arguments OPTIONS is not of type METADATA", recipeName);
+        }
 
         // if this named recipe exists, supplement it
-        psMetadata *current = NULL;
-        psMetadataItem *currentItem = psMetadataLookup(config->recipes, item->name);
-        if (currentItem) {
-            assert(currentItem->type == PS_DATA_METADATA);
-            current = psMemIncrRefCounter(currentItem->data.V);
-        }
-        current = psMetadataCopy (current, recipe);
-        psMetadataAdd(config->recipes, PS_LIST_TAIL, item->name, PS_DATA_METADATA | PS_META_REPLACE,
-                      "supplement command-line arguments", current);
-        psFree(recipe);  // Drop reference
-        psFree(current);  // Drop reference
+        psMetadata *current = psMetadataLookupMetadata(NULL, config->recipes, recipeName);
+        if (!current) {
+	    psError(PS_ERR_IO, false, "Selected recipe %s is not found in camera recipe", recipeName);
+	    return false;
+	}
+        if (!psMetadataUpdate (current, recipe)) {
+	    psError(PS_ERR_IO, false, "Failed to update recipe for %s from camera recipe", recipeName);
+	    return false;
+	}
     }
     psFree(recipesIter);
-    return true;
-}
-
-
+    *status = true;
+    return true;
+}
