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
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 #ifdef HAVE_CONFIG_H
00117 # include <config.h>
00118 #endif
00119
00120
00128
00129
00130
00131
00132
00133
00134 #include <uves_parameters.h>
00135 #include <uves_dump.h>
00136 #include <uves_backsub.h>
00137 #include <uves_extract.h>
00138 #include <uves_rebin.h>
00139 #include <uves_mdark_impl.h>
00140 #include <uves_reduce.h>
00141 #include <uves_utils_wrappers.h>
00142 #include <uves.h>
00143 #include <uves_error.h>
00144 #include <uves_msg.h>
00145
00146 #include <cpl.h>
00147
00148
00149
00150
00151 static int propagate(const char *substep_id, const cpl_parameterlist *sub_parameters,
00152 cpl_parameterlist *parent_parameters,
00153 const char *parent_id, const char *context);
00154 static cpl_parameter *
00155 create_parameter_enum_int (const char *name, cpl_type type,
00156 const char *description, const char *context,
00157 int default_value, int size, int *values);
00158 static cpl_parameter *
00159 create_parameter_enum_double(const char *name, cpl_type type, const char *description,
00160 const char *context, double default_value,
00161 int size, double *values);
00162 static cpl_parameter *
00163 create_parameter_enum_string(const char *name, cpl_type type, const char *description,
00164 const char *context, const char *default_value,
00165 int size, const char **values);
00166
00167
00168
00169 #define FAIL(return_code, error_code, ...) do { \
00170 cpl_msg_error(__func__, __VA_ARGS__); \
00171 if (cpl_error_get_code() == CPL_ERROR_NONE) { \
00172 cpl_error_set(__func__, error_code); \
00173 } \
00174 return return_code; \
00175 } while(false)
00176
00179
00180
00181
00182
00191
00192 cpl_error_code
00193 uves_define_global_parameters(cpl_parameterlist *parlist)
00194 {
00195 const char *context = "uves";
00196 const char *name = "";
00197 char *full_name = NULL;
00198 cpl_parameter *p;
00199
00200 {
00201 name = "debug";
00202 full_name = uves_sprintf("%s.%s", context, name);
00203 uves_parameter_new_value(p, full_name,
00204 CPL_TYPE_BOOL,
00205 "Whether or not to save intermediate "
00206 "results to local directory",
00207 context,
00208 false);
00209 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00210 cpl_parameterlist_append(parlist, p);
00211 cpl_free(full_name);
00212 }
00213
00214
00215 {
00216 name = "plotter";
00217 full_name = uves_sprintf("%s.%s", context, name);
00218 uves_parameter_new_value(
00219 p, full_name,
00220 CPL_TYPE_STRING,
00221 "Any plots produced by the recipe "
00222 "are redirected to the command specified "
00223 "by this parameter. The plotting command "
00224 "must contain the substring 'gnuplot' and "
00225 "must be able to parse gnuplot syntax on its "
00226 "standard input. "
00227 "Valid examples of such a command may include "
00228 "'gnuplot -persist' and 'cat > mygnuplot$$.gp'. "
00229 "A finer control of the plotting options can "
00230 "be obtained by writing an "
00231 "executable script, e.g. my_gnuplot.pl, that "
00232 "executes gnuplot after setting the desired gnuplot "
00233 "options (e.g. set terminal pslatex color). "
00234 "To turn off plotting, set this parameter to 'no'",
00235 context,
00236 "no");
00237
00238 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00239 cpl_parameterlist_append(parlist, p);
00240 cpl_free(full_name);
00241 }
00242
00243
00244
00245 {
00246 name = "process_chip";
00247 full_name = uves_sprintf("%s.%s", context, name);
00248 uves_parameter_new_enum(p, full_name,
00249 CPL_TYPE_STRING,
00250 "In case of RED arm data allow to proces the "
00251 "redl, redu, or both chip(s)",
00252 context,
00253 "both",3,"both","redl","redu");
00254 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00255 cpl_parameterlist_append(parlist, p);
00256 cpl_free(full_name);
00257 }
00258
00259 if (0)
00260
00261
00262 {
00263 name = "msginfolevel";
00264 full_name = uves_sprintf("%s.%s", context, name);
00265 uves_parameter_new_range(p, full_name,
00266 CPL_TYPE_INT,
00267 "This parameter controls the subdivision "
00268 "of the 'info' message level (set e.g. with "
00269 "esorex' --msg-level). The higher the value "
00270 "of this parameter, the more messages are "
00271 "printed at the info level. For minimum "
00272 "output, set to zero. Increase the level "
00273 "(to 1, 2, 3, ...) for more output. The "
00274 "value -1 is a special value meaning maximum "
00275 "output",
00276 context,
00277 -1,
00278 -1, INT_MAX);
00279 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00280 cpl_parameterlist_append(parlist, p);
00281 cpl_free(full_name);
00282 }
00283
00284 if (cpl_error_get_code() != CPL_ERROR_NONE)
00285 {
00286 cpl_msg_error(__func__, "Creation of global parameters failed: '%s'",
00287 cpl_error_get_where());
00288 }
00289
00290 return cpl_error_get_code();
00291 }
00292
00293
00294
00295
00310
00311
00312 int
00313 uves_exec_recipe(int (*get_info)(cpl_pluginlist *),
00314 const char *recipe_domain,
00315 const cpl_parameterlist *parameters,
00316 cpl_frameset *frames,
00317 const char *caller_id, const char *context)
00318 {
00319 cpl_pluginlist *list = NULL;
00320 cpl_plugin *plugin = NULL;
00321 cpl_recipe *recipe = NULL;
00322
00323 const char *recipe_id = NULL;
00324 cpl_parameter *p = NULL;
00325 char *parent_name = NULL;
00326 char *sub_domain = NULL;
00327 int status = 0;
00328
00329 bool must_destroy_plugin = false;
00330
00331
00332
00333 assure(recipe_domain != NULL, CPL_ERROR_NULL_INPUT, "Null recipe message domain");
00334 assure(parameters != NULL, CPL_ERROR_NULL_INPUT, "Null parameter list");
00335 assure(frames != NULL, CPL_ERROR_NULL_INPUT, "Null frame set");
00336 assure(caller_id != NULL, CPL_ERROR_NULL_INPUT, "Null caller recipe name");
00337
00338
00339
00340 check( list = cpl_pluginlist_new(),
00341 "Error allocating plugin list");
00342
00343
00344 status = get_info(list);
00345
00346 assure( status == 0, CPL_ERROR_ILLEGAL_INPUT,
00347 "Could not get info about recipe");
00348
00349
00350 check( plugin = cpl_pluginlist_get_first(list), "Error getting plugin");
00351 assure( plugin != NULL, CPL_ERROR_ILLEGAL_INPUT,
00352 "Plugin '%s' returned empty plugin list", recipe_id);
00353 assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
00354 CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");
00355 recipe = (cpl_recipe *) plugin;
00356
00357 recipe_id = cpl_strdup(cpl_plugin_get_name(plugin));
00358
00359
00360 must_destroy_plugin = true;
00361 assure( cpl_plugin_get_init(plugin)(plugin) == 0, CPL_ERROR_ILLEGAL_INPUT,
00362 "Error initializing recipe");
00363 assure( recipe->parameters != NULL, CPL_ERROR_ILLEGAL_INPUT,
00364 "Recipe '%s' returned NULL parameter list", recipe_id);
00365
00366
00367
00368
00369
00370
00371 for (p = cpl_parameterlist_get_first(recipe->parameters);
00372 p != NULL;
00373 p = cpl_parameterlist_get_next(recipe->parameters) )
00374 {
00375 const char *name = cpl_parameter_get_name(p);
00376 const char *subcontext = cpl_parameter_get_context(p);
00377 cpl_type type = cpl_parameter_get_type(p);
00378
00379 const cpl_parameter *parent;
00380
00381 if (strcmp(subcontext, "uves") == 0)
00382 {
00383 parent_name = uves_sprintf("%s", name);
00384 }
00385 else
00386 {
00387 if (context != NULL)
00388 {
00389 parent_name = uves_sprintf("%s.%s.%s", caller_id, context, name);
00390 }
00391 else
00392 {
00393 parent_name = uves_sprintf("%s.%s", caller_id, name);
00394 }
00395 }
00396
00397
00398 check( parent = cpl_parameterlist_find_const(parameters, parent_name),
00399 "Could not get parameter '%s' from provided parameter list", parent_name);
00400
00401 assure( parent != NULL, CPL_ERROR_DATA_NOT_FOUND,
00402 "Missing parameter '%s' needed to define '%s' in context '%s'",
00403 parent_name, name, context);
00404
00405 assure( cpl_parameter_get_type(parent) == type, CPL_ERROR_TYPE_MISMATCH,
00406 "Parameter '%s' type is %s. Type %s needed for recipe parameter '%s'",
00407 parent_name,
00408 uves_tostring_cpl_type(cpl_parameter_get_type(parent)),
00409 uves_tostring_cpl_type(type),
00410 name);
00411
00412 switch (type)
00413 {
00414 int value_int;
00415 bool value_bool;
00416 double value_double;
00417 const char *value_string;
00418
00419 case CPL_TYPE_BOOL:
00420 check( value_bool = cpl_parameter_get_bool(parent),
00421 "Error reading parameter '%s'", parent_name);
00422
00423 check( cpl_parameter_set_bool(p, value_bool),
00424 "Error setting parameter '%s'", name);
00425
00426 uves_msg_debug("Setting parameter '%s' <- '%s' = %s",
00427 name, parent_name, (value_bool) ? "true" : "false");
00428 break;
00429
00430 case CPL_TYPE_INT:
00431 check( value_int = cpl_parameter_get_int(parent),
00432 "Error reading parameter '%s'", parent_name);
00433
00434 check( cpl_parameter_set_int(p, value_int),
00435 "Error setting parameter '%s'", name);
00436
00437 uves_msg_debug("Setting parameter '%s' <- '%s' = %d",
00438 name, parent_name, value_int);
00439 break;
00440
00441 case CPL_TYPE_DOUBLE:
00442 check( value_double = cpl_parameter_get_double(parent),
00443 "Error reading parameter '%s'", parent_name);
00444
00445 check( cpl_parameter_set_double(p, value_double),
00446 "Error setting parameter '%s'", name);
00447
00448 uves_msg_debug("Setting parameter '%s' <- '%s' = %e",
00449 name, parent_name, value_double);
00450 break;
00451
00452 case CPL_TYPE_STRING:
00453 check( value_string = cpl_parameter_get_string(parent),
00454 "Error reading parameter '%s'", parent_name);
00455
00456 check( cpl_parameter_set_string(p, value_string),
00457 "Error setting parameter '%s'", name);
00458
00459 uves_msg_debug("Setting parameter '%s' <- '%s' = '%s'",
00460 name, parent_name, value_string);
00461 break;
00462
00463 default:
00464 assure(false, CPL_ERROR_UNSUPPORTED_MODE,
00465 "Parameter '%s' has type %s",
00466 name, uves_tostring_cpl_type(type));
00467 }
00468
00469 cpl_free(parent_name); parent_name = NULL;
00470
00471 }
00472
00473
00474 recipe->frames = frames;
00475
00476
00477
00478
00479
00480
00481
00482
00483 {
00484 const char *domain = uves_msg_get_domain();
00485 int warnings_in_caller = uves_msg_get_warnings();
00486
00487 sub_domain = uves_sprintf("%s.%s", domain, recipe_domain);
00488 uves_msg_set_domain(sub_domain);
00489
00490 status = cpl_plugin_get_exec(plugin)(plugin);
00491
00492
00493
00494 uves_msg_set_domain(domain);
00495
00496
00497
00498
00499 uves_msg_add_warnings(warnings_in_caller);
00500 }
00501
00502
00503
00504
00505
00506
00507 if (cpl_error_get_code() != CPL_ERROR_NONE)
00508 {
00509
00510 cpl_error_code ec = cpl_error_get_code();
00511 uves_error_reset();
00512 assure( false, ec, "Recipe '%s' failed", recipe_id);
00513 }
00514
00515 assure( status == 0, CPL_ERROR_ILLEGAL_OUTPUT,
00516 "Recipe '%s' failed with exit status %d", recipe_id, status);
00517
00518
00519 must_destroy_plugin = false;
00520 assure( cpl_plugin_get_deinit(plugin)(plugin) == 0,
00521 CPL_ERROR_ILLEGAL_OUTPUT,
00522 "Error cleaning up recipe");
00523
00524 uves_msg("Recipe '%s' succeeded", recipe_id);
00525
00526 cleanup:
00527 uves_free_string_const(&recipe_id);
00528 cpl_free(parent_name); parent_name = NULL;
00529 cpl_free(sub_domain); sub_domain = NULL;
00530 if (must_destroy_plugin)
00531 {
00532 cpl_plugin_get_deinit(plugin)(plugin);
00533 }
00534
00535 cpl_pluginlist_delete(list);
00536
00537 return (cpl_error_get_code() != CPL_ERROR_NONE);
00538 }
00539
00540
00555
00556
00557 int
00558 uves_invoke_recipe(const char *recipe_id, const cpl_parameterlist *parameters,
00559 cpl_frameset *frames,
00560 const char *caller_id, const char *context)
00561 {
00562 assure(recipe_id != NULL, CPL_ERROR_NULL_INPUT, "Null recipe name");
00563
00564 if (strcmp(recipe_id, make_str(UVES_PHYSMOD_ID) ) == 0) return uves_exec_recipe(&uves_physmod_get_info, UVES_PHYSMOD_DOM, parameters, frames, caller_id, context);
00565 else if (strcmp(recipe_id, make_str(UVES_ORDERPOS_ID)) == 0) return uves_exec_recipe(&uves_orderpos_get_info, UVES_ORDERPOS_DOM, parameters, frames, caller_id, context);
00566 else if (strcmp(recipe_id, make_str(UVES_MBIAS_ID) ) == 0) return uves_exec_recipe(&uves_mbias_get_info, UVES_MBIAS_DOM, parameters, frames, caller_id, context);
00567 else if (strcmp(recipe_id, make_str(UVES_MDARK_ID) ) == 0) return uves_exec_recipe(&uves_mdark_get_info, UVES_MDARK_DOM, parameters, frames, caller_id, context);
00568 else if (strcmp(recipe_id, make_str(UVES_MFLAT_ID) ) == 0) return uves_exec_recipe(&uves_mflat_get_info, UVES_MFLAT_DOM, parameters, frames, caller_id, context);
00569 else if (strcmp(recipe_id, make_str(UVES_WAVECAL_ID) ) == 0) return uves_exec_recipe(&uves_wavecal_get_info, UVES_WAVECAL_DOM, parameters, frames, caller_id, context);
00570 else if (strcmp(recipe_id, make_str(UVES_RESPONSE_ID)) == 0) return uves_exec_recipe(&uves_response_get_info, UVES_RESPONSE_DOM, parameters, frames, caller_id, context);
00571 else if (strcmp(recipe_id, make_str(UVES_SCIRED_ID) ) == 0) return uves_exec_recipe(&uves_scired_get_info, UVES_SCIRED_DOM, parameters, frames, caller_id, context);
00572 else if (strcmp(recipe_id, make_str(UVES_REDCHAIN_ID)) == 0) return uves_exec_recipe(&uves_redchain_get_info, UVES_REDCHAIN_DOM, parameters, frames, caller_id, context);
00573 else
00574 {
00575 assure( false, CPL_ERROR_ILLEGAL_INPUT, "Unknown recipe: '%s'", recipe_id);
00576 }
00577 cleanup:
00578 return (cpl_error_get_code() != CPL_ERROR_NONE);
00579 }
00580
00581
00582
00600
00601 int
00602 uves_prop_par(int (*get_info)(cpl_pluginlist *),
00603 cpl_parameterlist *parameters,
00604 const char *recipe_id, const char *context)
00605 {
00606 cpl_plugin *plugin = NULL;
00607 cpl_pluginlist *list = NULL;
00608 cpl_recipe *subrecipe = NULL;
00609 const char *name = NULL;
00610 int status;
00611
00612
00613 if (get_info == NULL)
00614 {
00615 FAIL(-1, CPL_ERROR_NULL_INPUT, "Null function pointer");
00616 }
00617
00618 if (parameters == NULL)
00619 {
00620 FAIL(-1, CPL_ERROR_NULL_INPUT, "Null parameter list");
00621 }
00622
00623 if (recipe_id == NULL)
00624 {
00625 FAIL(-1, CPL_ERROR_NULL_INPUT, "Null recipe id");
00626 }
00627
00628
00629 list = cpl_pluginlist_new();
00630 status = get_info(list);
00631
00632 if (status != 0)
00633 {
00634 cpl_pluginlist_delete(list);
00635 FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Could not get info about recipe");
00636 }
00637
00638
00639 if ((plugin = cpl_pluginlist_get_first(list)) == NULL)
00640 {
00641 cpl_pluginlist_delete(list);
00642 FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Error getting plugin");
00643 }
00644 if (cpl_plugin_get_name(plugin) == NULL) {
00645 cpl_pluginlist_delete(list);
00646 FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Plugin name is NULL");
00647 }
00648 name = cpl_strdup(cpl_plugin_get_name(plugin));
00649
00650 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE)
00651 {
00652 cpl_pluginlist_delete(list);
00653 FAIL(-1, CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");
00654 }
00655 subrecipe = (cpl_recipe *) plugin;
00656
00657
00658 if( cpl_plugin_get_init(plugin)(plugin) != 0)
00659 {
00660 cpl_plugin_get_deinit(plugin)(plugin);
00661 cpl_pluginlist_delete(list);
00662 FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Error getting '%s' parameter list",
00663 name);
00664 }
00665
00666 if (subrecipe->parameters == NULL)
00667 {
00668 cpl_plugin_get_deinit(plugin)(plugin);
00669 cpl_pluginlist_delete(list);
00670 FAIL(-1, CPL_ERROR_NULL_INPUT, "Recipe '%s' returned NULL parameter list",
00671 name);
00672 }
00673
00674 if (propagate(cpl_plugin_get_name(plugin), subrecipe->parameters, parameters, recipe_id, context) != 0)
00675 {
00676 cpl_plugin_get_deinit(plugin)(plugin);
00677 cpl_pluginlist_delete(list);
00678 FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT, "Error propagating parameters from recipe '%s'",
00679 name);
00680 }
00681
00682 cpl_plugin_get_deinit(plugin)(plugin);
00683 cpl_pluginlist_delete(list);
00684
00685 return 0;
00686 }
00687
00688
00694
00695 int
00696 uves_propagate_parameters(const char *subrecipe,
00697 cpl_parameterlist *parameters,
00698 const char *recipe_id, const char *context)
00699 {
00700 if (subrecipe == NULL) {
00701 FAIL(-1, CPL_ERROR_NULL_INPUT, "Null subrecipe id");
00702 }
00703
00704 if (strcmp(subrecipe, make_str(UVES_PHYSMOD_ID) ) == 0) return uves_prop_par(&uves_physmod_get_info, parameters, recipe_id, context);
00705 else if (strcmp(subrecipe, make_str(UVES_ORDERPOS_ID)) == 0) return uves_prop_par(&uves_orderpos_get_info, parameters, recipe_id, context);
00706 else if (strcmp(subrecipe, make_str(UVES_MBIAS_ID) ) == 0) return uves_prop_par(&uves_mbias_get_info, parameters, recipe_id, context);
00707 else if (strcmp(subrecipe, make_str(UVES_MDARK_ID) ) == 0) return uves_prop_par(&uves_mdark_get_info, parameters, recipe_id, context);
00708 else if (strcmp(subrecipe, make_str(UVES_MFLAT_ID) ) == 0) return uves_prop_par(&uves_mflat_get_info, parameters, recipe_id, context);
00709 else if (strcmp(subrecipe, make_str(UVES_WAVECAL_ID) ) == 0) return uves_prop_par(&uves_wavecal_get_info, parameters, recipe_id, context);
00710 else if (strcmp(subrecipe, make_str(UVES_RESPONSE_ID)) == 0) return uves_prop_par(&uves_response_get_info, parameters, recipe_id, context);
00711 else if (strcmp(subrecipe, make_str(UVES_SCIRED_ID) ) == 0) return uves_prop_par(&uves_scired_get_info, parameters, recipe_id, context);
00712 else if (strcmp(subrecipe, make_str(UVES_REDCHAIN_ID)) == 0) return uves_prop_par(&uves_redchain_get_info, parameters, recipe_id, context);
00713 else {
00714 FAIL(-1, CPL_ERROR_DATA_NOT_FOUND, "Unknown recipe: '%s'", subrecipe);
00715 }
00716 }
00717
00718
00763
00764
00765 int
00766 uves_propagate_parameters_step(const char *step_id,
00767 cpl_parameterlist *parameters,
00768 const char *recipe_id, const char *context)
00769 {
00770 cpl_parameterlist *subparameters = NULL;
00771 cpl_parameterlist *(*get_parameters)(void) = NULL;
00772
00773
00774
00775 if (step_id == NULL)
00776 {
00777 FAIL(-1, CPL_ERROR_NULL_INPUT, "Null parameter list");
00778 }
00779
00780 if (parameters == NULL)
00781 {
00782 FAIL(-1, CPL_ERROR_NULL_INPUT, "Null parameter list");
00783 }
00784
00785 if (recipe_id == NULL)
00786 {
00787 FAIL(-1, CPL_ERROR_NULL_INPUT, "Null recipe id");
00788 }
00789
00790
00791
00792 if (strcmp(step_id, UVES_BACKSUB_ID ) == 0) {
00793 get_parameters = uves_backsub_define_parameters;
00794 } else if (strcmp(step_id, UVES_QCDARK_ID ) == 0) {
00795 get_parameters = uves_qcdark_define_parameters;
00796 } else if (strcmp(step_id, UVES_EXTRACT_ID ) == 0) {
00797 get_parameters = uves_extract_define_parameters;
00798 } else if (strcmp(step_id, UVES_REBIN_ID ) == 0) {
00799 get_parameters = uves_rebin_define_parameters;
00800 } else if (strcmp(step_id, UVES_REDUCE_ID ) == 0) {
00801 get_parameters = uves_reduce_define_parameters;
00802 } else {
00803 FAIL(-1, CPL_ERROR_DATA_NOT_FOUND, "Unknown sub-step: '%s'", step_id);
00804 }
00805
00806
00807 if( (subparameters = get_parameters()) == NULL )
00808 {
00809 FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Error getting '%s' parameter list", step_id);
00810 }
00811
00812 if ( propagate(step_id, subparameters, parameters, recipe_id, context) != 0)
00813 {
00814 cpl_parameterlist_delete(subparameters);
00815 FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT, "Error propagating '%s' parameters", step_id);
00816 }
00817
00818 cpl_parameterlist_delete(subparameters);
00819 return 0;
00820 }
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 static cpl_parameter *
00835 create_parameter_enum_int(const char *name, cpl_type type,
00836 const char *description,
00837 const char *context,
00838 int default_value, int size,
00839 int *values)
00840 {
00841
00842
00843 cpl_parameter *result = NULL;
00844
00845 if (! (1 <= size && size <= 10))
00846 {
00847 cpl_msg_error(__func__, "Unsupported enumeration size: %d (max is 10)", size);
00848 return NULL;
00849 }
00850
00851 switch(size)
00852 {
00853 case 1:
00854 uves_parameter_new_enum(result, name,
00855 type,
00856 description,
00857 context,
00858 default_value, size,
00859 values[0]);
00860 break;
00861 case 2:
00862 uves_parameter_new_enum(result, name,
00863 type,
00864 description,
00865 context,
00866 default_value, size,
00867 values[0],
00868 values[1]);
00869 break;
00870 case 3:
00871 uves_parameter_new_enum(result, name,
00872 type,
00873 description,
00874 context,
00875 default_value, size,
00876 values[0],
00877 values[1],
00878 values[2]);
00879 break;
00880 case 4:
00881 uves_parameter_new_enum(result, name,
00882 type,
00883 description,
00884 context,
00885 default_value, size,
00886 values[0],
00887 values[1],
00888 values[2],
00889 values[3]);
00890 break;
00891 case 5:
00892 uves_parameter_new_enum(result, name,
00893 type,
00894 description,
00895 context,
00896 default_value, size,
00897 values[0],
00898 values[1],
00899 values[2],
00900 values[3],
00901 values[4]);
00902 break;
00903 case 6:
00904 uves_parameter_new_enum(result, name,
00905 type,
00906 description,
00907 context,
00908 default_value, size,
00909 values[0],
00910 values[1],
00911 values[2],
00912 values[3],
00913 values[4],
00914 values[5]);
00915 break;
00916 case 7:
00917 uves_parameter_new_enum(result, name,
00918 type,
00919 description,
00920 context,
00921 default_value, size,
00922 values[0],
00923 values[1],
00924 values[2],
00925 values[3],
00926 values[4],
00927 values[5],
00928 values[6]);
00929 break;
00930 case 8:
00931 uves_parameter_new_enum(result, name,
00932 type,
00933 description,
00934 context,
00935 default_value, size,
00936 values[0],
00937 values[1],
00938 values[2],
00939 values[3],
00940 values[4],
00941 values[5],
00942 values[6],
00943 values[7]);
00944 break;
00945 case 9:
00946 uves_parameter_new_enum(result, name,
00947 type,
00948 description,
00949 context,
00950 default_value, size,
00951 values[0],
00952 values[1],
00953 values[2],
00954 values[3],
00955 values[4],
00956 values[5],
00957 values[6],
00958 values[7],
00959 values[8]);
00960 break;
00961 case 10:
00962 uves_parameter_new_enum(result, name,
00963 type,
00964 description,
00965 context,
00966 default_value, size,
00967 values[0],
00968 values[1],
00969 values[2],
00970 values[3],
00971 values[4],
00972 values[5],
00973 values[6],
00974 values[7],
00975 values[8],
00976 values[9]);
00977 break;
00978 }
00979 return result;
00980 }
00981 static cpl_parameter *
00982 create_parameter_enum_double(const char *name, cpl_type type,
00983 const char *description,
00984 const char *context, double default_value,
00985 int size, double *values)
00986 {
00987
00988
00989 cpl_parameter *result = NULL;
00990
00991 if (! (1 <= size && size <= 10))
00992 {
00993 cpl_msg_error(__func__, "Unsupported enumeration size: %d (max is 10)", size);
00994 return NULL;
00995 }
00996
00997 switch(size)
00998 {
00999 case 1:
01000 uves_parameter_new_enum(result, name,
01001 type,
01002 description,
01003 context,
01004 default_value, size,
01005 values[0]);
01006 break;
01007 case 2:
01008 uves_parameter_new_enum(result, name,
01009 type,
01010 description,
01011 context,
01012 default_value, size,
01013 values[0],
01014 values[1]);
01015 break;
01016 case 3:
01017 uves_parameter_new_enum(result, name,
01018 type,
01019 description,
01020 context,
01021 default_value, size,
01022 values[0],
01023 values[1],
01024 values[2]);
01025 break;
01026 case 4:
01027 uves_parameter_new_enum(result, name,
01028 type,
01029 description,
01030 context,
01031 default_value, size,
01032 values[0],
01033 values[1],
01034 values[2],
01035 values[3]);
01036 break;
01037 case 5:
01038 uves_parameter_new_enum(result, name,
01039 type,
01040 description,
01041 context,
01042 default_value, size,
01043 values[0],
01044 values[1],
01045 values[2],
01046 values[3],
01047 values[4]);
01048 break;
01049 case 6:
01050 uves_parameter_new_enum(result, name,
01051 type,
01052 description,
01053 context,
01054 default_value, size,
01055 values[0],
01056 values[1],
01057 values[2],
01058 values[3],
01059 values[4],
01060 values[5]);
01061 break;
01062 case 7:
01063 uves_parameter_new_enum(result, name,
01064 type,
01065 description,
01066 context,
01067 default_value, size,
01068 values[0],
01069 values[1],
01070 values[2],
01071 values[3],
01072 values[4],
01073 values[5],
01074 values[6]);
01075 break;
01076 case 8:
01077 uves_parameter_new_enum(result, name,
01078 type,
01079 description,
01080 context,
01081 default_value, size,
01082 values[0],
01083 values[1],
01084 values[2],
01085 values[3],
01086 values[4],
01087 values[5],
01088 values[6],
01089 values[7]);
01090 break;
01091 case 9:
01092 uves_parameter_new_enum(result, name,
01093 type,
01094 description,
01095 context,
01096 default_value, size,
01097 values[0],
01098 values[1],
01099 values[2],
01100 values[3],
01101 values[4],
01102 values[5],
01103 values[6],
01104 values[7],
01105 values[8]);
01106 break;
01107 case 10:
01108 uves_parameter_new_enum(result, name,
01109 type,
01110 description,
01111 context,
01112 default_value, size,
01113 values[0],
01114 values[1],
01115 values[2],
01116 values[3],
01117 values[4],
01118 values[5],
01119 values[6],
01120 values[7],
01121 values[8],
01122 values[9]);
01123 break;
01124 }
01125 return result;
01126 }
01127 static cpl_parameter *
01128 create_parameter_enum_string(const char *name, cpl_type type,
01129 const char *description,
01130 const char *context,
01131 const char *default_value,
01132 int size, const char **values)
01133 {
01134
01135
01136 cpl_parameter *result = NULL;
01137
01138 if (! (1 <= size && size <= 10))
01139 {
01140 cpl_msg_error(__func__, "Unsupported enumeration size: %d (max is 10)", size);
01141 return NULL;
01142 }
01143
01144 switch(size)
01145 {
01146 case 1:
01147 uves_parameter_new_enum(result, name,
01148 type,
01149 description,
01150 context,
01151 default_value, size,
01152 values[0]);
01153 break;
01154 case 2:
01155 uves_parameter_new_enum(result, name,
01156 type,
01157 description,
01158 context,
01159 default_value, size,
01160 values[0],
01161 values[1]);
01162 break;
01163 case 3:
01164 uves_parameter_new_enum(result, name,
01165 type,
01166 description,
01167 context,
01168 default_value, size,
01169 values[0],
01170 values[1],
01171 values[2]);
01172 break;
01173 case 4:
01174 uves_parameter_new_enum(result, name,
01175 type,
01176 description,
01177 context,
01178 default_value, size,
01179 values[0],
01180 values[1],
01181 values[2],
01182 values[3]);
01183 break;
01184 case 5:
01185 uves_parameter_new_enum(result, name,
01186 type,
01187 description,
01188 context,
01189 default_value, size,
01190 values[0],
01191 values[1],
01192 values[2],
01193 values[3],
01194 values[4]);
01195 break;
01196 case 6:
01197 uves_parameter_new_enum(result, name,
01198 type,
01199 description,
01200 context,
01201 default_value, size,
01202 values[0],
01203 values[1],
01204 values[2],
01205 values[3],
01206 values[4],
01207 values[5]);
01208 break;
01209 case 7:
01210 uves_parameter_new_enum(result, name,
01211 type,
01212 description,
01213 context,
01214 default_value, size,
01215 values[0],
01216 values[1],
01217 values[2],
01218 values[3],
01219 values[4],
01220 values[5],
01221 values[6]);
01222 break;
01223 case 8:
01224 uves_parameter_new_enum(result, name,
01225 type,
01226 description,
01227 context,
01228 default_value, size,
01229 values[0],
01230 values[1],
01231 values[2],
01232 values[3],
01233 values[4],
01234 values[5],
01235 values[6],
01236 values[7]);
01237 break;
01238 case 9:
01239 uves_parameter_new_enum(result, name,
01240 type,
01241 description,
01242 context,
01243 default_value, size,
01244 values[0],
01245 values[1],
01246 values[2],
01247 values[3],
01248 values[4],
01249 values[5],
01250 values[6],
01251 values[7],
01252 values[8]);
01253 break;
01254 case 10:
01255 uves_parameter_new_enum(result, name,
01256 type,
01257 description,
01258 context,
01259 default_value, size,
01260 values[0],
01261 values[1],
01262 values[2],
01263 values[3],
01264 values[4],
01265 values[5],
01266 values[6],
01267 values[7],
01268 values[8],
01269 values[9]);
01270 break;
01271 }
01272 return result;
01273 }
01274
01275
01276
01312
01313
01314 static int
01315 propagate(const char *substep_id, const cpl_parameterlist *sub_parameters,
01316 cpl_parameterlist *parent_parameters,
01317 const char *parent_id, const char *context)
01318 {
01319 const cpl_parameter *p = NULL;
01320
01321
01322
01323
01324
01325
01326 for (p = cpl_parameterlist_get_first_const(sub_parameters);
01327 p != NULL;
01328 p = cpl_parameterlist_get_next_const(sub_parameters) )
01329 {
01330 const char *name = cpl_parameter_get_name(p);
01331 const char *description = cpl_parameter_get_help(p);
01332 const char *subcontext = cpl_parameter_get_context(p);
01333 const char *alias = cpl_parameter_get_alias(p,
01334 CPL_PARAMETER_MODE_CLI);
01335 cpl_parameter_class class = cpl_parameter_get_class(p);
01336 cpl_type type = cpl_parameter_get_type(p);
01337
01338
01339
01340
01341
01342
01343
01344 {
01345 const char *S;
01346
01347 if (strstr(name, "uves.") == name)
01348 {
01349 S = "uves";
01350 }
01351 else
01352 {
01353 S = substep_id;
01354
01355
01356 if (strstr(name, S) != name)
01357 {
01358 FAIL(-1, CPL_ERROR_ILLEGAL_INPUT,
01359 "Recipe id '%s' is not prefix of parameter name '%s'",
01360 S, name);
01361 }
01362 }
01363
01364
01365 if (strstr(subcontext, S) != subcontext)
01366 {
01367 FAIL(-1, CPL_ERROR_ILLEGAL_INPUT,
01368 "Recipe id '%s' is not prefix of parameter context '%s'",
01369 S, subcontext);
01370 }
01371
01372
01373 if (strstr(name, subcontext) != name)
01374 {
01375 FAIL(-1, CPL_ERROR_ILLEGAL_INPUT,
01376 "Parameter context '%s' is not prefix of parameter name '%s'",
01377 subcontext, name);
01378 }
01379 }
01380
01381 if (strcmp(subcontext, "uves") != 0)
01382 {
01383 int enum_size;
01384
01385 cpl_parameter *new_par = NULL;
01386 char *new_name;
01387 char *new_context;
01388 char *new_alias;
01389
01390 if (context == NULL)
01391 {
01392 new_name = uves_sprintf("%s.%s", parent_id, name);
01393 new_context = uves_sprintf("%s", parent_id);
01394 if (alias != NULL)
01395 {
01396 new_alias = uves_sprintf("%s.%s", substep_id, alias);
01397 }
01398 else
01399 {
01400 new_alias = NULL;
01401 }
01402 }
01403 else
01404 {
01405 new_name = uves_sprintf("%s.%s.%s", parent_id, context, name);
01406
01407 new_context = uves_sprintf("%s.%s", parent_id, context);
01408
01409 if (alias != NULL)
01410 {
01411 new_alias = uves_sprintf("%s.%s.%s",
01412 context, substep_id, alias);
01413
01414 }
01415 else
01416 {
01417 new_alias = NULL;
01418 }
01419 }
01420
01421 if (new_name == NULL || new_context == NULL)
01422 {
01423 if (new_name != NULL) cpl_free(new_name);
01424 if (new_context != NULL) cpl_free(new_context);
01425 if (new_alias != NULL) cpl_free(new_alias);
01426 FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT, "Memory allocation failed");
01427 }
01428
01429
01430
01431 if (class != CPL_PARAMETER_CLASS_VALUE &&
01432 class != CPL_PARAMETER_CLASS_RANGE &&
01433 class != CPL_PARAMETER_CLASS_ENUM)
01434 {
01435 cpl_free(new_name);
01436 cpl_free(new_context);
01437 if (new_alias != NULL) cpl_free(new_alias);
01438 FAIL(-1, CPL_ERROR_TYPE_MISMATCH,
01439 "Unrecognized class of parameter '%s'", name);
01440 }
01441
01442 if (type != CPL_TYPE_BOOL &&
01443 type != CPL_TYPE_INT &&
01444 type != CPL_TYPE_DOUBLE &&
01445 type != CPL_TYPE_STRING)
01446 {
01447 cpl_free(new_name);
01448 cpl_free(new_context);
01449 if (new_alias != NULL) cpl_free(new_alias);
01450 FAIL(-1, CPL_ERROR_UNSUPPORTED_MODE, "Unsupported type: %s",
01451 uves_tostring_cpl_type(type));
01452 }
01453
01454
01455 switch (class)
01456 {
01457 case CPL_PARAMETER_CLASS_VALUE:
01458 switch (type)
01459 {
01460 case CPL_TYPE_BOOL:
01461 uves_parameter_new_value(new_par, new_name,
01462 type,
01463 description,
01464 new_context,
01465 cpl_parameter_get_default_bool(p));
01466 break;
01467
01468 case CPL_TYPE_INT:
01469 uves_parameter_new_value(new_par, new_name,
01470 type,
01471 description,
01472 new_context,
01473 cpl_parameter_get_default_int(p));
01474 break;
01475
01476 case CPL_TYPE_DOUBLE:
01477 uves_parameter_new_value(new_par, new_name,
01478 type,
01479 description,
01480 new_context,
01481 cpl_parameter_get_default_double(p));
01482 break;
01483 case CPL_TYPE_STRING:
01484 uves_parameter_new_value(new_par, new_name,
01485 type,
01486 description,
01487 new_context,
01488 cpl_parameter_get_default_string(p));
01489 break;
01490 default:
01491 break;
01492 }
01493
01494 break;
01495
01496 case CPL_PARAMETER_CLASS_RANGE:
01497
01498 switch (type)
01499 {
01500 int min_int, max_int;
01501 double min_double, max_double;
01502
01503 case CPL_TYPE_INT:
01504 min_int = cpl_parameter_get_range_min_int(p);
01505 max_int = cpl_parameter_get_range_max_int(p);
01506
01507 uves_parameter_new_range(new_par, new_name,
01508 type,
01509 description,
01510 new_context,
01511 cpl_parameter_get_default_int(p),
01512 min_int, max_int);
01513 break;
01514
01515 case CPL_TYPE_DOUBLE:
01516 min_double = cpl_parameter_get_range_min_double(p);
01517 max_double = cpl_parameter_get_range_max_double(p);
01518
01519 uves_parameter_new_range(new_par, new_name,
01520 type,
01521 description,
01522 new_context,
01523 cpl_parameter_get_default_double(p),
01524 min_double, max_double);
01525 break;
01526 default:
01527 break;
01528 }
01529
01530 break;
01531
01532 case CPL_PARAMETER_CLASS_ENUM:
01533 enum_size = cpl_parameter_get_enum_size(p);
01534
01535
01536 switch (type)
01537 {
01538 int *values_int;
01539 double *values_double;
01540 const char **values_string;
01541 int i;
01542
01543 case CPL_TYPE_INT:
01544 if ( (values_int = cpl_malloc(sizeof(int) * enum_size))
01545 == NULL)
01546 {
01547 cpl_free(new_name);
01548 cpl_free(new_context);
01549 if (new_alias != NULL) cpl_free(new_alias);
01550 FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT,
01551 "Memory allocation failed");
01552 }
01553 for (i = 0; i < enum_size; i++)
01554 {
01555 values_int[i] = cpl_parameter_get_enum_int(p, i);
01556 }
01557
01558 new_par = create_parameter_enum_int(
01559 new_name,
01560 type,
01561 description,
01562 new_context,
01563 cpl_parameter_get_default_int(p),
01564 enum_size,
01565 values_int);
01566 cpl_free(values_int);
01567 break;
01568
01569 case CPL_TYPE_DOUBLE:
01570 if ( (values_double =
01571 cpl_malloc(sizeof(double) * enum_size)) == NULL)
01572 {
01573 cpl_free(new_name);
01574 cpl_free(new_context);
01575 if (new_alias != NULL) cpl_free(new_alias);
01576 FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT,
01577 "Memory allocation failed");
01578 }
01579 for (i = 0; i < enum_size; i++)
01580 {
01581 values_double[i] = cpl_parameter_get_enum_double(p, i);
01582 }
01583
01584 new_par = create_parameter_enum_double(
01585 new_name,
01586 type,
01587 description,
01588 new_context,
01589 cpl_parameter_get_default_double(p),
01590 enum_size,
01591 values_double);
01592 cpl_free(values_double);
01593
01594 break;
01595
01596 case CPL_TYPE_STRING:
01597 if ( (values_string =
01598 cpl_malloc(sizeof(char *) * enum_size)) == NULL)
01599 {
01600 cpl_free(new_name);
01601 cpl_free(new_context);
01602 if (new_alias != NULL) cpl_free(new_alias);
01603 FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT,
01604 "Memory allocation failed");
01605 }
01606 for (i = 0; i < enum_size; i++)
01607 {
01608 values_string[i] = cpl_parameter_get_enum_string(p, i);
01609 }
01610
01611 new_par = create_parameter_enum_string(
01612 new_name,
01613 type,
01614 description,
01615 new_context,
01616 cpl_parameter_get_default_string(p),
01617 enum_size,
01618 values_string);
01619 cpl_free(values_string);
01620
01621 break;
01622
01623 default:
01624 break;
01625
01626 }
01627
01628 break;
01629
01630 default:
01631 break;
01632
01633 }
01634
01635 if (new_par == NULL)
01636 {
01637 cpl_free(new_name);
01638 cpl_free(new_context);
01639 if (new_alias != NULL) cpl_free(new_alias);
01640 FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT,
01641 "Propagation of parameter '%s' failed",
01642 name);
01643 }
01644
01645
01646 if (alias != NULL)
01647 {
01648 cpl_parameter_set_alias(new_par, CPL_PARAMETER_MODE_CLI, new_alias);
01649 }
01650
01651
01652 cpl_parameterlist_append(parent_parameters, new_par);
01653
01654 cpl_free(new_name);
01655 cpl_free(new_context);
01656 if (new_alias != NULL) cpl_free(new_alias);
01657
01658 }
01659
01660 }
01661
01662 return (cpl_error_get_code() != CPL_ERROR_NONE);
01663 }
01664
01665