00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 #ifdef HAVE_CONFIG_H
00099 # include <config.h>
00100 #endif
00101
00102
00110
00111
00112
00113
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
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
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
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
00228
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,
00245 -1, INT_MAX);
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;
00297
00298
00299
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
00305
00306
00307 check( list = cpl_pluginlist_new(),
00308 "Error allocating plugin list");
00309
00310
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
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
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
00353
00354
00355
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
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 }
00454
00455 cpl_free(parent_name); parent_name = NULL;
00456
00457 }
00458
00459
00460 recipe->frames = frames;
00461
00462
00463
00464
00465
00466
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
00479
00480 uves_msg_set_domain(domain);
00481
00482
00483
00484
00485 uves_msg_add_warnings(warnings_in_caller);
00486 }
00487
00488
00489
00490
00491
00492
00493 if (cpl_error_get_code() != CPL_ERROR_NONE)
00494 {
00495
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
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
00555 if (subrecipe_id == NULL)
00556 {
00557 FAIL(-1, CPL_ERROR_NULL_INPUT, "Null subrecipe id");
00558 }
00559
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
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
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
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;
00693
00694
00695
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
00711
00712
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
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
00745
00746
00747
00748
00749
00750
00751
00752
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
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 }
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
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 }
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
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 }
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
01242
01243
01244
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
01259
01260
01261
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
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
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
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 }
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);
01313 new_context = uves_sprintf("%s", parent_id);
01314 if (alias != NULL)
01315 {
01316 new_alias = uves_sprintf("%s.%s", substep_id, alias);
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
01327 new_context = uves_sprintf("%s.%s", parent_id, context);
01328
01329 if (alias != NULL)
01330 {
01331 new_alias = uves_sprintf("%s.%s.%s",
01332 context, substep_id, alias);
01333
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
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
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 }
01413
01414 break;
01415
01416 case CPL_PARAMETER_CLASS_RANGE:
01417
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;
01451
01452 case CPL_PARAMETER_CLASS_ENUM:
01453 enum_size = cpl_parameter_get_enum_size(p);
01454
01455
01456 switch (type)
01457 {
01458 int *values_int;
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;
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;
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;
01542
01543 default:
01544 break;
01545
01546 }
01547
01548 break;
01549
01550 default:
01551 break;
01552
01553 }
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
01566 if (alias != NULL)
01567 {
01568 cpl_parameter_set_alias(new_par, CPL_PARAMETER_MODE_CLI, new_alias);
01569 }
01570
01571
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 }
01579
01580 }
01581
01582 return (cpl_error_get_code() != CPL_ERROR_NONE);
01583 }
01584
01585