uves_parameters.c

00001 /*                                                                              *
00002  *   This file is part of the ESO UVES Pipeline                                 *
00003  *   Copyright (C) 2004,2005 European Southern Observatory                      *
00004  *                                                                              *
00005  *   This library is free software; you can redistribute it and/or modify       *
00006  *   it under the terms of the GNU General Public License as published by       *
00007  *   the Free Software Foundation; either version 2 of the License, or          *
00008  *   (at your option) any later version.                                        *
00009  *                                                                              *
00010  *   This program is distributed in the hope that it will be useful,            *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00013  *   GNU General Public License for more details.                               *
00014  *                                                                              *
00015  *   You should have received a copy of the GNU General Public License          *
00016  *   along with this program; if not, write to the Free Software                *
00017  *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA       *
00018  *                                                                              */
00019 
00020 /*
00021  * $Author: jmlarsen $
00022  * $Date: 2007/06/14 11:12:00 $
00023  * $Revision: 1.38 $
00024  * $Name: uves-3_3_1 $
00025  * $Log: uves_parameters.c,v $
00026  * Revision 1.38  2007/06/14 11:12:00  jmlarsen
00027  * Expanded description of plotter parameter
00028  *
00029  * Revision 1.37  2007/06/06 08:17:33  amodigli
00030  * replace tab with 4 spaces
00031  *
00032  * Revision 1.36  2007/05/22 11:37:49  jmlarsen
00033  * Removed image plotting functionality
00034  *
00035  * Revision 1.35  2007/03/05 10:17:30  jmlarsen
00036  * Disabled strange msginfolevel parameter
00037  *
00038  * Revision 1.34  2007/02/09 13:39:31  jmlarsen
00039  * Use defines for recipe id
00040  *
00041  * Revision 1.33  2007/02/09 08:58:18  jmlarsen
00042  * Use define's rather than hard-coded recipe names
00043  *
00044  * Revision 1.32  2007/01/15 08:46:45  jmlarsen
00045  * Shortened lines
00046  *
00047  * Revision 1.31  2006/11/15 15:02:14  jmlarsen
00048  * Implemented const safe workarounds for CPL functions
00049  *
00050  * Revision 1.29  2006/11/15 14:04:08  jmlarsen
00051  * Removed non-const version of parameterlist_get_first/last/next which is
00052  * already in CPL, added const-safe wrapper, unwrapper and deallocator functions
00053  *
00054  * Revision 1.28  2006/11/13 14:23:55  jmlarsen
00055  * Removed workarounds for CPL const bugs
00056  *
00057  * Revision 1.27  2006/11/06 15:19:41  jmlarsen
00058  * Removed unused include directives
00059  *
00060  * Revision 1.26  2006/09/27 15:08:45  jmlarsen
00061  * Fixed doc. bug
00062  *
00063  * Revision 1.25  2006/09/20 12:53:57  jmlarsen
00064  * Replaced stringcat functions with uves_sprintf()
00065  *
00066  * Revision 1.24  2006/09/01 13:57:42  jmlarsen
00067  * Fixed bug that causing parameter class to change during propagation
00068  *
00069  * Revision 1.23  2006/08/18 07:07:43  jmlarsen
00070  * Switched order of cpl_calloc arguments
00071  *
00072  * Revision 1.22  2006/08/17 13:56:53  jmlarsen
00073  * Reduced max line length
00074  *
00075  * Revision 1.21  2006/08/14 15:21:08  jmlarsen
00076  * Update to CPL3
00077  *
00078  * Revision 1.20  2006/08/11 11:29:26  jmlarsen
00079  * Added explicit void at function definition
00080  *
00081  * Revision 1.19  2006/08/07 11:35:35  jmlarsen
00082  * Disabled parameter environment variable mode
00083  *
00084  * Revision 1.18  2006/07/03 13:17:12  jmlarsen
00085  * Changed order of global parameters
00086  *
00087  * Revision 1.17  2006/06/06 08:40:10  jmlarsen
00088  * Shortened max line length
00089  *
00090  * Revision 1.16  2006/06/01 14:43:17  jmlarsen
00091  * Added missing documentation
00092  *
00093  * Revision 1.15  2005/12/19 16:17:56  jmlarsen
00094  * Replaced bool -> int
00095  *
00096  */
00097 
00098 #ifdef HAVE_CONFIG_H
00099 #  include <config.h>
00100 #endif
00101 
00102 /*----------------------------------------------------------------------------*/
00110 /*----------------------------------------------------------------------------*/
00111 
00112 /*-----------------------------------------------------------------------------
00113                                 Includes
00114  -----------------------------------------------------------------------------*/
00115 
00116 #include <uves_parameters.h>
00117 #include <uves_dump.h>
00118 #include <uves_backsub.h>
00119 #include <uves_extract.h>
00120 #include <uves_rebin.h>
00121 #include <uves_reduce.h>
00122 #include <uves_utils_wrappers.h>
00123 #include <uves.h>
00124 #include <uves_error.h>
00125 #include <uves_msg.h>
00126 
00127 #include <irplib_access.h>
00128 
00129 #include <cpl.h>
00130 
00131 /*-----------------------------------------------------------------------------
00132                             Functions prototypes
00133  -----------------------------------------------------------------------------*/
00134 static int propagate(const char *substep_id, const cpl_parameterlist *sub_parameters, 
00135              cpl_parameterlist *parent_parameters,
00136              const char *parent_id, const char *context);
00137 static cpl_parameter *
00138 create_parameter_enum_int   (const char *name, cpl_type type,
00139                  const char *description, const char *context, 
00140                  int default_value, int size, int *values);
00141 static cpl_parameter *
00142 create_parameter_enum_double(const char *name, cpl_type type, const char *description,
00143                  const char *context, double default_value, 
00144                  int size, double *values);
00145 static cpl_parameter *
00146 create_parameter_enum_string(const char *name, cpl_type type, const char *description,
00147                  const char *context, const char *default_value, 
00148                  int size, const char **values);
00149 /*-----------------------------------------------------------------------------
00150                             Defines
00151  -----------------------------------------------------------------------------*/
00152 #define FAIL(return_code, error_code, ...) do {       \
00153         cpl_msg_error(__func__, __VA_ARGS__);         \
00154         if (cpl_error_get_code() == CPL_ERROR_NONE) { \
00155           cpl_error_set(__func__, error_code);        \
00156         }                                             \
00157         return return_code;                           \
00158         } while(false)
00159 
00162 /*-----------------------------------------------------------------------------
00163                             Implementation
00164  -----------------------------------------------------------------------------*/
00165 /*----------------------------------------------------------------------------*/
00174 /*----------------------------------------------------------------------------*/
00175 cpl_error_code
00176 uves_define_global_parameters(cpl_parameterlist *parlist)
00177 {
00178     const char *context = "uves";
00179     const char *name = "";
00180     char *full_name = NULL;
00181     cpl_parameter *p;
00182 
00183     {
00184     name = "debug";
00185     full_name = uves_sprintf("%s.%s", context, name);
00186     uves_parameter_new_value(p, full_name,
00187                     CPL_TYPE_BOOL,
00188                     "Whether or not to save intermediate "
00189                     "results to local directory",
00190                     context,
00191                     false);
00192     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00193     cpl_parameterlist_append(parlist, p);
00194     cpl_free(full_name);
00195     }
00196 
00197 
00198     {
00199         name = "plotter";
00200         full_name = uves_sprintf("%s.%s", context, name);
00201         uves_parameter_new_value(
00202             p, full_name,
00203             CPL_TYPE_STRING,
00204             "Any plots produced by the recipe "
00205             "are redirected to the command specified "
00206             "by this parameter. The plotting command "
00207             "must contain the substring 'gnuplot' and "
00208             "must be able to parse gnuplot syntax on its "
00209             "standard input. "
00210             "Valid examples of such a command may include "
00211             "'gnuplot -persist' and 'cat > mygnuplot$$.gp'. "
00212             "A finer control of the plotting options can "
00213             "be obtained by writing an "
00214             "executable script, e.g. my_gnuplot.pl, that "
00215             "executes gnuplot after setting the desired gnuplot "
00216             "options (e.g. set terminal pslatex color). "
00217             "To turn off plotting, set this parameter to 'no'",
00218             context,
00219             "no");
00220 
00221         cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00222         cpl_parameterlist_append(parlist, p);
00223         cpl_free(full_name);
00224     }
00225 
00226     if (0)
00227         /* The meaning of this parameter often escapes the developers,
00228            so let's not expose it to the users */
00229         {
00230         name = "msginfolevel";
00231     full_name = uves_sprintf("%s.%s", context, name);
00232     uves_parameter_new_range(p, full_name,
00233                     CPL_TYPE_INT,
00234                     "This parameter controls the subdivision "
00235                     "of the 'info' message level (set e.g. with "
00236                     "esorex' --msg-level). The higher the value "
00237                     "of this parameter, the more messages are "
00238                     "printed at the info level. For minimum "
00239                     "output, set to zero. Increase the level "
00240                     "(to 1, 2, 3, ...) for more output. The "
00241                     "value -1 is a special value meaning maximum "
00242                     "output",
00243                     context,
00244                     -1,                 /* Default */
00245                     -1, INT_MAX);       /* Range   */
00246     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00247     cpl_parameterlist_append(parlist, p);
00248     cpl_free(full_name);
00249     }
00250 
00251     if (cpl_error_get_code() != CPL_ERROR_NONE)
00252     {
00253         cpl_msg_error(__func__, "Creation of global parameters failed: '%s'",
00254               cpl_error_get_where());
00255     }
00256     
00257     return cpl_error_get_code();
00258 }
00259 
00260 
00261 
00262 
00263 
00264 /*----------------------------------------------------------------------------*/
00279 /*----------------------------------------------------------------------------*/
00280 
00281 int
00282 uves_invoke_recipe(const char *recipe_id, const cpl_parameterlist *parameters, 
00283            cpl_frameset *frames,
00284            const char *caller_id, const char *context)
00285 {
00286     cpl_pluginlist *list  = NULL;
00287     cpl_plugin *plugin    = NULL;
00288     cpl_recipe *recipe    = NULL;
00289 
00290     cpl_parameter *p      = NULL;
00291     char *parent_name     = NULL;
00292     char *sub_domain      = NULL;
00293     const char *recipe_domain = "";
00294     int status = 0;
00295 
00296     bool must_destroy_plugin = false;   /* Indicates if recipe_create() 
00297                        has been called */
00298 
00299     /* Check input */
00300     assure(recipe_id != NULL, CPL_ERROR_NULL_INPUT, "Null recipe name");
00301     assure(parameters != NULL, CPL_ERROR_NULL_INPUT, "Null parameter list");
00302     assure(frames != NULL, CPL_ERROR_NULL_INPUT, "Null frame set");
00303     assure(caller_id != NULL, CPL_ERROR_NULL_INPUT, "Null caller recipe name");
00304     /* 'context' may be NULL */    
00305 
00306     /* Get the sub-recipe plugin */
00307     check( list = cpl_pluginlist_new(),
00308        "Error allocating plugin list");
00309 
00310     /* Get info about recipe */
00311     if      (strcmp(recipe_id, make_str(UVES_PHYSMOD_ID) ) == 0)
00312     { recipe_domain = UVES_PHYSMOD_DOM;  status = uves_physmod_get_info(list);  }
00313     else if (strcmp(recipe_id, make_str(UVES_ORDERPOS_ID)) == 0)
00314     { recipe_domain = UVES_ORDERPOS_DOM; status = uves_orderpos_get_info(list); }
00315     else if (strcmp(recipe_id, make_str(UVES_MBIAS_ID)   ) == 0)
00316     { recipe_domain = UVES_MBIAS_DOM;    status = uves_mbias_get_info(list);    }
00317     else if (strcmp(recipe_id, make_str(UVES_MDARK_ID)   ) == 0)
00318     { recipe_domain = UVES_MDARK_DOM;    status = uves_mdark_get_info(list);    }
00319     else if (strcmp(recipe_id, make_str(UVES_MFLAT_ID)   ) == 0)
00320     { recipe_domain = UVES_MFLAT_DOM;    status = uves_mflat_get_info(list);    }
00321     else if (strcmp(recipe_id, make_str(UVES_WAVECAL_ID) ) == 0)
00322     { recipe_domain = UVES_WAVECAL_DOM;  status = uves_wavecal_get_info(list);  }
00323     else if (strcmp(recipe_id, make_str(UVES_RESPONSE_ID)) == 0)
00324     { recipe_domain = UVES_RESPONSE_DOM; status = uves_response_get_info(list); }
00325     else if (strcmp(recipe_id, make_str(UVES_SCIRED_ID)  ) == 0)
00326     { recipe_domain = UVES_SCIRED_DOM;   status = uves_scired_get_info(list);   }
00327     else if (strcmp(recipe_id, make_str(UVES_REDCHAIN_ID)) == 0)
00328     { recipe_domain = UVES_REDCHAIN_DOM; status = uves_redchain_get_info(list); }
00329     else
00330     {
00331         assure( false, CPL_ERROR_ILLEGAL_INPUT, "Unknown recipe: '%s'", recipe_id);
00332     }
00333 
00334     assure( status == 0, CPL_ERROR_ILLEGAL_INPUT, 
00335         "Could not get info about recipe '%s'", recipe_id);
00336 
00337     /* Get default parameter list */
00338     check( plugin = cpl_pluginlist_get_first(list), "Error getting plugin");
00339     assure( plugin != NULL, CPL_ERROR_ILLEGAL_INPUT,
00340         "Plugin '%s' returned empty plugin list", recipe_id);
00341     assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE, 
00342         CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");
00343     recipe = (cpl_recipe *) plugin;
00344     
00345     /* Call initializer function */
00346     must_destroy_plugin = true;
00347     assure( cpl_plugin_get_init(plugin)(plugin) == 0, CPL_ERROR_ILLEGAL_INPUT,
00348         "Error initializing recipe");
00349     assure( recipe->parameters != NULL, CPL_ERROR_ILLEGAL_INPUT,
00350         "Recipe '%s' returned NULL parameter list", recipe_id);
00351 
00352     /* For each recipe parameter x:
00353        Set to value of C.x (from argument parameter list)
00354 
00355        Parameters in 'uves' context are simply overwritten
00356     */
00357     for (p = cpl_parameterlist_get_first(recipe->parameters); 
00358      p != NULL;
00359      p = cpl_parameterlist_get_next(recipe->parameters) )
00360     {
00361         const char *name          = cpl_parameter_get_name(p);   
00362         const char *subcontext    = cpl_parameter_get_context(p);
00363         cpl_type type             = cpl_parameter_get_type(p);
00364         
00365         const cpl_parameter *parent;
00366         
00367         if (strcmp(subcontext, "uves") == 0)
00368         {
00369             parent_name = uves_sprintf("%s", name);
00370         }
00371         else
00372         {
00373             if (context != NULL)
00374             {
00375                 parent_name = uves_sprintf("%s.%s.%s", caller_id, context, name);
00376             }
00377             else
00378             {
00379                 parent_name = uves_sprintf("%s.%s", caller_id, name);
00380             }
00381         }
00382         
00383         /* Const cast, we don't change the parameter list, parent is declared const */
00384         check( parent = irplib_parameterlist_find_const(parameters, parent_name),
00385            "Could not get parameter '%s' from provided parameter list", parent_name);
00386         
00387         assure( parent != NULL, CPL_ERROR_DATA_NOT_FOUND,
00388             "Missing parameter '%s' needed to define '%s' in context '%s'",
00389             parent_name, name, context);
00390         
00391         assure( cpl_parameter_get_type(parent) == type, CPL_ERROR_TYPE_MISMATCH,
00392             "Parameter '%s' type is %s. Type %s needed for recipe parameter '%s'",
00393             parent_name, 
00394             uves_tostring_cpl_type(cpl_parameter_get_type(parent)),
00395             uves_tostring_cpl_type(type),
00396             name);
00397             
00398         switch (type)
00399         {
00400             int value_int;  
00401             bool value_bool;
00402             double value_double;
00403             const char *value_string;
00404 
00405         case CPL_TYPE_BOOL:
00406             check( value_bool = cpl_parameter_get_bool(parent), 
00407                "Error reading parameter '%s'", parent_name);
00408         
00409             check( cpl_parameter_set_bool(p, value_bool),
00410                "Error setting parameter '%s'", name);
00411             
00412             uves_msg_debug("Setting parameter '%s' <- '%s' = %s",
00413                    name, parent_name, (value_bool) ? "true" : "false");
00414             break;
00415 
00416         case CPL_TYPE_INT:
00417             check( value_int = cpl_parameter_get_int(parent),
00418                "Error reading parameter '%s'", parent_name);
00419         
00420             check( cpl_parameter_set_int(p, value_int),
00421                "Error setting parameter '%s'", name);
00422             
00423             uves_msg_debug("Setting parameter '%s' <- '%s' = %d", 
00424                    name, parent_name, value_int);
00425             break;
00426             
00427         case CPL_TYPE_DOUBLE:
00428             check( value_double = cpl_parameter_get_double(parent),
00429                "Error reading parameter '%s'", parent_name);
00430         
00431             check( cpl_parameter_set_double(p, value_double),
00432                "Error setting parameter '%s'", name);
00433             
00434             uves_msg_debug("Setting parameter '%s' <- '%s' = %e", 
00435                    name, parent_name, value_double);
00436             break;
00437             
00438         case CPL_TYPE_STRING:
00439             check( value_string = cpl_parameter_get_string(parent),
00440                "Error reading parameter '%s'", parent_name);
00441             
00442             check( cpl_parameter_set_string(p, value_string), 
00443                "Error setting parameter '%s'", name);
00444             
00445             uves_msg_debug("Setting parameter '%s' <- '%s' = '%s'", 
00446                    name, parent_name, value_string);
00447             break;
00448             
00449         default:
00450             assure(false, CPL_ERROR_UNSUPPORTED_MODE,
00451                "Parameter '%s' has type %s",
00452                name, uves_tostring_cpl_type(type));
00453         }  /* switch type */
00454         
00455         cpl_free(parent_name); parent_name = NULL;
00456         
00457     } /* Set each recipe parameter */
00458 
00459     /* Pass frame set without touching */
00460     recipe->frames = frames;
00461 
00462     /* 
00463      * Invoke recipe 
00464      *
00465      *  Remember message domain of caller,
00466      *   and number of warnings in caller.
00467      */
00468 
00469     {
00470     const char *domain = uves_msg_get_domain();
00471     int warnings_in_caller = uves_msg_get_warnings();
00472 
00473     sub_domain = uves_sprintf("%s.%s", domain, recipe_domain);
00474     uves_msg_set_domain(sub_domain);
00475 
00476     status = cpl_plugin_get_exec(plugin)(plugin);
00477 
00478     /* Reset state (domain+warnings) */
00479 
00480     uves_msg_set_domain(domain);
00481 
00482     /* Total number of warnings in caller is not
00483      * (previous warnings) + (subrecipe warnings)
00484      */
00485     uves_msg_add_warnings(warnings_in_caller);
00486     }
00487     
00488     /* On recipe failure: The recipe is responsible 
00489      *  for printing any error messages.
00490      *  A failing recipe is an unrecoverable error.
00491      */
00492 
00493     if (cpl_error_get_code() != CPL_ERROR_NONE)
00494     {
00495         /* Reset error stack but keep error code */
00496         cpl_error_code ec = cpl_error_get_code();
00497         uves_error_reset();
00498         assure( false, ec, "Recipe '%s' failed", recipe_id);
00499     }
00500     
00501     assure( status == 0, CPL_ERROR_ILLEGAL_OUTPUT,
00502         "Recipe '%s' failed with exit status %d", recipe_id, status);
00503     
00504     /* Call recipe_destroy */
00505     must_destroy_plugin = false;
00506     assure( cpl_plugin_get_deinit(plugin)(plugin) == 0, 
00507         CPL_ERROR_ILLEGAL_OUTPUT,
00508         "Error cleaning up recipe");
00509     
00510     uves_msg("Recipe '%s' succeeded", recipe_id);
00511 
00512   cleanup:
00513     cpl_free(parent_name); parent_name = NULL;
00514     cpl_free(sub_domain); sub_domain = NULL;
00515     if (must_destroy_plugin)
00516     {
00517         cpl_plugin_get_deinit(plugin)(plugin);
00518     }
00519 
00520     cpl_pluginlist_delete(list);
00521     
00522     return (cpl_error_get_code() != CPL_ERROR_NONE);
00523 }
00524 
00525 
00526 /*----------------------------------------------------------------------------*/
00544 /*----------------------------------------------------------------------------*/
00545 int
00546 uves_propagate_parameters(const char *subrecipe_id, cpl_parameterlist *parameters,
00547               const char *recipe_id, const char *context)
00548 {
00549     cpl_plugin *plugin    = NULL;
00550     cpl_pluginlist *list  = NULL;
00551     cpl_recipe *subrecipe = NULL;
00552     int status;
00553 
00554     /* Check input */
00555     if (subrecipe_id == NULL)
00556     {
00557         FAIL(-1, CPL_ERROR_NULL_INPUT, "Null subrecipe id");
00558     }
00559     /* context may be NULL */
00560     if (parameters == NULL)
00561     {
00562         FAIL(-1, CPL_ERROR_NULL_INPUT, "Null parameter list");
00563     }
00564     
00565     if (recipe_id == NULL)
00566     {
00567         FAIL(-1, CPL_ERROR_NULL_INPUT, "Null recipe id");
00568     }    
00569 
00570     /* Get the sub-recipe plugin */
00571     list = cpl_pluginlist_new();
00572 
00573     if      (strcmp(subrecipe_id, make_str(UVES_PHYSMOD_ID) ) == 0) status = uves_physmod_get_info(list);
00574     else if (strcmp(subrecipe_id, make_str(UVES_ORDERPOS_ID)) == 0) status = uves_orderpos_get_info(list);
00575     else if (strcmp(subrecipe_id, make_str(UVES_MBIAS_ID)   ) == 0) status = uves_mbias_get_info(list);
00576     else if (strcmp(subrecipe_id, make_str(UVES_MDARK_ID)   ) == 0) status = uves_mdark_get_info(list);
00577     else if (strcmp(subrecipe_id, make_str(UVES_MFLAT_ID)   ) == 0) status = uves_mflat_get_info(list);
00578     else if (strcmp(subrecipe_id, make_str(UVES_WAVECAL_ID) ) == 0) status = uves_wavecal_get_info(list);
00579     else if (strcmp(subrecipe_id, make_str(UVES_RESPONSE_ID)) == 0) status = uves_response_get_info(list);
00580     else if (strcmp(subrecipe_id, make_str(UVES_SCIRED_ID)  ) == 0) status = uves_scired_get_info(list);
00581     else if (strcmp(subrecipe_id, make_str(UVES_REDCHAIN_ID)) == 0) status = uves_redchain_get_info(list);
00582     else
00583     {
00584         cpl_pluginlist_delete(list);
00585         FAIL(-1, CPL_ERROR_DATA_NOT_FOUND, "Unknown recipe: '%s'", subrecipe_id);
00586     }
00587     
00588     if (status != 0)
00589     {
00590         cpl_pluginlist_delete(list);
00591         FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Could not get info about recipe '%s'", 
00592          subrecipe_id);
00593     }
00594 
00595     /* Get first plugin in plugin list, it must be of type recipe */
00596     if ((plugin = cpl_pluginlist_get_first(list)) == NULL)
00597     {
00598         cpl_pluginlist_delete(list);
00599         FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Error getting '%s' plugin", subrecipe_id);
00600     }
00601     if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE)
00602     {
00603         cpl_pluginlist_delete(list);
00604         FAIL(-1, CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");
00605     }
00606     subrecipe = (cpl_recipe *) plugin;
00607     
00608     /* Create parameter list by calling subrecipe initializer function */
00609     if( cpl_plugin_get_init(plugin)(plugin) != 0)
00610     {
00611         cpl_plugin_get_deinit(plugin)(plugin);
00612         cpl_pluginlist_delete(list);
00613         FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Error getting '%s' parameter list", 
00614          subrecipe_id);
00615     }
00616 
00617     if (subrecipe->parameters == NULL)
00618     {
00619         cpl_plugin_get_deinit(plugin)(plugin);
00620         cpl_pluginlist_delete(list);
00621         FAIL(-1, CPL_ERROR_NULL_INPUT, "Recipe '%s' returned NULL parameter list", 
00622          subrecipe_id);
00623     }
00624     
00625     if (propagate(subrecipe_id, subrecipe->parameters, parameters, recipe_id, context) != 0)
00626     {
00627         cpl_plugin_get_deinit(plugin)(plugin);
00628         cpl_pluginlist_delete(list);
00629         FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT, "Error propagating parameters from recipe '%s'", 
00630          subrecipe_id);
00631     }
00632     
00633     cpl_plugin_get_deinit(plugin)(plugin);
00634     cpl_pluginlist_delete(list);
00635     
00636     return 0;
00637 }
00638 
00639 /*----------------------------------------------------------------------------*/
00684 /*----------------------------------------------------------------------------*/
00685 
00686 int
00687 uves_propagate_parameters_step(const char *step_id,
00688                    cpl_parameterlist *parameters,
00689                    const char *recipe_id, const char *context)
00690 {
00691     cpl_parameterlist *subparameters = NULL;
00692     cpl_parameterlist *(*get_parameters)(void) = NULL; /* Pointer to function 
00693                               returning parameter list */
00694     
00695     /* Check input */
00696     if (step_id == NULL)
00697     {
00698         FAIL(-1, CPL_ERROR_NULL_INPUT, "Null parameter list");
00699     }
00700     
00701     if (parameters == NULL)
00702     {
00703         FAIL(-1, CPL_ERROR_NULL_INPUT, "Null parameter list");
00704     }
00705     
00706     if (recipe_id == NULL)
00707     {
00708         FAIL(-1, CPL_ERROR_NULL_INPUT, "Null recipe id");
00709     }    
00710     /* context may be NULL */
00711     
00712     /* Define which function to call */
00713     if      (strcmp(step_id, UVES_BACKSUB_ID ) == 0) 
00714     get_parameters = uves_backsub_define_parameters;
00715     else if (strcmp(step_id, UVES_EXTRACT_ID ) == 0)
00716     get_parameters = uves_extract_define_parameters;
00717     else if (strcmp(step_id, UVES_REBIN_ID   ) == 0) 
00718     get_parameters = uves_rebin_define_parameters;
00719     else if (strcmp(step_id, UVES_REDUCE_ID  ) == 0)
00720     get_parameters = uves_reduce_define_parameters;
00721     else
00722     {
00723         FAIL(-1, CPL_ERROR_DATA_NOT_FOUND, "Unknown sub-step: '%s'", step_id);
00724     }
00725 
00726     /* Get sub-step parameters */
00727     if( (subparameters = get_parameters()) == NULL )
00728     {
00729         FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Error getting '%s' parameter list", step_id);
00730     }
00731     
00732     if ( propagate(step_id, subparameters, parameters, recipe_id, context) != 0)
00733     {
00734         cpl_parameterlist_delete(subparameters);
00735         FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT, "Error propagating '%s' parameters", step_id);
00736     }
00737     
00738     cpl_parameterlist_delete(subparameters);
00739     return 0;
00740 }
00741 
00742 
00743 /*
00744  * Create an enumeration parameter.
00745  * One function for each of  int, double, string
00746  *    size of values array must match 'size', returns NULL iff error. 
00747  *
00748  * It would be much nicer to use a cpl_parameter_duplicate(), but that
00749  * doesn't exist
00750  *
00751  * (These three functions could be reduced to one function by use
00752  * of void pointers, but that is also ugly)
00753  */
00754 static cpl_parameter *
00755 create_parameter_enum_int(const char *name, cpl_type type,
00756               const char *description, 
00757               const char *context, 
00758               int default_value, int size,
00759               int *values)
00760 {
00761     /*  This is just ugly */
00762 
00763     cpl_parameter *result = NULL;
00764     
00765     if (! (1 <= size && size <= 10))
00766     {
00767         cpl_msg_error(__func__, "Unsupported enumeration size: %d (max is 10)", size);
00768         return NULL;
00769     }
00770     
00771     switch(size)
00772     {
00773     case 1:
00774         uves_parameter_new_enum(result, name,
00775                        type,
00776                        description,
00777                        context,
00778                        default_value, size,
00779                        values[0]);
00780         break;
00781     case 2:
00782         uves_parameter_new_enum(result, name,
00783                           type,
00784                           description,
00785                           context,
00786                           default_value, size,
00787                           values[0],
00788                           values[1]);
00789         break;
00790     case 3:
00791         uves_parameter_new_enum(result, name,
00792                           type,
00793                           description,
00794                           context,
00795                           default_value, size,
00796                           values[0],
00797                           values[1],
00798                           values[2]);
00799         break;
00800     case 4:
00801         uves_parameter_new_enum(result, name,
00802                           type,
00803                           description,
00804                           context,
00805                           default_value, size,
00806                           values[0], 
00807                           values[1], 
00808                           values[2], 
00809                           values[3]);
00810         break;
00811     case 5:
00812         uves_parameter_new_enum(result, name,
00813                           type,
00814                           description,
00815                           context,
00816                           default_value, size,
00817                           values[0], 
00818                           values[1], 
00819                           values[2], 
00820                           values[3], 
00821                           values[4]);
00822         break;
00823     case 6:
00824         uves_parameter_new_enum(result, name,
00825                           type,
00826                           description,
00827                           context,
00828                           default_value, size,
00829                           values[0], 
00830                           values[1], 
00831                           values[2], 
00832                           values[3], 
00833                           values[4], 
00834                           values[5]);
00835         break;
00836     case 7:
00837         uves_parameter_new_enum(result, name,
00838                           type,
00839                           description,
00840                           context,
00841                           default_value, size,
00842                           values[0], 
00843                           values[1], 
00844                           values[2], 
00845                           values[3], 
00846                           values[4], 
00847                           values[5], 
00848                           values[6]);
00849         break;
00850     case 8:
00851         uves_parameter_new_enum(result, name,
00852                           type,
00853                           description,
00854                           context,
00855                           default_value, size,
00856                           values[0], 
00857                           values[1], 
00858                           values[2], 
00859                           values[3], 
00860                           values[4], 
00861                           values[5], 
00862                           values[6], 
00863                           values[7]);
00864         break;
00865     case 9:
00866         uves_parameter_new_enum(result, name,
00867                           type,
00868                           description,
00869                           context,
00870                           default_value, size,
00871                           values[0], 
00872                           values[1], 
00873                           values[2], 
00874                           values[3], 
00875                           values[4], 
00876                           values[5], 
00877                           values[6], 
00878                           values[7], 
00879                           values[8]);
00880         break;
00881     case 10:
00882         uves_parameter_new_enum(result, name,
00883                        type,
00884                        description,
00885                        context,
00886                        default_value, size,
00887                        values[0], 
00888                        values[1], 
00889                        values[2], 
00890                        values[3], 
00891                        values[4], 
00892                        values[5], 
00893                        values[6], 
00894                        values[7], 
00895                        values[8], 
00896                        values[9]);
00897         break;
00898     } /* Switch size */
00899     return result;
00900 }
00901 static cpl_parameter *
00902 create_parameter_enum_double(const char *name, cpl_type type,
00903                  const char *description, 
00904                  const char *context, double default_value,
00905                  int size, double *values)
00906 {
00907     /*  This is very ugly */
00908     
00909     cpl_parameter *result = NULL; 
00910 
00911     if (! (1 <= size && size <= 10))
00912     {
00913         cpl_msg_error(__func__, "Unsupported enumeration size: %d (max is 10)", size);
00914         return NULL;
00915     }
00916     
00917     switch(size)
00918     {
00919     case 1:
00920         uves_parameter_new_enum(result, name,
00921                        type,
00922                        description,
00923                        context,
00924                        default_value, size,
00925                        values[0]);
00926         break;
00927     case 2:
00928         uves_parameter_new_enum(result, name,
00929                           type,
00930                           description,
00931                           context,
00932                           default_value, size,
00933                           values[0],
00934                           values[1]);
00935         break;
00936     case 3:
00937         uves_parameter_new_enum(result, name,
00938                           type,
00939                           description,
00940                           context,
00941                           default_value, size,
00942                           values[0],
00943                           values[1],
00944                           values[2]);
00945         break;
00946     case 4:
00947         uves_parameter_new_enum(result, name,
00948                           type,
00949                           description,
00950                           context,
00951                           default_value, size,
00952                           values[0], 
00953                           values[1], 
00954                           values[2], 
00955                           values[3]);
00956         break;
00957     case 5:
00958         uves_parameter_new_enum(result, name,
00959                           type,
00960                           description,
00961                           context,
00962                           default_value, size,
00963                           values[0], 
00964                           values[1], 
00965                           values[2], 
00966                           values[3], 
00967                           values[4]);
00968         break;
00969     case 6:
00970         uves_parameter_new_enum(result, name,
00971                           type,
00972                           description,
00973                           context,
00974                           default_value, size,
00975                           values[0], 
00976                           values[1], 
00977                           values[2], 
00978                           values[3], 
00979                           values[4], 
00980                           values[5]);
00981         break;
00982     case 7:
00983         uves_parameter_new_enum(result, name,
00984                           type,
00985                           description,
00986                           context,
00987                           default_value, size,
00988                           values[0], 
00989                           values[1], 
00990                           values[2], 
00991                           values[3], 
00992                           values[4], 
00993                           values[5], 
00994                           values[6]);
00995         break;
00996     case 8:
00997         uves_parameter_new_enum(result, name,
00998                           type,
00999                           description,
01000                           context,
01001                           default_value, size,
01002                           values[0], 
01003                           values[1], 
01004                           values[2], 
01005                           values[3], 
01006                           values[4], 
01007                           values[5], 
01008                           values[6], 
01009                           values[7]);
01010         break;
01011     case 9:
01012         uves_parameter_new_enum(result, name,
01013                           type,
01014                           description,
01015                           context,
01016                           default_value, size,
01017                           values[0], 
01018                           values[1], 
01019                           values[2], 
01020                           values[3], 
01021                           values[4], 
01022                           values[5], 
01023                           values[6], 
01024                           values[7], 
01025                           values[8]);
01026         break;
01027     case 10:
01028         uves_parameter_new_enum(result, name,
01029                        type,
01030                        description,
01031                        context,
01032                        default_value, size,
01033                        values[0], 
01034                        values[1], 
01035                        values[2], 
01036                        values[3], 
01037                        values[4], 
01038                        values[5], 
01039                        values[6], 
01040                        values[7], 
01041                        values[8], 
01042                        values[9]);
01043         break;
01044     } /* Switch size */
01045     return result;
01046 }
01047 static cpl_parameter *
01048 create_parameter_enum_string(const char *name, cpl_type type,
01049                  const char *description, 
01050                  const char *context, 
01051                  const char *default_value, 
01052                  int size, const char **values)
01053 {
01054     /*  This is extremely ugly */
01055     
01056     cpl_parameter *result = NULL;
01057 
01058     if (! (1 <= size && size <= 10))
01059     {
01060         cpl_msg_error(__func__, "Unsupported enumeration size: %d (max is 10)", size);
01061         return NULL;
01062     }
01063     
01064     switch(size)
01065     {
01066     case 1:
01067         uves_parameter_new_enum(result, name,
01068                        type,
01069                        description,
01070                        context,
01071                        default_value, size,
01072                        values[0]);
01073         break;
01074     case 2:
01075         uves_parameter_new_enum(result, name,
01076                           type,
01077                           description,
01078                           context,
01079                           default_value, size,
01080                           values[0],
01081                           values[1]);
01082         break;
01083     case 3:
01084         uves_parameter_new_enum(result, name,
01085                           type,
01086                           description,
01087                           context,
01088                           default_value, size,
01089                           values[0],
01090                           values[1],
01091                           values[2]);
01092         break;
01093     case 4:
01094         uves_parameter_new_enum(result, name,
01095                           type,
01096                           description,
01097                           context,
01098                           default_value, size,
01099                           values[0], 
01100                           values[1], 
01101                           values[2], 
01102                           values[3]);
01103         break;
01104     case 5:
01105         uves_parameter_new_enum(result, name,
01106                           type,
01107                           description,
01108                           context,
01109                           default_value, size,
01110                           values[0], 
01111                           values[1], 
01112                           values[2], 
01113                           values[3], 
01114                           values[4]);
01115         break;
01116     case 6:
01117         uves_parameter_new_enum(result, name,
01118                           type,
01119                           description,
01120                           context,
01121                           default_value, size,
01122                           values[0], 
01123                           values[1], 
01124                           values[2], 
01125                           values[3], 
01126                           values[4], 
01127                           values[5]);
01128         break;
01129     case 7:
01130         uves_parameter_new_enum(result, name,
01131                           type,
01132                           description,
01133                           context,
01134                           default_value, size,
01135                           values[0], 
01136                           values[1], 
01137                           values[2], 
01138                           values[3], 
01139                           values[4], 
01140                           values[5], 
01141                           values[6]);
01142         break;
01143     case 8:
01144         uves_parameter_new_enum(result, name,
01145                           type,
01146                           description,
01147                           context,
01148                           default_value, size,
01149                           values[0], 
01150                           values[1], 
01151                           values[2], 
01152                           values[3], 
01153                           values[4], 
01154                           values[5], 
01155                           values[6], 
01156                           values[7]);
01157         break;
01158     case 9:
01159         uves_parameter_new_enum(result, name,
01160                           type,
01161                           description,
01162                           context,
01163                           default_value, size,
01164                           values[0], 
01165                           values[1], 
01166                           values[2], 
01167                           values[3], 
01168                           values[4], 
01169                           values[5], 
01170                           values[6], 
01171                           values[7], 
01172                           values[8]);
01173         break;
01174     case 10:
01175         uves_parameter_new_enum(result, name,
01176                        type,
01177                        description,
01178                        context,
01179                        default_value, size,
01180                        values[0], 
01181                        values[1], 
01182                        values[2], 
01183                        values[3], 
01184                        values[4], 
01185                        values[5], 
01186                        values[6], 
01187                        values[7], 
01188                        values[8], 
01189                        values[9]);
01190         break;
01191     } /* Switch size */
01192     return result;
01193 }
01194 
01195 
01196 /*----------------------------------------------------------------------------*/
01232 /*----------------------------------------------------------------------------*/
01233 
01234 static int
01235 propagate(const char *substep_id, const cpl_parameterlist *sub_parameters, 
01236       cpl_parameterlist *parent_parameters,
01237       const char *parent_id, const char *context)
01238 {
01239     const cpl_parameter *p = NULL;
01240     
01241     /* For each sub-recipe parameter:
01242        prefix with context and insert in parent parameter list
01243 
01244        Set (overwrite) default value as current value
01245     */
01246     for (p = irplib_parameterlist_get_first_const(sub_parameters);
01247      p != NULL;
01248      p = irplib_parameterlist_get_next_const(sub_parameters) )
01249     {
01250         const char *name          = cpl_parameter_get_name(p);   
01251         const char *description   = cpl_parameter_get_help(p);
01252         const char *subcontext    = cpl_parameter_get_context(p);
01253         const char *alias         = cpl_parameter_get_alias(p, 
01254                                 CPL_PARAMETER_MODE_CLI);
01255         cpl_parameter_class class = cpl_parameter_get_class(p);
01256         cpl_type type             = cpl_parameter_get_type(p);
01257         
01258         /* Check that S <= name
01259          * and S <= c and c <= name,
01260          * where S is either subrecipe id or 'uves', c is the context,
01261          * and "<=" means "is substring of"
01262          */
01263 
01264         {
01265         const char *S;
01266                 
01267         if (strstr(name, "uves.") == name)
01268             {
01269             S = "uves";
01270             }
01271         else
01272             {
01273             S = substep_id;
01274 
01275             /* Check S <= name */
01276             if (strstr(name, S) != name)
01277                 {
01278                 FAIL(-1, CPL_ERROR_ILLEGAL_INPUT,
01279                      "Recipe id '%s' is not prefix of parameter name '%s'",
01280                      S, name);
01281                 }
01282             }
01283         
01284         /* Check S <= c */
01285         if (strstr(subcontext, S) != subcontext)
01286             {
01287             FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, 
01288                  "Recipe id '%s' is not prefix of parameter context '%s'", 
01289                  S, subcontext);
01290             }
01291         
01292         /* Check c <= name */
01293         if (strstr(name, subcontext) != name)
01294             {
01295             FAIL(-1, CPL_ERROR_ILLEGAL_INPUT,
01296                  "Parameter context '%s' is not prefix of parameter name '%s'", 
01297                  subcontext, name);
01298             }
01299         }/* End check parameter format */
01300         
01301         if (strcmp(subcontext, "uves") != 0)
01302         {
01303             int enum_size;
01304             
01305             cpl_parameter *new_par  = NULL;
01306             char *new_name;
01307             char *new_context;
01308             char *new_alias;
01309             
01310             if (context == NULL)
01311             {
01312                 new_name     = uves_sprintf("%s.%s", parent_id, name);     /* R.S.x */
01313                 new_context  = uves_sprintf("%s", parent_id);              /* R     */
01314                 if (alias != NULL)
01315                 {
01316                     new_alias = uves_sprintf("%s.%s", substep_id, alias); /* S.A */
01317                 }
01318                 else
01319                 {
01320                     new_alias = NULL;
01321                 }
01322             }
01323             else
01324             {
01325                 new_name     = uves_sprintf("%s.%s.%s", parent_id, context, name);  
01326                 /* R.c.Sx */
01327                 new_context  = uves_sprintf("%s.%s", parent_id, context); 
01328                 /* R.c    */
01329                 if (alias != NULL)
01330                 {
01331                     new_alias = uves_sprintf("%s.%s.%s", 
01332                                  context, substep_id, alias); 
01333                     /* c.S.A */
01334                 }
01335                 else
01336                 {
01337                     new_alias = NULL;
01338                 }
01339             }
01340             
01341             if (new_name == NULL || new_context == NULL)
01342             {
01343                 if (new_name    != NULL) cpl_free(new_name);
01344                 if (new_context != NULL) cpl_free(new_context);
01345                 if (new_alias   != NULL) cpl_free(new_alias);
01346                 FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT, "Memory allocation failed");
01347             }
01348             
01349             
01350             /* Check for legal class/type before switch */
01351             if (class != CPL_PARAMETER_CLASS_VALUE &&
01352             class != CPL_PARAMETER_CLASS_RANGE &&
01353             class != CPL_PARAMETER_CLASS_ENUM)
01354             {
01355                 cpl_free(new_name);
01356                 cpl_free(new_context);
01357                 if (new_alias != NULL) cpl_free(new_alias);
01358                 FAIL(-1, CPL_ERROR_TYPE_MISMATCH,
01359                  "Unrecognized class of parameter '%s'", name);
01360             }
01361             
01362             if (type != CPL_TYPE_BOOL   &&
01363             type != CPL_TYPE_INT    &&
01364             type != CPL_TYPE_DOUBLE &&
01365             type != CPL_TYPE_STRING)
01366             {
01367                 cpl_free(new_name);
01368                 cpl_free(new_context);
01369                 if (new_alias != NULL) cpl_free(new_alias);
01370                 FAIL(-1, CPL_ERROR_UNSUPPORTED_MODE, "Unsupported type: %s",
01371                  uves_tostring_cpl_type(type));
01372             }
01373             
01374             /* Create a new parameter from the sub-parameter */
01375             switch (class)
01376             {
01377             case CPL_PARAMETER_CLASS_VALUE:
01378                 switch (type)
01379                 {
01380                 case CPL_TYPE_BOOL:
01381                     uves_parameter_new_value(new_par, new_name,
01382                                  type,
01383                                  description,
01384                                  new_context,
01385                                  cpl_parameter_get_default_bool(p));
01386                     break;
01387                     
01388                 case CPL_TYPE_INT:
01389                     uves_parameter_new_value(new_par, new_name,
01390                                  type,
01391                                  description,
01392                                  new_context,
01393                                  cpl_parameter_get_default_int(p));
01394                     break;
01395                     
01396                 case CPL_TYPE_DOUBLE:
01397                     uves_parameter_new_value(new_par, new_name,
01398                                  type,
01399                                  description,
01400                                  new_context,
01401                                  cpl_parameter_get_default_double(p));
01402                     break;
01403                 case CPL_TYPE_STRING:
01404                     uves_parameter_new_value(new_par, new_name,
01405                                  type,
01406                                  description,
01407                                  new_context,
01408                                  cpl_parameter_get_default_string(p));
01409                     break;
01410                 default:
01411                     break; 
01412                 }       /* switch type */
01413                 
01414                 break;   /* CLASS_VALUE */
01415                 
01416             case CPL_PARAMETER_CLASS_RANGE:
01417                 /* Range is either int or double */
01418                 switch (type)
01419                 {
01420                     int min_int, max_int;
01421                     double min_double, max_double;
01422                     
01423                 case CPL_TYPE_INT:
01424                     min_int = cpl_parameter_get_range_min_int(p);
01425                     max_int = cpl_parameter_get_range_max_int(p);
01426                     
01427                     uves_parameter_new_range(new_par, new_name,
01428                                  type,
01429                                  description,
01430                                  new_context,
01431                                  cpl_parameter_get_default_int(p),
01432                                  min_int, max_int);
01433                     break;
01434                     
01435                 case CPL_TYPE_DOUBLE:
01436                     min_double = cpl_parameter_get_range_min_double(p);
01437                     max_double = cpl_parameter_get_range_max_double(p);
01438                     
01439                     uves_parameter_new_range(new_par, new_name,
01440                                  type,
01441                                  description,
01442                                  new_context,
01443                                  cpl_parameter_get_default_double(p),
01444                                  min_double, max_double);
01445                     break;
01446                 default:
01447                     break;
01448                 }
01449         
01450                 break;   /* CLASS_RANGE */
01451         
01452             case CPL_PARAMETER_CLASS_ENUM:
01453                 enum_size = cpl_parameter_get_enum_size(p);
01454             
01455                 /* Enum type is either int, double or string */
01456                 switch (type)
01457                 {
01458                     int        *values_int;        /* Arrays to hold enum values */
01459                     double     *values_double;
01460                     const char **values_string;
01461                     int i;
01462                     
01463                 case CPL_TYPE_INT:
01464                     if ( (values_int = cpl_malloc(sizeof(int) * enum_size))
01465                      == NULL)
01466                     {
01467                         cpl_free(new_name);
01468                         cpl_free(new_context);
01469                         if (new_alias != NULL) cpl_free(new_alias);
01470                         FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT, 
01471                          "Memory allocation failed");
01472                     }
01473                     for (i = 0; i < enum_size; i++)
01474                     {
01475                         values_int[i] = cpl_parameter_get_enum_int(p, i);
01476                     }
01477                 
01478                     new_par = create_parameter_enum_int(
01479                     new_name,
01480                     type,
01481                     description,
01482                     new_context,
01483                     cpl_parameter_get_default_int(p),
01484                     enum_size,
01485                     values_int);
01486                     cpl_free(values_int);
01487                     break;  /* Enum type int */
01488                     
01489                 case CPL_TYPE_DOUBLE:
01490                     if ( (values_double = 
01491                       cpl_malloc(sizeof(double) * enum_size)) == NULL)
01492                     {
01493                         cpl_free(new_name);
01494                         cpl_free(new_context);
01495                         if (new_alias != NULL) cpl_free(new_alias);
01496                         FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT,
01497                          "Memory allocation failed");
01498                     }
01499                     for (i = 0; i < enum_size; i++)
01500                     {
01501                         values_double[i] = cpl_parameter_get_enum_double(p, i);
01502                     }
01503                 
01504                     new_par = create_parameter_enum_double(
01505                     new_name,
01506                     type,
01507                     description,
01508                     new_context,
01509                     cpl_parameter_get_default_double(p),
01510                     enum_size,
01511                     values_double);
01512                     cpl_free(values_double);
01513 
01514                     break;  /* Enum type double */
01515             
01516                 case CPL_TYPE_STRING:
01517                     if ( (values_string = 
01518                       cpl_malloc(sizeof(char *) * enum_size)) == NULL)
01519                     {
01520                         cpl_free(new_name);
01521                         cpl_free(new_context);
01522                         if (new_alias != NULL) cpl_free(new_alias);
01523                         FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT, 
01524                          "Memory allocation failed");
01525                     }
01526                     for (i = 0; i < enum_size; i++)
01527                     {
01528                         values_string[i] = cpl_parameter_get_enum_string(p, i);
01529                     }
01530                 
01531                     new_par = create_parameter_enum_string(
01532                     new_name,
01533                     type,
01534                     description,
01535                     new_context,
01536                     cpl_parameter_get_default_string(p),
01537                     enum_size,
01538                     values_string);
01539                     cpl_free(values_string);
01540                     
01541                     break;  /* Enum type string */
01542                 
01543                 default:
01544                     break;
01545                 
01546                 } /* Switch enum type */
01547             
01548                 break;   /* CLASS_ENUM */
01549 
01550             default:
01551                 break;
01552             
01553             } /* Switch class */
01554 
01555             if (new_par == NULL)
01556             {
01557                 cpl_free(new_name);
01558                 cpl_free(new_context);
01559                 if (new_alias != NULL) cpl_free(new_alias);
01560                 FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT,
01561                  "Propagation of parameter '%s' failed", 
01562                  name);
01563             }
01564         
01565             /* Also propagate alias */
01566             if (alias != NULL)
01567             {
01568                 cpl_parameter_set_alias(new_par, CPL_PARAMETER_MODE_CLI, new_alias);
01569             }
01570 
01571             /* Insert parameter in parent parameter list */
01572             cpl_parameterlist_append(parent_parameters, new_par);
01573             
01574             cpl_free(new_name);
01575             cpl_free(new_context);
01576             if (new_alias != NULL) cpl_free(new_alias);
01577             
01578         }  /* If parameter context was not 'uves' */
01579         
01580     } /* For each sub-recipe parameter */
01581     
01582     return (cpl_error_get_code() != CPL_ERROR_NONE);
01583 }
01584 
01585 

Generated on Tue Jun 19 14:39:16 2007 for UVES Pipeline Reference Manual by  doxygen 1.4.6