From 61890e3dc3201ce38e5af7f6b561389a123448e0 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 3 Dec 2023 15:41:27 +0100 Subject: [PATCH] target: rewrite function target_configure() as COMMAND_HELPER The function target_configure() is used by the commands 'target create', 'configure' and 'cget', already rewritten as COMMAND_HANDLER. Rewrite the common function as COMMAND_HELPER. While there: - fix the check on arguments, even if it should be coded better; - keep jimtcl code for target_type::target_jim_configure() and for rtos_create(); these would be rewritten later on. Change-Id: I7e5699ca6d124e34d3b2199714e3ce584bfcce80 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8829 Tested-by: jenkins --- src/target/target.c | 434 +++++++++++++++++++++++--------------------- 1 file changed, 225 insertions(+), 209 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 4bd2f24cc..99481622d 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -214,8 +214,6 @@ static const struct nvp nvp_target_event[] = { { .name = NULL, .value = -1 } }; -static const struct jim_nvp *jim_nvp_target_event = (const struct jim_nvp *)nvp_target_event; - static const struct nvp nvp_target_state[] = { { .name = "unknown", .value = TARGET_UNKNOWN }, { .name = "running", .value = TARGET_RUNNING }, @@ -238,7 +236,7 @@ static const struct nvp nvp_target_debug_reason[] = { { .name = NULL, .value = -1 }, }; -static const struct jim_nvp nvp_target_endian[] = { +static const struct nvp nvp_target_endian[] = { { .name = "big", .value = TARGET_BIG_ENDIAN }, { .name = "little", .value = TARGET_LITTLE_ENDIAN }, { .name = "be", .value = TARGET_BIG_ENDIAN }, @@ -2844,8 +2842,7 @@ COMMAND_HANDLER(handle_targets_command) marker, target_name(target), target_type_name(target), - jim_nvp_value2name_simple(nvp_target_endian, - target->endianness)->name, + nvp_value2name(nvp_target_endian, target->endianness)->name, target->tap->dotted_name, state); } @@ -4859,7 +4856,7 @@ enum target_cfg_param { TCFG_GDB_MAX_CONNECTIONS, }; -static struct jim_nvp nvp_config_opts[] = { +static struct nvp nvp_config_opts[] = { { .name = "-type", .value = TCFG_TYPE }, { .name = "-event", .value = TCFG_EVENT }, { .name = "-work-area-virt", .value = TCFG_WORK_AREA_VIRT }, @@ -4877,78 +4874,71 @@ static struct jim_nvp nvp_config_opts[] = { { .name = NULL, .value = -1 } }; -static int target_configure(struct jim_getopt_info *goi, struct target *target) +static COMMAND_HELPER(target_configure, struct target *target, unsigned int index, bool is_configure) { - struct jim_nvp *n; - Jim_Obj *o; - jim_wide w; - int e; + const struct nvp *n; + int retval; /* parse config or cget options ... */ - while (goi->argc > 0) { - Jim_SetEmptyResult(goi->interp); - /* jim_getopt_debug(goi); */ - + while (index < CMD_ARGC) { if (target->type->target_jim_configure) { /* target defines a configure function */ /* target gets first dibs on parameters */ - e = (*(target->type->target_jim_configure))(target, goi); + struct jim_getopt_info goi; + jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - index, CMD_JIMTCL_ARGV + index); + goi.is_configure = is_configure; + int e = (*target->type->target_jim_configure)(target, &goi); + index = CMD_ARGC - goi.argc; if (e == JIM_OK) { /* more? */ continue; } if (e == JIM_ERR) { /* An error */ - return e; + int reslen; + const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); + if (reslen > 0) + command_print(CMD, "%s", result); + return ERROR_FAIL; } /* otherwise we 'continue' below */ } - e = jim_getopt_nvp(goi, nvp_config_opts, &n); - if (e != JIM_OK) { - jim_getopt_nvp_unknown(goi, nvp_config_opts, 0); - return e; + n = nvp_name2value(nvp_config_opts, CMD_ARGV[index]); + if (!n->name) { + nvp_unknown_command_print(CMD, nvp_config_opts, NULL, CMD_ARGV[index]); + return ERROR_COMMAND_ARGUMENT_INVALID; } + index++; switch (n->value) { case TCFG_TYPE: /* not settable */ - if (goi->is_configure) { - Jim_SetResultFormatted(goi->interp, - "not settable: %s", n->name); - return JIM_ERR; - } else { -no_params: - if (goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, - goi->argc, goi->argv, - "NO PARAMS"); - return JIM_ERR; - } + if (is_configure) { + command_print(CMD, "not settable: %s", n->name); + return ERROR_COMMAND_ARGUMENT_INVALID; } - Jim_SetResultString(goi->interp, - target_type_name(target), -1); + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "%s", target_type_name(target)); /* loop for more */ break; + case TCFG_EVENT: - if (goi->argc == 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ..."); - return JIM_ERR; + if (index == CMD_ARGC) { + command_print(CMD, "missing event-name"); + return ERROR_COMMAND_ARGUMENT_INVALID; } - e = jim_getopt_nvp(goi, jim_nvp_target_event, &n); - if (e != JIM_OK) { - jim_getopt_nvp_unknown(goi, jim_nvp_target_event, 1); - return e; + n = nvp_name2value(nvp_target_event, CMD_ARGV[index]); + if (!n->name) { + nvp_unknown_command_print(CMD, nvp_target_event, CMD_ARGV[index - 1], CMD_ARGV[index]); + return ERROR_COMMAND_ARGUMENT_INVALID; } + index++; - 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; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing event-body"); + return ERROR_COMMAND_ARGUMENT_INVALID; } } @@ -4964,20 +4954,20 @@ no_params: if (&teap->list == &target->events_action) teap = NULL; - if (goi->is_configure) { + if (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 */ - jim_getopt_obj(goi, &o); - if (Jim_Length(o) == 0) { + if (strlen(CMD_ARGV[index]) == 0) { /* empty action, drop existing one */ if (teap) { list_del(&teap->list); Jim_DecrRefCount(teap->interp, teap->body); free(teap); } + index++; break; } @@ -4988,10 +4978,12 @@ no_params: replace = false; } teap->event = n->value; - teap->interp = goi->interp; + teap->interp = CMD_CTX->interp; if (teap->body) Jim_DecrRefCount(teap->interp, teap->body); - teap->body = Jim_DuplicateObj(goi->interp, o); + /* use jim object to keep its reference on tcl file and line */ + /* TODO: need duplicate? isn't IncrRefCount enough? */ + teap->body = Jim_DuplicateObj(teap->interp, CMD_JIMTCL_ARGV[index++]); /* * FIXME: * Tcl/TK - "tk events" have a nice feature. @@ -5008,219 +5000,266 @@ no_params: /* add to head of event list */ list_add(&teap->list, &target->events_action); } - Jim_SetEmptyResult(goi->interp); } else { - /* get */ - if (!teap) - Jim_SetEmptyResult(goi->interp); - else - Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, teap->body)); + /* cget */ + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (teap) + command_print(CMD, "%s", Jim_GetString(teap->body, NULL)); } } /* loop for more */ break; case TCFG_WORK_AREA_VIRT: - if (goi->is_configure) { - target_free_all_working_areas(target); - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - target->working_area_virt = w; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[index], target->working_area_virt); + index++; target->working_area_virt_spec = true; + target_free_all_working_areas(target); } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, TARGET_ADDR_FMT, target->working_area_virt); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_virt)); /* loop for more */ break; case TCFG_WORK_AREA_PHYS: - if (goi->is_configure) { - target_free_all_working_areas(target); - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - target->working_area_phys = w; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[index], target->working_area_phys); + index++; target->working_area_phys_spec = true; + target_free_all_working_areas(target); } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, TARGET_ADDR_FMT, target->working_area_phys); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_phys)); /* loop for more */ break; case TCFG_WORK_AREA_SIZE: - if (goi->is_configure) { + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index], target->working_area_size); + index++; target_free_all_working_areas(target); - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - target->working_area_size = w; } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "0x%08" PRIx32, target->working_area_size); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size)); /* loop for more */ break; case TCFG_WORK_AREA_BACKUP: - if (goi->is_configure) { + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + retval = command_parse_bool_arg(CMD_ARGV[index], &target->backup_working_area); + if (retval != ERROR_OK) + return retval; + index++; target_free_all_working_areas(target); - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - /* make this boolean */ - target->backup_working_area = (w != 0); } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, target->backup_working_area ? "1" : "0"); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area ? 1 : 0)); - /* loop for more e*/ + /* loop for more */ break; - case TCFG_ENDIAN: - if (goi->is_configure) { - e = jim_getopt_nvp(goi, nvp_target_endian, &n); - if (e != JIM_OK) { - jim_getopt_nvp_unknown(goi, nvp_target_endian, 1); - return e; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + n = nvp_name2value(nvp_target_endian, CMD_ARGV[index]); + if (!n->name) { + nvp_unknown_command_print(CMD, nvp_target_endian, CMD_ARGV[index - 1], CMD_ARGV[index]); + return ERROR_COMMAND_ARGUMENT_INVALID; } + index++; target->endianness = n->value; } else { - if (goi->argc != 0) - goto no_params; - } - n = jim_nvp_value2name_simple(nvp_target_endian, target->endianness); - if (!n->name) { - target->endianness = TARGET_LITTLE_ENDIAN; - n = jim_nvp_value2name_simple(nvp_target_endian, target->endianness); + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + n = nvp_value2name(nvp_target_endian, target->endianness); + if (!n->name) { + target->endianness = TARGET_LITTLE_ENDIAN; + n = nvp_value2name(nvp_target_endian, target->endianness); + } + command_print(CMD, "%s", n->name); } - Jim_SetResultString(goi->interp, n->name, -1); /* loop for more */ break; case TCFG_COREID: - if (goi->is_configure) { - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - target->coreid = (int32_t)w; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + COMMAND_PARSE_NUMBER(s32, CMD_ARGV[index], target->coreid); + index++; } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "%" PRIi32, target->coreid); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->coreid)); /* loop for more */ break; case TCFG_CHAIN_POSITION: - if (goi->is_configure) { - Jim_Obj *o_t; - struct jtag_tap *tap; - + if (is_configure) { if (target->has_dap) { - Jim_SetResultString(goi->interp, - "target requires -dap parameter instead of -chain-position!", -1); - return JIM_ERR; + command_print(CMD, "target requires -dap parameter instead of -chain-position!"); + return ERROR_COMMAND_ARGUMENT_INVALID; } - e = jim_getopt_obj(goi, &o_t); - if (e != JIM_OK) - return e; - tap = jtag_tap_by_jim_obj(goi->interp, o_t); - if (!tap) - return JIM_ERR; + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[index]); + if (!tap) { + command_print(CMD, "Tap '%s' could not be found", CMD_ARGV[index]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + index++; target->tap = tap; target->tap_configured = true; } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "%s", target->tap->dotted_name); } - Jim_SetResultString(goi->interp, target->tap->dotted_name, -1); - /* loop for more e*/ + /* loop for more */ break; + case TCFG_DBGBASE: - if (goi->is_configure) { - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - target->dbgbase = (uint32_t)w; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index], target->dbgbase); + index++; target->dbgbase_set = true; } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "0x%08" PRIx32, target->dbgbase); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase)); /* loop for more */ break; + case TCFG_RTOS: - /* RTOS */ - { - int result = rtos_create(goi, target); - if (result != JIM_OK) - return result; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + struct jim_getopt_info goi; + jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - index, CMD_JIMTCL_ARGV + index); + index++; + goi.is_configure = true; + int resval = rtos_create(&goi, target); + int reslen; + const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); + if (reslen > 0) + command_print(CMD, "%s", result); + if (resval != JIM_OK) + return ERROR_FAIL; + } else { + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + if (target->rtos) + command_print(CMD, "%s", target->rtos->type->name); } /* loop for more */ break; case TCFG_DEFER_EXAMINE: - /* DEFER_EXAMINE */ - target->defer_examine = true; + if (is_configure) + target->defer_examine = true; + else + command_print(CMD, "%s", target->defer_examine ? "true" : "false"); /* loop for more */ break; case TCFG_GDB_PORT: - if (goi->is_configure) { - struct command_context *cmd_ctx = current_command_context(goi->interp); - if (cmd_ctx->mode != COMMAND_CONFIG) { - Jim_SetResultString(goi->interp, "-gdb-port must be configured before 'init'", -1); - return JIM_ERR; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + /* TODO: generalize test of COMMAND_CONFIG */ + if (CMD_CTX->mode != COMMAND_CONFIG) { + command_print(CMD, "-gdb-port must be configured before 'init'"); + return ERROR_COMMAND_ARGUMENT_INVALID; } - const char *s; - e = jim_getopt_string(goi, &s, NULL); - if (e != JIM_OK) - return e; + char *s = strdup(CMD_ARGV[index]); + if (!s) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } free(target->gdb_port_override); - target->gdb_port_override = strdup(s); + target->gdb_port_override = s; + index++; } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "%s", target->gdb_port_override ? target->gdb_port_override : "undefined"); } - Jim_SetResultString(goi->interp, target->gdb_port_override ? target->gdb_port_override : "undefined", -1); /* loop for more */ break; case TCFG_GDB_MAX_CONNECTIONS: - if (goi->is_configure) { - struct command_context *cmd_ctx = current_command_context(goi->interp); - if (cmd_ctx->mode != COMMAND_CONFIG) { - Jim_SetResultString(goi->interp, "-gdb-max-connections must be configured before 'init'", -1); - return JIM_ERR; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + if (CMD_CTX->mode != COMMAND_CONFIG) { + command_print(CMD, "-gdb-max-connections must be configured before 'init'"); + return ERROR_COMMAND_ARGUMENT_INVALID; } - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - target->gdb_max_connections = (w < 0) ? CONNECTION_LIMIT_UNLIMITED : (int)w; + COMMAND_PARSE_NUMBER(int, CMD_ARGV[index], target->gdb_max_connections); + index++; + if (target->gdb_max_connections < 0) + target->gdb_max_connections = CONNECTION_LIMIT_UNLIMITED; } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "%d", target->gdb_max_connections); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->gdb_max_connections)); + /* loop for more */ break; } - } /* while (goi->argc) */ - + } - /* done - we return */ - return JIM_OK; + return ERROR_OK; } COMMAND_HANDLER(handle_target_configure) @@ -5228,23 +5267,11 @@ COMMAND_HANDLER(handle_target_configure) if (!CMD_ARGC) return ERROR_COMMAND_SYNTAX_ERROR; - struct jim_getopt_info goi; - - jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC, CMD_JIMTCL_ARGV); - goi.is_configure = !strcmp(CMD_NAME, "configure"); + bool is_configure = !strcmp(CMD_NAME, "configure"); struct target *target = get_current_target(CMD_CTX); - int e = target_configure(&goi, target); - - int reslen; - const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); - if (reslen > 0) - command_print(CMD, "%s", result); - - if (e != JIM_OK) - return ERROR_FAIL; - return ERROR_OK; + return CALL_COMMAND_HANDLER(target_configure, target, 0, is_configure); } COMMAND_HANDLER(handle_target_examine) @@ -5803,18 +5830,9 @@ COMMAND_HANDLER(handle_target_create) } /* Do the rest as "configure" options */ - struct jim_getopt_info goi; - jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - 2, CMD_JIMTCL_ARGV + 2); - - goi.is_configure = 1; - int e = target_configure(&goi, target); - - int reslen; - const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); - if (reslen > 0) - command_print(CMD, "%s", result); - - if (e == JIM_OK) { + bool is_configure = true; + retval = CALL_COMMAND_HANDLER(target_configure, target, 2, is_configure); + if (retval == ERROR_OK) { if (target->has_dap) { if (!target->dap_configured) { command_print(CMD, "-dap ?name? required when creating target"); @@ -5829,8 +5847,6 @@ COMMAND_HANDLER(handle_target_create) /* tap must be set after target was configured */ if (!target->tap) retval = ERROR_COMMAND_ARGUMENT_INVALID; - } else { - retval = ERROR_FAIL; } if (retval != ERROR_OK) { -- 2.49.0