Index: trunk/psModules/src/config/pmConfig.c
===================================================================
--- trunk/psModules/src/config/pmConfig.c	(revision 10422)
+++ trunk/psModules/src/config/pmConfig.c	(revision 10428)
@@ -4,6 +4,6 @@
  *  @author EAM (IfA)
  *
- *  @version $Revision: 1.56 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-12-04 02:14:09 $
+ *  @version $Revision: 1.57 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-12-04 20:41:51 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -25,4 +25,5 @@
 #include <pslib.h>
 #include "pmConfig.h"
+#include "pmConfigRecipes.h"
 
 #define PS_SITE "PS_SITE"         // Name of the environment variable containing the site config file
@@ -38,5 +39,5 @@
     psFree(config->cameraName);
     psFree(config->recipes);
-    psFree(config->recipesSource);
+    psFree(config->recipeSymbols);
     psFree(config->arguments);
     psFree(config->database);
@@ -55,5 +56,5 @@
     config->recipes = psMetadataAlloc();
     config->recipesRead = PM_RECIPE_SOURCE_NONE;
-    config->recipesSource = psMetadataAlloc();
+    config->recipeSymbols = psMetadataAlloc();
     config->arguments = psMetadataAlloc();
     config->database = NULL;
@@ -660,181 +661,4 @@
 }
 
-
-// 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
-                        pmRecipeSource sourceType, // The source type
-                        const char *sourceName // The name of the source, for error messages
-                       )
-{
-    assert(config);
-
-    if (!source) {
-        psTrace("psModules.pmConfig", 4, "The %s has not been read --- cannot read recipes from this "
-                "location.\n", sourceName);
-        config->recipesRead &= ~sourceType;
-        return false;
-    }
-
-    bool mdok = true;                   // Status of MD lookup
-    psMetadata *recipes = psMetadataLookupMetadata(&mdok, source, "RECIPES"); // The list of recipes
-    if (!mdok || !recipes) {
-        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.
-    // 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)))
-        {
-            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);
-    }
-    config->recipesRead |= sourceType;
-
-    {
-        // Having read that, we now need to check to see if any symbolic links need to be resolved
-        psMetadataIterator *recipesIter = psMetadataIteratorAlloc(config->recipesSource, PS_LIST_HEAD, NULL);
-        psMetadataItem *sourceItem = NULL;  // Item containing source, from iteration
-        while ((sourceItem = psMetadataGetAndIncrement(recipesIter))) {
-            assert(sourceItem->type == PS_TYPE_S32); // It should be this type: we put it in ourselves
-            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
-                if (!mdok || !linkSource) {
-                    // Can't yet resolve it
-                    continue;
-                }
-                psString comment = NULL;
-                psStringAppend(&comment, "Symbolic link from %s", linkName);
-                psMetadataAdd(config->recipes, PS_LIST_TAIL, sourceItem->name,
-                              PS_DATA_METADATA | PS_META_REPLACE, comment, linkSource);
-                psFree(comment);
-            }
-        }
-        psFree(recipesIter);
-    }
-    return true;
-}
-
-// 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);
-
-    if (!config->recipes) {
-        config->recipes = psMetadataAlloc();
-    }
-
-    // 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
-    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");
-        }
-    }
-    /*
-     * 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;
-}
-
-
 psDB *pmConfigDB(pmConfig *config)
 {
@@ -1057,166 +881,2 @@
     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
-
