This is an automated email from Gerrit. "Evgeniy Naydanov <evgeniy.nayda...@syntacore.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8643
-- gerrit commit ea77280ec5c1681c65601030e0bab09126c10c3c Author: Evgeniy Naydanov <evgeniy.nayda...@syntacore.com> Date: Fri Nov 29 17:44:50 2024 +0300 target: clean-up target configuration argument handling There were multiple issues with how `target create` and `<target_name> configure/cget` used to handle arguments: * `Jim_WrongNumArgs()` called with `argc == 0`, which causes a `JimPanic` if `JIM_DEBUG_PANIC` is defined Link: https://github.com/msteveb/jimtcl/blob/3a2cfdf696daa0d92c0f2e8d8fc1ff337ba99c62/jim.c#L11934 * In some cases `Jim_WrongNumArgs()` reported unhelpfull arguments making the message incorrect, e.g: ``` > openocd -c 'target create a_name' ... wrong # args: should be "a_name <name> <target_type> [<target_options> ...]" ``` Here the error message mentions both: the name of the target passed to `target create` (`a_name`) and `<name>`. To combat these issues a new function is introduced: `jim_getopt_wrong_num_args()`. The function wraps the call to `Jim_WrongNumArgs()` making these kinds of errors less likely. Change-Id: Ifb72e4df9a1da7f5da7945498ca4d9d139aa9562 Signed-off-by: Evgeniy Naydanov <evgeniy.nayda...@syntacore.com> diff --git a/src/helper/jim-nvp.c b/src/helper/jim-nvp.c index cdd4d34291..2125fdf369 100644 --- a/src/helper/jim-nvp.c +++ b/src/helper/jim-nvp.c @@ -23,6 +23,7 @@ #include "jim-nvp.h" #include <stdio.h> #include <string.h> +#include <assert.h> int jim_get_nvp(Jim_Interp *interp, Jim_Obj *objptr, const struct jim_nvp *nvp_table, const struct jim_nvp **result) @@ -258,6 +259,12 @@ void jim_getopt_nvp_unknown(struct jim_getopt_info *goi, const struct jim_nvp *n jim_set_result_nvp_unknown(goi->interp, NULL, goi->argv[-1], nvptable); } +void jim_getopt_wrong_num_args(const struct jim_getopt_info *goi, int argc, const char *msg) +{ + assert(argc > 0 && "Expecting a positive number of context arguments."); + Jim_WrongNumArgs(goi->interp, argc, goi->argv - argc, msg); +} + int jim_getopt_enum(struct jim_getopt_info *goi, const char *const *lookup, int *puthere) { int _safe; diff --git a/src/helper/jim-nvp.h b/src/helper/jim-nvp.h index 45af6c867f..e4edc49400 100644 --- a/src/helper/jim-nvp.h +++ b/src/helper/jim-nvp.h @@ -292,6 +292,23 @@ int jim_getopt_nvp(struct jim_getopt_info *goi, const struct jim_nvp *lookup, st */ void jim_getopt_nvp_unknown(struct jim_getopt_info *goi, const struct jim_nvp *lookup, int hadprefix); +/** Create an appropriate error message when there are missing arguments. + * + * \param goi - options info + * \param cntxt_args - number of arguments to prepend to the message + * \param expctd_args - optional string describing the missing arguments + * + * This function will set the "goi->interp->result" to a human readable error + * message containing the previous "cntxt_args" arguments (starting from + * "goi->argv[-cntxt_args]") and the "expctd_args" separated by a space + * character. + * + * "cntxt_args" should be positive to provide the neccessary context. + * + * "expctd_args" can be NULL if no more arguments are expected. + */ +void jim_getopt_wrong_num_args(const struct jim_getopt_info *goi, int cntxt_args, + const char *expctd_args); /** Remove argv[0] as Enum * diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 0dd538e8f2..ec187e2354 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -103,13 +103,24 @@ int rtos_create(struct jim_getopt_info *goi, struct target *target) Jim_Obj *res; int e; - if (!goi->is_configure && goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS"); - return JIM_ERR; + if (!goi->is_configure) { + if (goi->argc != 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + /*expctd_args*/ NULL); + return JIM_ERR; + } + Jim_SetResultString(goi->interp, + target->rtos ? target->rtos->type->name : "none", -1); + return JIM_OK; } os_free(target); + if (goi->argc == 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?name? ..."); + return JIM_ERR; + } e = jim_getopt_string(goi, &cp, NULL); if (e != JIM_OK) return e; diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 9f122070aa..342ad5c8ad 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2954,9 +2954,8 @@ static int aarch64_jim_configure(struct target *target, struct jim_getopt_info * pc->cti = cti; } else { if (goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, - goi->argc, goi->argv, - "NO PARAMS"); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + /*expctd_args*/ NULL); return JIM_ERR; } diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 0c7633beab..17f557d009 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -2432,7 +2432,7 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi, return JIM_OK; err_no_param: - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS"); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, /*expctd_args*/ NULL); return JIM_ERR; } diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index 88eec832ef..d3782f2682 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -512,13 +512,12 @@ static int cti_create(struct jim_getopt_info *goi) static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct jim_getopt_info goi; - jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - if (goi.argc < 2) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, - "<name> [<cti_options> ...]"); + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "<name> [<cti_options> ...]"); return JIM_ERR; } + struct jim_getopt_info goi; + jim_getopt_setup(&goi, interp, argc - 1, argv + 1); return cti_create(&goi); } diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 9f4afae743..b96ba5b0ae 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -418,13 +418,13 @@ err: static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct jim_getopt_info goi; - jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - if (goi.argc < 2) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, + if (argc < 3) { + Jim_WrongNumArgs(interp, argc, argv, "<name> [<dap_options> ...]"); return JIM_ERR; } + struct jim_getopt_info goi; + jim_getopt_setup(&goi, interp, argc - 1, argv + 1); return dap_create(&goi); } diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index c14fd5fc84..cfffeb0196 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -493,12 +493,14 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s case CFG_EVENT: if (goi->is_configure) { if (goi->argc < 2) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?"); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?event-name? ?EVENT-BODY?"); return JIM_ERR; } } else { if (goi->argc != 1) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?"); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?event-name?"); return JIM_ERR; } } @@ -550,7 +552,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s return JIM_OK; err_no_params: - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS"); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, /*expctd_args*/ NULL); return JIM_ERR; } @@ -559,13 +561,12 @@ static int jim_arm_tpiu_swo_configure(Jim_Interp *interp, int argc, Jim_Obj * co struct command *c = jim_to_command(interp); struct jim_getopt_info goi; - jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - goi.is_configure = !strcmp(c->name, "configure"); - if (goi.argc < 1) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, - "missing: -option ..."); + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "-option ..."); return JIM_ERR; } + jim_getopt_setup(&goi, interp, argc - 1, argv + 1); + goi.is_configure = !strcmp(c->name, "configure"); struct arm_tpiu_swo_object *obj = c->jim_handler_data; return arm_tpiu_swo_configure(&goi, obj); } diff --git a/src/target/stm8.c b/src/target/stm8.c index 2b3466dacb..47551eb536 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -1946,8 +1946,7 @@ static int stm8_jim_configure(struct target *target, struct jim_getopt_info *goi return e; if (goi->argc == 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, - "-blocksize ?bytes? ..."); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, "?bytes? ..."); return JIM_ERR; } @@ -1965,8 +1964,7 @@ static int stm8_jim_configure(struct target *target, struct jim_getopt_info *goi return e; if (goi->argc == 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, - "-flashstart ?address? ..."); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, "?address? ..."); return JIM_ERR; } @@ -1984,8 +1982,7 @@ static int stm8_jim_configure(struct target *target, struct jim_getopt_info *goi return e; if (goi->argc == 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, - "-flashend ?address? ..."); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, "?address? ..."); return JIM_ERR; } @@ -2003,8 +2000,7 @@ static int stm8_jim_configure(struct target *target, struct jim_getopt_info *goi return e; if (goi->argc == 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, - "-eepromstart ?address? ..."); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, "?address? ..."); return JIM_ERR; } @@ -2022,8 +2018,7 @@ static int stm8_jim_configure(struct target *target, struct jim_getopt_info *goi return e; if (goi->argc == 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, - "-eepromend ?address? ..."); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, "?address? ..."); return JIM_ERR; } @@ -2041,8 +2036,7 @@ static int stm8_jim_configure(struct target *target, struct jim_getopt_info *goi return e; if (goi->argc == 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, - "-optionstart ?address? ..."); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, "?address? ..."); return JIM_ERR; } @@ -2060,8 +2054,7 @@ static int stm8_jim_configure(struct target *target, struct jim_getopt_info *goi return e; if (goi->argc == 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, - "-optionend ?address? ..."); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, "?address? ..."); return JIM_ERR; } diff --git a/src/target/target.c b/src/target/target.c index 6c474899a4..d88841bbb8 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4944,9 +4944,8 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) } else { no_params: if (goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, - goi->argc, goi->argv, - "NO PARAMS"); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + /*expctd_args*/ NULL); return JIM_ERR; } } @@ -4956,7 +4955,8 @@ no_params: break; case TCFG_EVENT: if (goi->argc == 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ..."); + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?event-name? ..."); return JIM_ERR; } @@ -4966,78 +4966,87 @@ no_params: return e; } - if (goi->is_configure) { - if (goi->argc != 1) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?"); - return JIM_ERR; - } - } else { - if (goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?"); - return JIM_ERR; - } + struct target_event_action *teap; + + teap = target->event_action; + while (teap) { + if (teap->event == (enum target_event)n->value) + break; + teap = teap->next; } - { - struct target_event_action *teap; - - teap = target->event_action; - /* replace existing? */ - while (teap) { - if (teap->event == (enum target_event)n->value) - break; - teap = teap->next; + if (goi->is_configure) { + /* START_DEPRECATED_TPIU */ + if (n->value == TARGET_EVENT_TRACE_CONFIG) + LOG_TARGET_INFO(target, "DEPRECATED target event %s; " + "use TPIU events {pre,post}-{enable,disable}", n->name); + /* END_DEPRECATED_TPIU */ + + if (goi->argc == 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 2, + "?EVENT-BODY?"); + return JIM_ERR; } + e = jim_getopt_obj(goi, &o); + if (e != JIM_OK) + return e; - if (goi->is_configure) { - /* START_DEPRECATED_TPIU */ - if (n->value == TARGET_EVENT_TRACE_CONFIG) - LOG_INFO("DEPRECATED target event %s; use TPIU events {pre,post}-{enable,disable}", n->name); - /* END_DEPRECATED_TPIU */ - bool replace = true; + bool replace = true; + if (!teap) { + /* create new */ + teap = calloc(1, sizeof(*teap)); if (!teap) { - /* create new */ - teap = calloc(1, sizeof(*teap)); - replace = false; + LOG_ERROR("Out of memory!"); + return JIM_ERR; } - teap->event = n->value; - teap->interp = goi->interp; - jim_getopt_obj(goi, &o); - if (teap->body) - Jim_DecrRefCount(teap->interp, teap->body); - teap->body = Jim_DuplicateObj(goi->interp, o); - /* - * FIXME: - * Tcl/TK - "tk events" have a nice feature. - * See the "BIND" command. - * We should support that here. - * You can specify %X and %Y in the event code. - * The idea is: %T - target name. - * The idea is: %N - target number - * The idea is: %E - event name. - */ - Jim_IncrRefCount(teap->body); - - if (!replace) { - /* add to head of event list */ - teap->next = target->event_action; - target->event_action = teap; - } - Jim_SetEmptyResult(goi->interp); - } else { - /* get */ - if (!teap) - Jim_SetEmptyResult(goi->interp); - else - Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, teap->body)); + replace = false; } + teap->event = n->value; + teap->interp = goi->interp; + if (teap->body) + Jim_DecrRefCount(teap->interp, teap->body); + teap->body = Jim_DuplicateObj(goi->interp, o); + /* + * FIXME: + * Tcl/TK - "tk events" have a nice feature. + * See the "BIND" command. + * We should support that here. + * You can specify %X and %Y in the event code. + * The idea is: + * - %T: target name. + * - %E: event name. + */ + Jim_IncrRefCount(teap->body); + + if (!replace) { + /* add to head of event list */ + teap->next = target->event_action; + target->event_action = teap; + } + Jim_SetEmptyResult(goi->interp); + } else { + /* get */ + if (goi->argc != 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 2, + /*expctd_args*/ NULL); + return JIM_ERR; + } + if (!teap) + Jim_SetEmptyResult(goi->interp); + else + Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, teap->body)); } /* loop for more */ break; case TCFG_WORK_AREA_VIRT: if (goi->is_configure) { + if (goi->argc == 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?address? ..."); + return JIM_ERR; + } target_free_all_working_areas(target); e = jim_getopt_wide(goi, &w); if (e != JIM_OK) @@ -5054,6 +5063,11 @@ no_params: case TCFG_WORK_AREA_PHYS: if (goi->is_configure) { + if (goi->argc == 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?address? ..."); + return JIM_ERR; + } target_free_all_working_areas(target); e = jim_getopt_wide(goi, &w); if (e != JIM_OK) @@ -5070,6 +5084,11 @@ no_params: case TCFG_WORK_AREA_SIZE: if (goi->is_configure) { + if (goi->argc == 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?address? ..."); + return JIM_ERR; + } target_free_all_working_areas(target); e = jim_getopt_wide(goi, &w); if (e != JIM_OK) @@ -5085,6 +5104,11 @@ no_params: case TCFG_WORK_AREA_BACKUP: if (goi->is_configure) { + if (goi->argc == 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?0|1? ..."); + return JIM_ERR; + } target_free_all_working_areas(target); e = jim_getopt_wide(goi, &w); if (e != JIM_OK) @@ -5102,6 +5126,11 @@ no_params: case TCFG_ENDIAN: if (goi->is_configure) { + if (goi->argc == 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?endian? ..."); + return JIM_ERR; + } e = jim_getopt_nvp(goi, nvp_target_endian, &n); if (e != JIM_OK) { jim_getopt_nvp_unknown(goi, nvp_target_endian, 1); @@ -5123,6 +5152,11 @@ no_params: case TCFG_COREID: if (goi->is_configure) { + if (goi->argc == 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?number? ..."); + return JIM_ERR; + } e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; @@ -5147,6 +5181,11 @@ no_params: } target_free_all_working_areas(target); + if (goi->argc == 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?tap? ..."); + return JIM_ERR; + } e = jim_getopt_obj(goi, &o_t); if (e != JIM_OK) return e; @@ -5164,6 +5203,11 @@ no_params: break; case TCFG_DBGBASE: if (goi->is_configure) { + if (goi->argc == 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?address? ..."); + return JIM_ERR; + } e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; @@ -5200,6 +5244,11 @@ no_params: return JIM_ERR; } + if (goi->argc == 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?port_no? ..."); + return JIM_ERR; + } const char *s; e = jim_getopt_string(goi, &s, NULL); if (e != JIM_OK) @@ -5222,6 +5271,11 @@ no_params: return JIM_ERR; } + if (goi->argc == 0) { + jim_getopt_wrong_num_args(goi, /*cntxt_args*/ 1, + "?number? ..."); + return JIM_ERR; + } e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; @@ -5245,13 +5299,12 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a struct command *c = jim_to_command(interp); struct jim_getopt_info goi; - jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - goi.is_configure = !strcmp(c->name, "configure"); - if (goi.argc < 1) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, - "missing: -option ..."); + if (argc < 2) { + Jim_WrongNumArgs(interp, argc, argv, "-option ..."); return JIM_ERR; } + jim_getopt_setup(&goi, interp, argc - 1, argv + 1); + goi.is_configure = !strcmp(c->name, "configure"); struct command_context *cmd_ctx = current_command_context(interp); assert(cmd_ctx); struct target *target = get_current_target(cmd_ctx); @@ -6050,13 +6103,13 @@ COMMAND_HANDLER(handle_target_smp) static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct jim_getopt_info goi; - jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - if (goi.argc < 3) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, + if (argc < 4) { + Jim_WrongNumArgs(interp, 1, argv, "<name> <target_type> [<target_options> ...]"); return JIM_ERR; } + struct jim_getopt_info goi; + jim_getopt_setup(&goi, interp, argc - 1, argv + 1); return target_create(&goi); } --