Index: /trunk/psModules/src/config/pmConfig.c
===================================================================
--- /trunk/psModules/src/config/pmConfig.c	(revision 7708)
+++ /trunk/psModules/src/config/pmConfig.c	(revision 7709)
@@ -3,6 +3,6 @@
  *  @author PAP, IfA
  *
- *  @version $Revision: 1.27 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-06-24 03:25:14 $
+ *  @version $Revision: 1.28 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-28 00:49:13 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -31,4 +31,5 @@
     psFree(config->camera);
     psFree(config->recipes);
+    psFree(config->recipesSource);
     psFree(config->arguments);
     psFree(config->database);
@@ -43,5 +44,7 @@
     config->site = NULL;
     config->camera = NULL;
-    config->recipes = NULL;
+    config->recipes = psMetadataAlloc();
+    config->recipesRead = P_PM_RECIPE_SOURCE_NONE;
+    config->recipesSource = psMetadataAlloc();
     config->arguments = NULL;
     config->database = NULL;
@@ -284,8 +287,5 @@
 
     // Load the recipes from the camera file, if appropriate
-    if (! config->recipes && config->camera) {
-        pmConfigReadRecipes(config);
-    }
-
+    pmConfigReadRecipes(config);
 
     //
@@ -554,7 +554,5 @@
 
         // Now we have the camera, we can read the recipes
-        if (!config->recipes) {
-            pmConfigReadRecipes(config);
-        }
+        pmConfigReadRecipes(config);
 
         return format;
@@ -562,5 +560,5 @@
 
     // Otherwise, try the specific camera
-    if (! formatFromHeader(&format, config->camera, header, "specified 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");
@@ -604,15 +602,20 @@
 
 
-// Read the recipe filenames
-static bool recipeFileNames(psMetadata *target, // The target metadata into which to read the recipes
-                            psMetadata *source, // The source configuration, from which to read the filenames
-                            const char *sourceName // The name of the source, for error messages
-                           )
-{
-    assert(target);
+// Load the recipes
+static bool loadRecipes(pmConfig *config, // The configuration into which to read the recipes
+                        psMetadata *source, // The source configuration, from which to read the filenames
+                        p_pmRecipeSource sourceType, // The source type
+                        const char *sourceName // The name of the source, for error messages
+                       )
+{
+    assert(config);
 
     if (!source) {
+        #if 0
         psLogMsg(__func__, PS_LOG_WARN, "The %s has not been read --- cannot read recipes from this "
                  "location.\n", sourceName);
+        #endif
+
+        config->recipesRead &= ~sourceType;
         return false;
     }
@@ -623,4 +626,5 @@
         psLogMsg(__func__, PS_LOG_WARN, "RECIPES in the %s is not of type METADATA --- ignored\n",
                  sourceName);
+        config->recipesRead &= ~sourceType;
         return false;
     }
@@ -637,7 +641,28 @@
             continue;
         }
-        psMetadataAddItem(target, fileItem, PS_LIST_TAIL, PS_META_REPLACE);
+
+        // Check to see if it's currently defined
+        int check = psMetadataLookupS32(&mdok, config->recipesSource, fileItem->name);
+        if (mdok && check > sourceType) {
+            // It's already defined with a higher priority
+            continue;
+        }
+        psString comment = psStringCopy("Recipe added at ");
+        psStringAppend(&comment, "%s from %s", sourceName, fileItem->data.V);
+        psMetadataAddS32(config->recipesSource, PS_LIST_TAIL, fileItem->name,
+                         PS_META_REPLACE, comment, sourceType);
+        psFree(comment);
+
+        // Read the recipe
+        psMetadata *recipe = NULL;      // Recipe from file
+        if (readConfig(&recipe, fileItem->data.V, "recipe")) {
+            psMetadataAdd(config->recipes, PS_LIST_TAIL, fileItem->name,
+                          PS_DATA_METADATA | PS_META_REPLACE, fileItem->comment, recipe);
+        }
+        psFree(recipe);                 // Drop reference
     }
     psFree(recipesIter);
+
+    config->recipesRead |= sourceType;
 
     return true;
@@ -657,56 +682,59 @@
 
     // Read the recipe file names from the site configuration and camera configuration
-    recipeFileNames(config->recipes, config->site, "site configuration");
-    recipeFileNames(config->recipes, config->camera, "camera configuration");
-
-    // Go through the command-line arguments
-    int argNum; // Argument number for "-recipe"
-    while ((argNum = psArgumentGet(config->argc, config->argv, "-recipe")) > 0) {
-        psArgumentRemove(argNum, &config->argc, config->argv);
-        if (argNum + 1 >= config->argc) {
-            psLogMsg(__func__, PS_LOG_WARN, "-recipe command-line switch provided without the "
-                     "required recipe and source --- ignored.\n");
-            if (argNum == config->argc) {
-                // Remove the single last argument (we required two, they gave us one)
-                psArgumentRemove(argNum, &config->argc, config->argv);
-            }
-            continue;
-        }
-
-        const 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
-        psArgumentRemove(argNum, &config->argc, config->argv);
-
-        // Is the source a symbolic reference?
-        const char *recipeFile = psMetadataLookupStr(&mdok, config->recipes, recipeSource);
-        if (mdok && recipeFile && strlen(recipeFile) > 0) {
-            psString comment = psStringCopy("Recipe added from command line as symbolic link to ");
-            psStringAppend(&comment, "%s", recipeSource);
-            psMetadataAddStr(config->recipes, PS_LIST_TAIL, recipeName, PS_META_REPLACE, comment, recipeFile);
-        } else {
-            // Otherwise, treat the source as a filename
-            psMetadataAddStr(config->recipes, PS_LIST_TAIL, recipeName, PS_META_REPLACE,
-                             "Recipe added from command line", recipeSource);
-        }
-    }
-
-    // Read the recipes
-    psMetadataIterator *recipesIter = psMetadataIteratorAlloc(config->recipes, PS_LIST_HEAD, NULL);// Iterator
-    psMetadataItem *recipesItem = NULL; // Item from iteration
-    while ((recipesItem = psMetadataGetAndIncrement(recipesIter))) {
-        if (recipesItem->type != PS_DATA_STRING) {
-            psLogMsg(__func__, PS_LOG_WARN, "Filename for recipe %s isn't of type STR --- ignored.\n",
-                     recipesItem->name);
-            continue;
-        }
-        psMetadata *recipe = NULL;      // Recipe from file
-        if (readConfig(&recipe, recipesItem->data.V, "recipe")) {
-            psMetadataAdd(config->recipes, PS_LIST_TAIL, recipesItem->name,
-                          PS_DATA_METADATA | PS_META_REPLACE, recipesItem->comment, recipe);
-        }
-        psFree(recipe);                 // Drop reference
-    }
-    psFree(recipesIter);
+    if (!(config->recipesRead & P_PM_RECIPE_SOURCE_SITE)) {
+        loadRecipes(config, config->site, P_PM_RECIPE_SOURCE_SITE, "site configuration");
+    }
+    if (!(config->recipesRead & P_PM_RECIPE_SOURCE_CAMERA)) {
+        loadRecipes(config, config->camera, P_PM_RECIPE_SOURCE_CAMERA, "camera configuration");
+    }
+    if (!(config->recipesRead & P_PM_RECIPE_SOURCE_CL)) {
+        // Go through the command-line arguments
+        int argNum; // Argument number for "-recipe"
+        while ((argNum = psArgumentGet(config->argc, config->argv, "-recipe")) > 0) {
+            psArgumentRemove(argNum, &config->argc, config->argv);
+            if (argNum + 1 >= config->argc) {
+                psLogMsg(__func__, PS_LOG_WARN, "-recipe command-line switch provided without the "
+                         "required recipe and source --- ignored.\n");
+                if (argNum == config->argc) {
+                    // Remove the single last argument (we required two, they gave us one)
+                    psArgumentRemove(argNum, &config->argc, config->argv);
+                }
+                continue;
+            }
+
+            const 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
+            psArgumentRemove(argNum, &config->argc, config->argv);
+
+            // Command-line has the highest priority, so we don't have to check to see if it's already there
+            psMetadataAddS32(config->recipesSource, PS_LIST_TAIL, recipeName, PS_META_REPLACE,
+                             "Recipe added from command line", P_PM_RECIPE_SOURCE_CL);
+
+            // Is the source a symbolic reference?
+            psMetadata *extant = psMetadataLookupMD(&mdok, config->recipes, recipeSource); // Does it exist?
+            if (mdok && extant) {
+                psString comment = psStringCopy("Recipe added from command line as symbolic link to ");
+                psStringAppend(&comment, "%s", recipeSource);
+                psMetadataAdd(config->recipes, PS_LIST_TAIL, recipeName, PS_DATA_METADATA | PS_META_REPLACE,
+                              comment, extant);
+                psFree(comment);
+            } else {
+                // Otherwise, treat the source as a filename
+                psMetadata *recipe = NULL;      // Recipe from file
+                if (readConfig(&recipe, recipeSource, "recipe")) {
+                    psString comment = psStringCopy("Recipe added at command line from ");
+                    psStringAppend(&comment, "%s", recipeSource);
+                    psMetadataAdd(config->recipes, PS_LIST_TAIL, recipeName,
+                                  PS_DATA_METADATA | PS_META_REPLACE, comment, recipe);
+                    psFree(comment);
+                    psFree(recipe);                 // Drop reference
+                }
+            }
+            psFree(recipeName);
+            psFree(recipeSource);
+        } // Iterating through the command-line arguments
+        config->recipesRead |= P_PM_RECIPE_SOURCE_CL;
+    }
 
     return true;
Index: /trunk/psModules/src/config/pmConfig.h
===================================================================
--- /trunk/psModules/src/config/pmConfig.h	(revision 7708)
+++ /trunk/psModules/src/config/pmConfig.h	(revision 7709)
@@ -3,6 +3,6 @@
  *  @author PAP, IfA
  *
- *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-06-24 03:25:14 $
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-28 00:49:13 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -13,4 +13,13 @@
 
 #include "pslib.h"
+
+// What recipe sources have been read so far?
+typedef enum {
+    P_PM_RECIPE_SOURCE_NONE   = 0x00,   // None yet
+    P_PM_RECIPE_SOURCE_SITE   = 0x01,   // Site configuration
+    P_PM_RECIPE_SOURCE_CAMERA = 0x02,   // Camera configuration
+    P_PM_RECIPE_SOURCE_CL     = 0x04,   // Command-line
+    P_PM_RECIPE_SOURCE_ALL    = 0x07    // All sources
+} p_pmRecipeSource;
 
 // Configuration information
@@ -25,4 +34,7 @@
     int argc;                           // Number of command-line arguments
     char **argv;                        // Command-line arguments (raw version)
+    // Private members
+    p_pmRecipeSource recipesRead;       // Which recipe sources have been read
+    psMetadata *recipesSource;          // Where each recipe came from
 }
 pmConfig;
