From ec5d97160f38afbc6b548ff3a38023e59b47812a Mon Sep 17 00:00:00 2001 From: Mahder Gebremedhin Date: Thu, 19 Aug 2021 16:38:45 +0200 Subject: [PATCH] Allow repetition of simulation flags. (#7784) - There are 4 policies for handling repeated flags. - `FLAG_REPEAT_POLICY_FORBID` - `FLAG_REPEAT_POLICY_IGNORE` - `FLAG_REPEAT_POLICY_REPLACE` - `FLAG_REPEAT_POLICY_COMBINE` The first three are implemented. Combining flags (`FLAG_REPEAT_POLICY_COMBINE)` is not yet implemented. Will be added later. _Maybe we need to add `FLAG_REPEAT_POLICY_IGNORE_SILENT` for flags like `-help`_. - If an `Option` (with value) is specified multiple times: Forbid: Prints an error and terminates flag/option processing. Ignore: Prints a warning and ignores the new value. Replace: Prints a warning and uses the new value. Combine: Prints a warning and combines all values (NOT YET IMPLEMENTED). - If a `flag` is specified multiple times: Forbid: Prints an error and terminates flag/option processing. Ignore: Prints a warning and ignores the repeated flags. Replace: Invalid for `flags`. Print error and terminate. Combine: Invalid for `flags`. Print error and terminate. - All flags/options are now set to `FLAG_REPEAT_POLICY_FORBID` except for `-help` and `-lv` which are both set to `FLAG_REPEAT_POLICY_REPLACE` for now. Please feel free to update the policies for the flags if you know what should be the best way to handle them each. --- .../SimulationRuntime/c/simulation/options.c | 122 +++++++++++++++--- .../c/util/simulation_options.c | 119 +++++++++++++++++ .../c/util/simulation_options.h | 8 ++ 3 files changed, 233 insertions(+), 16 deletions(-) diff --git a/OMCompiler/SimulationRuntime/c/simulation/options.c b/OMCompiler/SimulationRuntime/c/simulation/options.c index 73f2374bbf2..6b895bce518 100644 --- a/OMCompiler/SimulationRuntime/c/simulation/options.c +++ b/OMCompiler/SimulationRuntime/c/simulation/options.c @@ -40,6 +40,9 @@ static int optionSet(const char *option, int argc, char** argv); /* -f=value static const char* getOption(const char*, int, char **); /* -f=value; returns NULL if not found */ static const char* getFlagValue(const char *, int , char **); /* -f value; returns NULL if not found */ +static int handle_repeated_option(int flag_index, char **argv_loc, int is_sticky); +static int handle_repeated_flag(int flag_index); + int omc_flag[FLAG_MAX]; const char *omc_flagValue[FLAG_MAX]; @@ -104,13 +107,17 @@ int checkCommandLineArguments(int argc, char **argv) { if((FLAG_TYPE[j] == FLAG_TYPE_FLAG) && flagSet(FLAG_NAME[j], 1, argv+i)) { - if(omc_flag[j]) - { - errorStreamPrint(LOG_STDOUT, 0, "each command line option can only be used once: %s", argv[i]); + // Flag is not yet set. + if(!omc_flag[j]) { + omc_flag[j] = 1; + } + // Flag is already specified earlier. Check repetition policy. + else if(!handle_repeated_flag(j)) { + // repetition is invlaid for this Flag return 1; } - omc_flag[j] = 1; + // All good. found=1; #ifdef USE_DEBUG_OUTPUT @@ -121,16 +128,20 @@ int checkCommandLineArguments(int argc, char **argv) } else if((FLAG_TYPE[j] == FLAG_TYPE_OPTION) && flagSet(FLAG_NAME[j], 1, argv+i) && (i+1 < argc)) { - if(omc_flag[j]) - { - errorStreamPrint(LOG_STDOUT, 0, "each command line option can only be used once: %s", argv[i]); + // Option is not yet set. + if(!omc_flag[j]) { + omc_flag[j] = 1; + omc_flagValue[j] = (char*)getFlagValue(FLAG_NAME[j], 1, argv+i); + } + // Option is already specified earlier. Check repetition policy. + else if(!handle_repeated_option(j, argv+i, 0 /*Not sticky*/)) { + // repetition is invlaid for this option return 1; } - omc_flag[j] = 1; - omc_flagValue[j] = (char*)getFlagValue(FLAG_NAME[j], 1, argv+i); + // All good. + found = 1; i++; - found=1; #ifdef USE_DEBUG_OUTPUT debugStreamPrint(LOG_STDOUT, 0, "-%s %s", FLAG_NAME[j], omc_flagValue[j]); @@ -140,15 +151,20 @@ int checkCommandLineArguments(int argc, char **argv) } else if((FLAG_TYPE[j] == FLAG_TYPE_OPTION) && optionSet(FLAG_NAME[j], 1, argv+i)) { - if(omc_flag[j]) - { - errorStreamPrint(LOG_STDOUT, 0, "each command line option can only be used once: %s", argv[i]); + + // Option is not yet set. + if (!omc_flag[j]) { + omc_flag[j] = 1; + omc_flagValue[j] = (char*)getOption(FLAG_NAME[j], 1, argv+i); + } + // Option is already specified earlier. Check repetition policy. + else if (!handle_repeated_option(j, argv+i, 1 /*Sticky*/)) { + // repetition is invlaid for this option return 1; } - omc_flag[j] = 1; - omc_flagValue[j] = (char*)getOption(FLAG_NAME[j], 1, argv+i); - found=1; + // All good. + found = 1; #ifdef USE_DEBUG_OUTPUT debugStreamPrint(LOG_STDOUT, 0, "-%s=%s", FLAG_NAME[j], omc_flagValue[j]); @@ -174,6 +190,80 @@ int checkCommandLineArguments(int argc, char **argv) return 0; } +static int handle_repeated_flag(int flag_index) { + + const char* flag_name = FLAG_NAME[flag_index]; + flag_repeat_policy repeat_policy = FLAG_REPEAT_POLICIES[flag_index]; + + if(repeat_policy == FLAG_REPEAT_POLICY_IGNORE) { + warningStreamPrint(LOG_STDOUT, 0, "Command line flag '%s' specified again. Ignoring." + , flag_name); + return 1; + } + + if(repeat_policy == FLAG_REPEAT_POLICY_FORBID) { + errorStreamPrint(LOG_STDOUT, 0, "Command line flag '%s' can be specified only once.", flag_name); + return 0; + } + + + if(repeat_policy == FLAG_REPEAT_POLICY_REPLACE) { + errorStreamPrint(LOG_STDOUT, 0, "Command line flag %s is supposed to be replaced on repetition. This option does not apply for flags. Fix the repetition policy for the flag.", flag_name); + return 0; + } + + if(repeat_policy == FLAG_REPEAT_POLICY_COMBINE) { + errorStreamPrint(LOG_STDOUT, 0, "Command line flag %s is supposed to be combined on repetition. This option does not apply for flags. Fix the repetition policy for the flag.", flag_name); + return 0; + } + + errorStreamPrint(LOG_STDOUT, 0, "Error: Unknow repetition policy for command line flag %s.", flag_name); + return 0; +} + +static int handle_repeated_option(int flag_index, char **argv_loc, int is_sticky) { + + const char* flag_name = FLAG_NAME[flag_index]; + flag_repeat_policy repeat_policy = FLAG_REPEAT_POLICIES[flag_index]; + + const char* old_value = omc_flagValue[flag_index]; + + if(repeat_policy == FLAG_REPEAT_POLICY_IGNORE) { + warningStreamPrint(LOG_STDOUT, 0, "Command line option '%s' specified again. Keeping the first value '%s' and ignoring the rest." + , flag_name, old_value); + return 1; + } + + if(repeat_policy == FLAG_REPEAT_POLICY_FORBID) { + errorStreamPrint(LOG_STDOUT, 0, "Command line option '%s' can be specified only once.", flag_name); + return 0; + } + + + const char* new_value; + + if(is_sticky) // lv=LOG_STATS + new_value = (char*)getOption(flag_name, 1, argv_loc); + else // lv LOG_STATS + new_value = (char*)getFlagValue(flag_name, 1, argv_loc); + + if(repeat_policy == FLAG_REPEAT_POLICY_REPLACE) { + omc_flagValue[flag_index] = new_value; + warningStreamPrint(LOG_STDOUT, 0, "Command line option '%s' specified again. Value has been overriden from '%s' to '%s'." + , flag_name, old_value, new_value); + return 1; + } + + if(repeat_policy == FLAG_REPEAT_POLICY_COMBINE) { + errorStreamPrint(LOG_STDOUT, 0, "Command line option %s is supposed to be combined on repetition. This has not bee implemented yet", flag_name); + return 0; + } + + errorStreamPrint(LOG_STDOUT, 0, "Error: Unknow repetition policy for command line option %s.", flag_name); + return 0; + +} + static int flagSet(const char *option, int argc, char** argv) { int i; diff --git a/OMCompiler/SimulationRuntime/c/util/simulation_options.c b/OMCompiler/SimulationRuntime/c/util/simulation_options.c index b76af3fd13a..1ad8b672e2e 100644 --- a/OMCompiler/SimulationRuntime/c/util/simulation_options.c +++ b/OMCompiler/SimulationRuntime/c/util/simulation_options.c @@ -568,6 +568,125 @@ const char *FLAG_DETAILED_DESC[FLAG_MAX+1] = { "FLAG_MAX" }; +const flag_repeat_policy FLAG_REPEAT_POLICIES[FLAG_MAX] = { + FLAG_REPEAT_POLICY_FORBID, + + /* FLAG_ABORT_SLOW */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_ALARM */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_CLOCK */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_CPU */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_CSV_OSTEP */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_CVODE_ITER */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_CVODE_LMM */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_DATA_RECONCILE_Cx */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_DAE_MODE */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_DELTA_X_LINEARIZE */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_DELTA_X_SOLVER */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_EMBEDDED_SERVER */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_EMBEDDED_SERVER_PORT */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_MAT_SYNC */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_EMIT_PROTECTED */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_DATA_RECONCILE_Eps */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_F */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HELP */ FLAG_REPEAT_POLICY_REPLACE, + /* FLAG_HOMOTOPY_ADAPT_BEND */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_BACKTRACE_STRATEGY */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_H_EPS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_MAX_LAMBDA_STEPS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_MAX_NEWTON_STEPS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_MAX_TRIES */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_NEG_START_DIR */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_ON_FIRST_TRY */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NO_HOMOTOPY_ON_FIRST_TRY */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_TAU_DEC_FACTOR */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_TAU_DEC_FACTOR_PRED */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_TAU_INC_FACTOR */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_TAU_INC_THRESHOLD */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_TAU_MAX */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_TAU_MIN */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_HOMOTOPY_TAU_START */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IDA_MAXERRORTESTFAIL */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IDA_MAXNONLINITERS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IDA_MAXCONVFAILS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IDA_NONLINCONVCOEF */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IDA_LS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IDA_SCALING */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IDAS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IGNORE_HIDERESULT */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IIF */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IIM */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IIT */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_ILS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IMPRK_ORDER */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IMPRK_LS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_INITIAL_STEP_SIZE */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_INPUT_CSV */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_INPUT_FILE */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_INPUT_FILE_STATES */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_INPUT_PATH */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IPOPT_HESSE*/ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IPOPT_INIT*/ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IPOPT_JAC*/ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IPOPT_MAX_ITER */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_IPOPT_WARM_START */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_JACOBIAN */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_JACOBIAN_THREADS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_L */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_L_DATA_RECOVERY */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_LOG_FORMAT */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_LS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_LS_IPOPT */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_LSS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_LSS_MAX_DENSITY */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_LSS_MIN_SIZE */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_LV */ FLAG_REPEAT_POLICY_REPLACE, + /* FLAG_LV_TIME */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_MAX_BISECTION_ITERATIONS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_MAX_EVENT_ITERATIONS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_MAX_ORDER */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_MAX_STEP_SIZE */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_MEASURETIMEPLOTFORMAT */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NEWTON_FTOL */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NEWTON_MAX_STEP_FACTOR */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NEWTON_XTOL */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NEWTON_STRATEGY */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NLS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NLS_INFO */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NLS_LS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NLS_MAX_DENSITY */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NLS_MIN_SIZE */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NOEMIT */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NOEQUIDISTANT_GRID */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NOEQUIDISTANT_OUT_FREQ*/ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NOEQUIDISTANT_OUT_TIME*/ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NOEVENTEMIT */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NO_RESTART */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NO_ROOTFINDING */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NO_SCALING */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_NO_SUPPRESS_ALG */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_OPTDEBUGEJAC */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_OPTIMIZER_NP */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_OPTIMIZER_TGRID */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_OUTPUT */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_OUTPUT_PATH */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_OVERRIDE */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_OVERRIDE_FILE */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_PORT */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_R */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_DATA_RECONCILE */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_DATA_RECONCILE_BOUNDARY */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_RT */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_S */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_SINGLE_PRECISION */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_SOLVER_STEPS */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_STEADY_STATE */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_STEADY_STATE_TOL */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_DATA_RECONCILE_Sx */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_UP_HESSIAN */ FLAG_REPEAT_POLICY_FORBID, + /* FLAG_W */ FLAG_REPEAT_POLICY_FORBID, +}; + + const int FLAG_TYPE[FLAG_MAX] = { FLAG_TYPE_UNKNOWN, diff --git a/OMCompiler/SimulationRuntime/c/util/simulation_options.h b/OMCompiler/SimulationRuntime/c/util/simulation_options.h index 16fb2f6cbab..7d6fc62ad33 100644 --- a/OMCompiler/SimulationRuntime/c/util/simulation_options.h +++ b/OMCompiler/SimulationRuntime/c/util/simulation_options.h @@ -174,9 +174,17 @@ enum _FLAG_TYPE FLAG_TYPE_MAX }; +typedef enum { + FLAG_REPEAT_POLICY_FORBID = 0, + FLAG_REPEAT_POLICY_IGNORE, + FLAG_REPEAT_POLICY_REPLACE, + FLAG_REPEAT_POLICY_COMBINE +} flag_repeat_policy; + extern const char *FLAG_NAME[FLAG_MAX+1]; extern const char *FLAG_DESC[FLAG_MAX+1]; extern const char *FLAG_DETAILED_DESC[FLAG_MAX+1]; +extern const flag_repeat_policy FLAG_REPEAT_POLICIES[FLAG_MAX]; extern const int FLAG_TYPE[FLAG_MAX]; enum SOLVER_METHOD