Index: /trunk/psModules/src/config/pmConfig.c
===================================================================
--- /trunk/psModules/src/config/pmConfig.c	(revision 10421)
+++ /trunk/psModules/src/config/pmConfig.c	(revision 10422)
@@ -4,6 +4,6 @@
  *  @author EAM (IfA)
  *
- *  @version $Revision: 1.55 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-12-03 18:48:10 $
+ *  @version $Revision: 1.56 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-12-04 02:14:09 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -54,5 +54,5 @@
     config->cameraName = NULL;
     config->recipes = psMetadataAlloc();
-    config->recipesRead = P_PM_RECIPE_SOURCE_NONE;
+    config->recipesRead = PM_RECIPE_SOURCE_NONE;
     config->recipesSource = psMetadataAlloc();
     config->arguments = psMetadataAlloc();
@@ -60,4 +60,5 @@
     config->argc = argc;
     config->argv = argv;
+    config->defaultRecipe = NULL;
     config->workdir = NULL;
 
@@ -205,5 +206,5 @@
 
 
-pmConfig *pmConfigRead(int *argc, char **argv)
+pmConfig *pmConfigRead(int *argc, char **argv, char *defaultRecipe)
 {
     PS_ASSERT_PTR_NON_NULL(argc, NULL);
@@ -212,4 +213,5 @@
 
     pmConfig *config = pmConfigAlloc(argc, argv); // The configuration, containing site, camera and recipes
+    config->defaultRecipe = defaultRecipe;
 
     //
@@ -365,6 +367,6 @@
             // expanded in the future to do files, and perhaps even sockets.
             if (!psTraceSetDestination(psMessageDestination(traceDest))) {
-                psLogMsg(__func__, PS_LOG_WARN, "Unable to set trace destination to %s\n",
-                         config->argv[argNum]);
+                psLogMsg(__func__, PS_LOG_WARN, "Unable to set trace destination to %s\n", traceDest);
+
             }
         }
@@ -442,9 +444,18 @@
 
     // Load the recipes from the camera file, if appropriate
-    if(!pmConfigReadRecipes(config)) {
+    if(!pmConfigReadRecipes(config, PM_RECIPE_SOURCE_SITE | PM_RECIPE_SOURCE_CAMERA)) {
         psError(PS_ERR_IO, false, "Failed to read recipes from camera file");
         psFree(config);
         return NULL;
     }
+
+    // load command-line options of the form -recipe NAME RECIPE
+    pmConfigLoadRecipeArguments (config);
+
+    // read in command-line options to specific recipe values
+    pmConfigLoadRecipeOptions (config, "-D");
+    pmConfigLoadRecipeOptions (config, "-Di");
+    pmConfigLoadRecipeOptions (config, "-Df");
+    pmConfigLoadRecipeOptions (config, "-Db");
 
     psErrorClear();   // we may have failed to find some items in the metadata
@@ -606,5 +617,5 @@
 
         // Now we have the camera, we can read the recipes
-        pmConfigReadRecipes(config);
+        pmConfigReadRecipes(config, PM_RECIPE_SOURCE_CAMERA | PM_RECIPE_SOURCE_CL);
 
         return format;
@@ -650,8 +661,9 @@
 
 
-// Load the recipes
+// Load the recipes: each time we load a specific recipe, it overrides the metadata
+// entries for an existing recipe metadata
 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
+                        pmRecipeSource sourceType, // The source type
                         const char *sourceName // The name of the source, for error messages
                        )
@@ -660,9 +672,6 @@
 
     if (!source) {
-        #if 0
-        psLogMsg(__func__, PS_LOG_WARN, "The %s has not been read --- cannot read recipes from this "
-                 "location.\n", sourceName);
-        #endif
-
+        psTrace("psModules.pmConfig", 4, "The %s has not been read --- cannot read recipes from this "
+                "location.\n", sourceName);
         config->recipesRead &= ~sourceType;
         return false;
@@ -672,9 +681,12 @@
     psMetadata *recipes = psMetadataLookupMetadata(&mdok, source, "RECIPES"); // The list of recipes
     if (!mdok || !recipes) {
-        psLogMsg(__func__, PS_LOG_WARN, "RECIPES in the %s is not of type METADATA --- ignored\n",
+        psLogMsg("psModules.pmConfig", PS_LOG_WARN, "RECIPES in the %s is not of type METADATA --- ignored\n",
                  sourceName);
         config->recipesRead &= ~sourceType;
         return false;
     }
+
+    // for sourceType == SITE | CAMERA, RECIPES contains a list of files to be read (pmConfigFileRead)
+    // for sourceType == CL, RECIPES contains a list of metadata already loaded
 
     // Copy the filenames to the target from the "RECIPES" in the source.
@@ -686,36 +698,60 @@
         while ((fileItem = psMetadataGetAndIncrement(recipesIter)))
         {
-            if (fileItem->type != PS_DATA_STRING) {
-                psLogMsg(__func__, PS_LOG_WARN, "Recipe %s from %s is not of type STR --- ignored.\n",
-                         fileItem->name, sourceName);
-                continue;
-            }
-
-            // 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, (char*)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 (pmConfigFileRead(&recipe, fileItem->data.V, "recipe")) {
-                psMetadataAdd(config->recipes, PS_LIST_TAIL, fileItem->name,
-                              PS_DATA_METADATA | PS_META_REPLACE, fileItem->comment, recipe);
-            } else {
-                psError(PS_ERR_IO, false, "Failed to read recipe");
-
-                psFree(recipe);  // Drop reference
-                psFree(recipesIter);
-
-                return false;
-            }
-            psFree(recipe);                 // Drop reference
+            psMetadata *recipe = NULL;
+            psMetadata *current = NULL;
+
+            switch (sourceType) {
+            case PM_RECIPE_SOURCE_SITE:
+            case PM_RECIPE_SOURCE_CAMERA:
+                // type mismatch is a serious error
+                if (fileItem->type != PS_DATA_STRING) {
+                    psAbort ("pmConfig", "%s in %s RECIPES is not of type STR", fileItem->name, sourceName);
+                }
+
+                // Check to see if it's currently defined
+                // XXX EAM : I think this check is now not needed?
+                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, (char*)fileItem->data.V);
+                psTrace ("psModules.pmConfig", 3, comment);
+                psMetadataAddS32(config->recipesSource, PS_LIST_TAIL, fileItem->name,
+                                 PS_META_REPLACE, comment, sourceType);
+                psFree(comment);
+
+                // Read the recipe file.
+                if (!pmConfigFileRead(&recipe, fileItem->data.V, "recipe")) {
+                    psError(PS_ERR_IO, false, "Failed to read recipe");
+                    psFree(recipe);  // Drop reference
+                    psFree(recipesIter);
+                    return false;
+                }
+                break;
+
+            case PM_RECIPE_SOURCE_CL:
+                // type mismatch is a serious error
+                if (fileItem->type != PS_DATA_METADATA) {
+                    psAbort ("pmConfig", "%s in %s RECIPES is not of type METADATA", fileItem->name, sourceName);
+                }
+                // increment the ref counter to protect the data
+                recipe = psMemIncrRefCounter (fileItem->data.V);
+                break;
+
+            default:
+                psAbort ("pmConfig", "unknown sourceType");
+            }
+
+            // if this named recipe exists, supplement it
+            current = psMetadataLookupMetadata (NULL, config->recipes, fileItem->name);
+            if (current) {
+                psMemIncrRefCounter (current);
+            }
+            current = psMetadataCopy (current, recipe);
+            psMetadataAdd(config->recipes, PS_LIST_TAIL, fileItem->name, PS_DATA_METADATA | PS_META_REPLACE, fileItem->comment, current);
+            psFree(recipe);  // Drop reference
+            psFree(current);  // Drop reference
         }
         psFree(recipesIter);
@@ -729,5 +765,5 @@
         while ((sourceItem = psMetadataGetAndIncrement(recipesIter))) {
             assert(sourceItem->type == PS_TYPE_S32); // It should be this type: we put it in ourselves
-            if (sourceItem->data.S32 == P_PM_RECIPE_SOURCE_SYMBOLIC) {
+            if (sourceItem->data.S32 == PM_RECIPE_SOURCE_SYMBOLIC) {
                 const char *linkName = sourceItem->comment; // The name of the link
                 psMetadata *linkSource = psMetadataLookupMetadata(&mdok, config->recipes, linkName); // The source
@@ -748,6 +784,9 @@
 }
 
-
-bool pmConfigReadRecipes(pmConfig *config)
+// 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
+// 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)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -757,85 +796,34 @@
     }
 
-    bool mdok = true;                   // Status of MD lookup
-
     // Read the recipe file names from the site configuration and camera configuration
-    if (config->site && !(config->recipesRead & P_PM_RECIPE_SOURCE_SITE)) {
-        if(!loadRecipes(config, config->site, P_PM_RECIPE_SOURCE_SITE, "site configuration")) {
-            psError(PS_ERR_IO, false, "Failed to read recipes from site config");
-            #if 0     // see comment at end of routine
-
-            return false;
-            #endif
-
-        }
-    }
-    if (config->camera && !(config->recipesRead & P_PM_RECIPE_SOURCE_CAMERA)) {
-        if (!loadRecipes(config, config->camera, P_PM_RECIPE_SOURCE_CAMERA, "camera configuration")) {
-            psError(PS_ERR_IO, false, "Failed to read recipes from camera config");
-            #if 0     // see comment at end of routine
-
-            return false;
-            #endif
-
-        }
-    }
-
-    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
-
-            // Is the source a symbolic reference?
-            psMetadata *extant = psMetadataLookupMetadata(&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);
-                // Put the source in the comment, so we can retrieve it again if we need it
-                psMetadataAddS32(config->recipesSource, PS_LIST_TAIL, recipeName, PS_META_REPLACE,
-                                 recipeSource, P_PM_RECIPE_SOURCE_SYMBOLIC);
-
-            } else if (access(recipeSource, R_OK) == 0) {
-                // The source is a file
-                psMetadata *recipe = NULL;      // Recipe from file
-                if (pmConfigFileRead(&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
-                    psMetadataAddS32(config->recipesSource, PS_LIST_TAIL, recipeName, PS_META_REPLACE,
-                                     "Recipe added from command line", P_PM_RECIPE_SOURCE_CL);
-                }
-            } else {
-                // Assume it's a symbolic reference to something that's not yet read in
-                psMetadataAddS32(config->recipesSource, PS_LIST_TAIL, recipeName, PS_META_REPLACE,
-                                 recipeSource, P_PM_RECIPE_SOURCE_SYMBOLIC);
-            }
-            psFree(recipeName);
-            psFree(recipeSource);
-        } // Iterating through the command-line arguments
-        config->recipesRead |= P_PM_RECIPE_SOURCE_CL;
+    // XXX EAM : I think it should be an error for config->site:recipes not to exist
+    // for now, keep this as a warning
+    if (config->site && (source & PM_RECIPE_SOURCE_SITE)) {
+        if (!loadRecipes(config, config->site, PM_RECIPE_SOURCE_SITE, "site configuration")) {
+            psLogMsg ("psModules.pmConfig", PS_LOG_WARN, "Failed to read recipes from site config");
+        } else {
+            psTrace ("psModules.pmConfig", 3, "read recipes from site config");
+        }
+    }
+
+    // camera-specific recipes are not required : note the absence with a message
+    // camera-specific recipes may be read for a specified camera (in pmConfigRead) or
+    // for an identified camera (in pmConfigCameraFormatFromHeader).  the second
+    // set should not override the first set
+    if (config->camera && (source & PM_RECIPE_SOURCE_CAMERA) && !(config->recipesRead & PM_RECIPE_SOURCE_CAMERA)) {
+        if (!loadRecipes(config, config->camera, PM_RECIPE_SOURCE_CAMERA, "camera configuration")) {
+            psLogMsg ("psModules.pmConfig", PS_LOG_DETAIL, "no recipe supplied by camera config");
+        } else {
+            psTrace ("psModules.pmConfig", 3, "read recipes from camera config");
+        }
+    }
+
+    // apply recipes loaded into config->arguments based on command-line arguments
+    if (config->arguments && (source & PM_RECIPE_SOURCE_CL)) {
+        if (!loadRecipes(config, config->arguments, PM_RECIPE_SOURCE_CL, "command-line arguments")) {
+            psLogMsg ("psModules.pmConfig", PS_LOG_DETAIL, "no recipe supplied on command-line arguments");
+        } else {
+            psTrace ("psModules.pmConfig", 3, "read recipes from command-line arguments");
+        }
     }
     /*
@@ -1069,2 +1057,166 @@
     return newName;
 }
+
+// search for options of the form -D KEY VALUE or -D RECIPE:KEY VALUE
+bool pmConfigLoadRecipeOptions (pmConfig *config, char *flag)
+{
+
+    int argNum;
+
+    // save the recipes onto config->arguments:RECIPES
+    psMetadata *recipes = psMetadataLookupMetadata(NULL, config->arguments, "RECIPES");
+    if (!recipes) {
+        recipes = psMetadataAlloc ();
+        psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "RECIPES",  PS_DATA_METADATA, "", recipes);
+    } else {
+        psMemIncrRefCounter (recipes); // so we can free options below if not allocated here
+    }
+
+    // -D key value (all added as string)
+    while ((argNum = psArgumentGet (*config->argc, config->argv, flag))) {
+        psArgumentRemove (argNum, config->argc, config->argv);
+
+        // do we have enough arguments?
+        if (argNum + 1 >= *config->argc) {
+            psError(PS_ERR_IO, true, "insufficient parameters for command-line argument -D");
+            return false;
+        }
+
+        // is a target recipe specified?
+        char *recipeName = NULL;
+        char *key;
+        psArray *words = psStringSplitArray(config->argv[argNum], ":", false);
+        switch (words->n) {
+        case 1:
+            recipeName = config->defaultRecipe;
+            if (!config->defaultRecipe) {
+                psError(PS_ERR_IO, true, "syntax error in parameter: no default recipe available; must specify recipe");
+                return false;
+            }
+            key = words->data[0];
+            break;
+        case 2:
+            recipeName = words->data[0];
+            key = words->data[1];
+            break;
+        default:
+            psError(PS_ERR_IO, true, "syntax error in parameter");
+            return false;
+        }
+
+        // if this recipe is already defined in recipes, supplement
+        psMetadata *recipe = psMetadataLookupMetadata(NULL, recipes, recipeName);
+        if (!recipe) {
+            recipe = psMetadataAlloc ();
+            psMetadataAddPtr (recipes, PS_LIST_TAIL, recipeName,  PS_DATA_METADATA, "", recipe);
+        } else {
+            psMemIncrRefCounter (recipe); // so we can free recipe below if not allocated here
+        }
+
+        bool valid = false;
+        if (!strcmp (flag, "-D")) {
+            psMetadataAddStr (recipe, PS_LIST_TAIL, key, PS_META_REPLACE, "", config->argv[argNum+1]);
+            valid = true;
+        }
+        if (!strcmp (flag, "-Di")) {
+            psMetadataAddS32 (recipe, PS_LIST_TAIL, key, PS_META_REPLACE, "", atoi(config->argv[argNum+1]));
+            valid = true;
+        }
+        if (!strcmp (flag, "-Df")) {
+            psMetadataAddF32 (recipe, PS_LIST_TAIL, key, PS_META_REPLACE, "", atof(config->argv[argNum+1]));
+            valid = true;
+        }
+        if (!strcmp (flag, "-Db")) {
+            if (!strcasecmp (config->argv[argNum+1], "true")) {
+                psMetadataAddBool (recipe, PS_LIST_TAIL, key, PS_META_REPLACE, "", true);
+            } else {
+                psMetadataAddBool (recipe, PS_LIST_TAIL, key, PS_META_REPLACE, "", false);
+            }
+            valid = true;
+        }
+        psFree (words);
+        psFree (recipe);
+        assert (valid);  // flag may be: -D, -Df, -Di, -Db
+
+        psArgumentRemove (argNum, config->argc, config->argv);
+        psArgumentRemove (argNum, config->argc, config->argv);
+    }
+    psFree (recipes);
+    return true;
+}
+
+// examine command-line arguments for -recipe KEY VALUE
+// if VALUE is an existing file, read as metadata and save on config->arguments with name = KEY
+// if VALUE is not an exiting file, it is a symbolic lookup.  ???
+bool pmConfigLoadRecipeArguments (pmConfig *config)
+{
+
+    // 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) {
+            psError(PS_ERR_IO, false, "-recipe command-line switch provided without the required recipe and source\n");
+            return false;
+        }
+
+        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);
+
+        if (access(recipeSource, R_OK) == 0) {
+            // The source is a file: load onto config->arguments
+            // save the recipes onto config->arguments:RECIPES
+            psMetadata *recipes = psMetadataLookupMetadata(NULL, config->arguments, "RECIPES");
+            if (!recipes) {
+                recipes = psMetadataAlloc ();
+                psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "RECIPES",  PS_DATA_METADATA, "", recipes);
+            } else {
+                psMemIncrRefCounter (recipes); // so we can free options below if not allocated here
+            }
+
+            psMetadata *recipe = NULL;      // Recipe from file
+            if (pmConfigFileRead(&recipe, recipeSource, "recipe")) {
+                psString comment = psStringCopy("Recipe added at command line from ");
+                psStringAppend(&comment, "%s", recipeSource);
+                psMetadataAdd(recipes, PS_LIST_TAIL, recipeName, PS_DATA_METADATA | PS_META_REPLACE, comment, recipe);
+                psFree(comment);
+                psFree(recipe);                 // Drop reference
+            } else {
+                psAbort ("pmConfig.c", "error reading config file %s\n", recipeSource);
+            }
+            psFree (recipes);
+        } else {
+            // Assume it's a symbolic reference to something that's not yet read in
+            psMetadataAddS32(config->recipesSource, PS_LIST_TAIL, recipeName, PS_META_REPLACE,
+                             recipeSource, PM_RECIPE_SOURCE_SYMBOLIC);
+        }
+        psTrace ("psModules.pmConfig", 3, "read recipe %s from %s", recipeName, recipeSource);
+        psFree(recipeName);
+        psFree(recipeSource);
+    } // Iterating through the command-line arguments
+
+    return true;
+}
+
+# if (0)
+
+    // Is the source a symbolic reference?
+    // XXX EAM : need to be careful about hierachy and overrides
+    psMetadata *extant = psMetadataLookupMetadata(&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);
+    // Put the source in the comment, so we can retrieve it again if we need it
+    psMetadataAddS32(config->recipesSource, PS_LIST_TAIL, recipeName, PS_META_REPLACE,
+                     recipeSource, PM_RECIPE_SOURCE_SYMBOLIC);
+
+} else
+
+    # endif
+
Index: /trunk/psModules/src/config/pmConfig.h
===================================================================
--- /trunk/psModules/src/config/pmConfig.h	(revision 10421)
+++ /trunk/psModules/src/config/pmConfig.h	(revision 10422)
@@ -9,6 +9,6 @@
 /// @author Eugene Magnier, IfA
 ///
-/// @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
-/// @date $Date: 2006-12-03 18:48:10 $
+/// @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+/// @date $Date: 2006-12-04 02:14:09 $
 ///
 /// Copyright 2005-2006 Institute for Astronomy, University of Hawaii
@@ -28,11 +28,11 @@
 /// psModules --- there is no need for the user to know about it.
 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_SYMBOLIC    = 0x14, ///< Symbolic link, specified on command-line
-    P_PM_RECIPE_SOURCE_ALL         = 0xff  ///< All sources
-} p_pmRecipeSource;
+    PM_RECIPE_SOURCE_NONE        = 0x00, ///< None yet
+    PM_RECIPE_SOURCE_SITE        = 0x01, ///< Site configuration
+    PM_RECIPE_SOURCE_CAMERA      = 0x02, ///< Camera configuration
+    PM_RECIPE_SOURCE_CL          = 0x04, ///< Command-line
+    PM_RECIPE_SOURCE_SYMBOLIC    = 0x14, ///< Symbolic link, specified on command-line
+    PM_RECIPE_SOURCE_ALL         = 0xff  ///< All sources
+} pmRecipeSource;
 
 /// Configuration information
@@ -52,6 +52,7 @@
     int *argc;                          ///< Number of command-line arguments
     char **argv;                        ///< Command-line arguments (raw version)
+    char *defaultRecipe;  ///< name of top-level recipe for this program
     // Private members
-    p_pmRecipeSource recipesRead;       ///< Which recipe sources have been read
+    pmRecipeSource recipesRead;       ///< Which recipe sources have been read
     psMetadata *recipesSource;          ///< Where each recipe came from
 }
@@ -81,5 +82,6 @@
 /// psLib log, trace and time setups are also performed if specified in the site configuration.
 pmConfig *pmConfigRead(int *argc,       ///< Number of command-line arguments
-                       char **argv      ///< Array of command-line arguments
+                       char **argv, ///< Array of command-line arguments
+                       char *defaultRecipe ///< name of top-level recipe for this program
                       );
 
@@ -122,5 +124,6 @@
 /// Attempt to read recipes from the sources that are available but have not already been read.  Having read a
 /// recipe, attempt to resolve symbolic links that were specified on the command line.
-bool pmConfigReadRecipes(pmConfig *config ///< Configuration
+bool pmConfigReadRecipes(pmConfig *config, ///< Configuration
+                         pmRecipeSource source ///< desired sources for recipes
                         );
 
@@ -164,3 +167,7 @@
 psString pmConfigConvertFilename (char *filename, pmConfig *config);
 
+
+bool pmConfigLoadRecipeArguments (pmConfig *config);
+bool pmConfigLoadRecipeOptions (pmConfig *config, char *flag);
+
 #endif
