From: Zach W. <zw...@us...> - 2009-11-25 19:58:21
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 4946925bea77a4aace6c310b2b724cf2095c6719 (commit) via a3d81eed4d2aac51056f36d7c00ee639bb39c552 (commit) via be482a5335dd35ee1fa163faa0af481b2ec65b70 (commit) via ed90b6659f6d6b98b59d65f7a889e0221bdffa87 (commit) via 9d4c89f37f814df05837cec280b362ad2962c667 (commit) via a93b404161dc42f8dee805c8f95bc4974aded9cb (commit) via d89c6310146d9e5fd1a4ab364f09c0f841da5c73 (commit) via 9e5d8a94f1ea28ee6764511f0cb3c38b22ca8b51 (commit) via 910bb250c479b4de9c30231e1a090e9a2d647434 (commit) via c297a14f7072d98bdad6bd7b9bac3a3069de9ed9 (commit) via 6b066cd17073d868b88414556d1ca3f0580449ec (commit) via 8f5ff3ddcf0ab11b0ec6fc9215144154fb0519f9 (commit) via 17a9dea53a71e9d7e241262725f3dd707b620d37 (commit) via cd7e76ebf0e09466aeb3c61498360c45a1a3ad39 (commit) from f74e2e033a2ad082e5bef67d0ddedd1db3f58300 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 4946925bea77a4aace6c310b2b724cf2095c6719 Author: Zachary T Welch <zw...@su...> Date: Tue Nov 24 20:32:10 2009 -0800 use ARRAY_SIZE macro Search and destroy lingering cases where the ARRAY_SIZE macro should be used to convey more intrinsic meaning in the OpenOCD code. diff --git a/src/flash/avrf.c b/src/flash/avrf.c index 1c48464..687dd4b 100644 --- a/src/flash/avrf.c +++ b/src/flash/avrf.c @@ -290,7 +290,7 @@ static int avrf_probe(struct flash_bank *bank) LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", EXTRACT_MFG(device_id), 0x1F); } - for (i = 0; i < (int)(sizeof(avft_chips_info) / sizeof(avft_chips_info[0])); i++) + for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) { if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) { @@ -369,7 +369,7 @@ static int avrf_info(struct flash_bank *bank, char *buf, int buf_size) LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected", EXTRACT_MFG(device_id), 0x1F); } - for (i = 0; i < (int)(sizeof(avft_chips_info) / sizeof(avft_chips_info[0])); i++) + for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) { if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) { diff --git a/src/flash/tms470.c b/src/flash/tms470.c index 682013e..5965934 100644 --- a/src/flash/tms470.c +++ b/src/flash/tms470.c @@ -46,7 +46,7 @@ const struct flash_sector TMS470R1A256_SECTORS[] = { }; #define TMS470R1A256_NUM_SECTORS \ - (sizeof(TMS470R1A256_SECTORS)/sizeof(TMS470R1A256_SECTORS[0])) + ARRAY_SIZE(TMS470R1A256_SECTORS) const struct flash_sector TMS470R1A288_BANK0_SECTORS[] = { {0x00000000, 0x00002000, -1, -1}, @@ -56,7 +56,7 @@ const struct flash_sector TMS470R1A288_BANK0_SECTORS[] = { }; #define TMS470R1A288_BANK0_NUM_SECTORS \ - (sizeof(TMS470R1A288_BANK0_SECTORS)/sizeof(TMS470R1A288_BANK0_SECTORS[0])) + ARRAY_SIZE(TMS470R1A288_BANK0_SECTORS) const struct flash_sector TMS470R1A288_BANK1_SECTORS[] = { {0x00040000, 0x00010000, -1, -1}, @@ -66,7 +66,7 @@ const struct flash_sector TMS470R1A288_BANK1_SECTORS[] = { }; #define TMS470R1A288_BANK1_NUM_SECTORS \ - (sizeof(TMS470R1A288_BANK1_SECTORS)/sizeof(TMS470R1A288_BANK1_SECTORS[0])) + ARRAY_SIZE(TMS470R1A288_BANK1_SECTORS) const struct flash_sector TMS470R1A384_BANK0_SECTORS[] = { {0x00000000, 0x00002000, -1, -1}, @@ -82,7 +82,7 @@ const struct flash_sector TMS470R1A384_BANK0_SECTORS[] = { }; #define TMS470R1A384_BANK0_NUM_SECTORS \ - (sizeof(TMS470R1A384_BANK0_SECTORS)/sizeof(TMS470R1A384_BANK0_SECTORS[0])) + ARRAY_SIZE(TMS470R1A384_BANK0_SECTORS) const struct flash_sector TMS470R1A384_BANK1_SECTORS[] = { {0x00020000, 0x00008000, -1, -1}, @@ -92,7 +92,7 @@ const struct flash_sector TMS470R1A384_BANK1_SECTORS[] = { }; #define TMS470R1A384_BANK1_NUM_SECTORS \ - (sizeof(TMS470R1A384_BANK1_SECTORS)/sizeof(TMS470R1A384_BANK1_SECTORS[0])) + ARRAY_SIZE(TMS470R1A384_BANK1_SECTORS) const struct flash_sector TMS470R1A384_BANK2_SECTORS[] = { {0x00040000, 0x00008000, -1, -1}, @@ -102,7 +102,7 @@ const struct flash_sector TMS470R1A384_BANK2_SECTORS[] = { }; #define TMS470R1A384_BANK2_NUM_SECTORS \ - (sizeof(TMS470R1A384_BANK2_SECTORS)/sizeof(TMS470R1A384_BANK2_SECTORS[0])) + ARRAY_SIZE(TMS470R1A384_BANK2_SECTORS) /* ---------------------------------------------------------------------- */ diff --git a/src/jtag/ft2232.c b/src/jtag/ft2232.c index 73cbaf3..29b6389 100644 --- a/src/jtag/ft2232.c +++ b/src/jtag/ft2232.c @@ -1949,7 +1949,7 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor { static const char* type_str[] = {"BM", "AM", "100AX", "UNKNOWN", "2232C", "232R", "2232H", "4232H"}; - unsigned no_of_known_types = sizeof(type_str) / sizeof(type_str[0]) - 1; + unsigned no_of_known_types = ARRAY_SIZE(type_str) - 1; unsigned type_index = ((unsigned)ftdi_device <= no_of_known_types) ? ftdi_device : FT_DEVICE_UNKNOWN; LOG_INFO("device: %lu \"%s\"", ftdi_device, type_str[type_index]); @@ -2034,7 +2034,7 @@ static int ft2232_init_libftdi(uint16_t vid, uint16_t pid, int more, int* try_mo ftdi_device = ftdic.type; static const char* type_str[] = {"AM", "BM", "2232C", "R", "2232H", "4232H", "Unknown"}; - unsigned no_of_known_types = sizeof(type_str) / sizeof(type_str[0]) - 1; + unsigned no_of_known_types = ARRAY_SIZE(type_str) - 1; unsigned type_index = ((unsigned)ftdi_device < no_of_known_types) ? ftdi_device : no_of_known_types; LOG_DEBUG("FTDI chip type: %i \"%s\"", (int)ftdi_device, type_str[type_index]); diff --git a/src/jtag/rlink/rlink_speed_table.c b/src/jtag/rlink/rlink_speed_table.c index 5c40ab4..2ef62ee 100644 --- a/src/jtag/rlink/rlink_speed_table.c +++ b/src/jtag/rlink/rlink_speed_table.c @@ -97,5 +97,5 @@ const struct rlink_speed_table rlink_speed_table[] = {{ dtc_2, sizeof(dtc_2), (ST7_FOSC * 2) / (1000 * 2), 2 }}; -const size_t rlink_speed_table_size = sizeof(rlink_speed_table) / sizeof(*rlink_speed_table); +const size_t rlink_speed_table_size = ARRAY_SIZE(rlink_speed_table); diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index bc29078..e755dd7 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -1304,7 +1304,7 @@ static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *ar { tap_state_t states[8]; - if ((argc < 2) || ((size_t)argc > (sizeof(states)/sizeof(*states) + 1))) + if ((argc < 2) || ((size_t)argc > (ARRAY_SIZE(states) + 1))) { Jim_WrongNumArgs(interp, 1, args, "wrong arguments"); return JIM_ERR; diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 9d89086..fc3f47c 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -596,7 +596,7 @@ int armv7m_checksum_memory(struct target *target, } /* convert flash writing code into a buffer in target endianness */ - for (i = 0; i < (sizeof(cortex_m3_crc_code)/sizeof(uint16_t)); i++) + for (i = 0; i < ARRAY_SIZE(cortex_m3_crc_code); i++) if ((retval = target_write_u16(target, crc_algorithm->address + i*sizeof(uint16_t), cortex_m3_crc_code[i])) != ERROR_OK) { return retval; @@ -659,7 +659,7 @@ int armv7m_blank_check_memory(struct target *target, } /* convert flash writing code into a buffer in target endianness */ - for (i = 0; i < (sizeof(erase_check_code)/sizeof(uint16_t)); i++) + for (i = 0; i < ARRAY_SIZE(erase_check_code); i++) target_write_u16(target, erase_check_algorithm->address + i*sizeof(uint16_t), erase_check_code[i]); armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; diff --git a/src/target/avrt.c b/src/target/avrt.c index dc527f5..6ba6206 100644 --- a/src/target/avrt.c +++ b/src/target/avrt.c @@ -196,7 +196,7 @@ int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, int ir_l field[0].num_bits = tap->ir_length; field[0].out_value = ir_out; field[0].in_value = ir_in; - jtag_add_plain_ir_scan(sizeof(field) / sizeof(field[0]), field, jtag_set_end_state(TAP_IDLE)); + jtag_add_plain_ir_scan(ARRAY_SIZE(field), field, jtag_set_end_state(TAP_IDLE)); } return ERROR_OK; @@ -217,7 +217,7 @@ int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, int dr_l field[0].num_bits = dr_len; field[0].out_value = dr_out; field[0].in_value = dr_in; - jtag_add_plain_dr_scan(sizeof(field) / sizeof(field[0]), field, jtag_set_end_state(TAP_IDLE)); + jtag_add_plain_dr_scan(ARRAY_SIZE(field), field, jtag_set_end_state(TAP_IDLE)); } return ERROR_OK; diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 4f9a704..604d34e 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -348,8 +348,8 @@ int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int co param_in[0] = addr; param_in[1] = blocksize; - if ((retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, - sizeof(param_in)/sizeof(param_in[0]), param_in, blocksize, &buf[bytesread], 1)) != ERROR_OK) + if ((retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, + ARRAY_SIZE(param_in), param_in, blocksize, &buf[bytesread], 1)) != ERROR_OK) { return retval; } @@ -387,8 +387,8 @@ int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t param_in[0] = addr; - if ((retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, - sizeof(param_in)/sizeof(param_in[0]), param_in, sizeof(uint32_t), buf, 1)) != ERROR_OK) + if ((retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, + ARRAY_SIZE(param_in), param_in, sizeof(uint32_t), buf, 1)) != ERROR_OK) { return retval; } @@ -459,8 +459,8 @@ int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int co param_in[0] = addr; param_in[1] = blocksize; - mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ - sizeof(param_in)/sizeof(param_in[0]), param_in, count, param_out, 1); + mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \ + ARRAY_SIZE(param_in), param_in, count, param_out, 1); // count -= blocksize; // addr += blocksize; @@ -540,8 +540,8 @@ int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int cou param_in[0] = addr; param_in[1] = blocksize; - mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ - sizeof(param_in)/sizeof(param_in[0]), param_in, count, param_out, 1); + mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \ + ARRAY_SIZE(param_in), param_in, count, param_out, 1); // count -= blocksize; // addr += blocksize; @@ -619,7 +619,7 @@ int mips32_pracc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int c memcpy(¶m_in[2], buf, count * sizeof(uint32_t)); - mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \ count + 2, param_in, 0, NULL, 1); free(param_in); @@ -654,8 +654,8 @@ int mips32_pracc_write_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_ param_in[0] = addr; param_in[1] = *buf; - mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ - sizeof(param_in)/sizeof(param_in[0]),param_in, 0, NULL, 1); + mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \ + ARRAY_SIZE(param_in),param_in, 0, NULL, 1); return ERROR_OK; } @@ -714,7 +714,7 @@ int mips32_pracc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int c param_in[i + 2] = buf[i]; } - mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \ count + 2, param_in, 0, NULL, 1); free(param_in); @@ -777,7 +777,7 @@ int mips32_pracc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int co param_in[i + 2] = buf[i]; } - retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \ count +2, param_in, 0, NULL, 1); free(param_in); @@ -851,7 +851,7 @@ int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) int retval; - retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \ 38, regs, 0, NULL, 1); return retval; @@ -928,7 +928,7 @@ int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) int retval; - retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \ 0, NULL, 38, regs, 1); return retval; diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index 6f06d9a..68a39fa 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -143,7 +143,7 @@ int mips_ejtag_step_enable(struct mips_ejtag *ejtag_info) MIPS32_NOP, }; - mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \ 0, NULL, 0, NULL, 1); return ERROR_OK; @@ -169,7 +169,7 @@ int mips_ejtag_step_disable(struct mips_ejtag *ejtag_info) MIPS32_NOP, }; - mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \ 0, NULL, 0, NULL, 1); return ERROR_OK; @@ -234,7 +234,7 @@ int mips_ejtag_read_debug(struct mips_ejtag *ejtag_info, uint32_t* debug_reg) MIPS32_NOP, }; - mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \ 0, NULL, 1, debug_reg, 1); return ERROR_OK; diff --git a/src/target/xscale.c b/src/target/xscale.c index e402a11..07fcc4c 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -412,7 +412,7 @@ static int xscale_read_tx(struct target *target, int consume) jtag_add_pathmove(3, path); else { - jtag_add_pathmove(sizeof(noconsume_path)/sizeof(*noconsume_path), noconsume_path); + jtag_add_pathmove(ARRAY_SIZE(noconsume_path), noconsume_path); } jtag_add_dr_scan(3, fields, jtag_set_end_state(TAP_IDLE)); @@ -2825,7 +2825,7 @@ static void xscale_build_reg_cache(struct target *target) struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache); struct xscale_reg *arch_info = malloc(sizeof(xscale_reg_arch_info)); int i; - int num_regs = sizeof(xscale_reg_arch_info) / sizeof(struct xscale_reg); + int num_regs = ARRAY_SIZE(xscale_reg_arch_info); (*cache_p) = armv4_5_build_reg_cache(target, armv4_5); commit a3d81eed4d2aac51056f36d7c00ee639bb39c552 Author: Zachary T Welch <zw...@su...> Date: Mon Nov 23 12:14:05 2009 -0800 support OPENOCD_DEBUG_LEVEL environment setting Detect the OPENOCD_DEBUG_LEVEL setting in log_init(), allowing the very early startup phases to be debugged. diff --git a/src/helper/log.c b/src/helper/log.c index 27fa831..3067ecc 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -346,6 +346,19 @@ void log_init(void) if (debug_level == -1) debug_level = LOG_LVL_INFO; + char *debug_env = getenv("OPENOCD_DEBUG_LEVEL"); + if (NULL != debug_env) + { + int value; + int retval = parse_int(debug_env, &value); + if (ERROR_OK == retval && + debug_level >= LOG_LVL_SILENT && + debug_level <= LOG_LVL_DEBUG) + { + debug_level = value; + } + } + if (log_output == NULL) log_output = stderr; commit be482a5335dd35ee1fa163faa0af481b2ec65b70 Author: Zachary T Welch <zw...@su...> Date: Fri Nov 20 16:36:32 2009 -0800 log: improve initialization Removes redundant assignment of start_ms from log_register_commands(). Eliminates command_context parameter and return value. Adds Doxygen comment block for this API call. diff --git a/src/helper/log.c b/src/helper/log.c index 3799fb3..27fa831 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -336,25 +336,20 @@ static struct command_registration log_command_handlers[] = { int log_register_commands(struct command_context *cmd_ctx) { - start = timeval_ms(); - return register_commands(cmd_ctx, NULL, log_command_handlers); } -int log_init(struct command_context *cmd_ctx) +void log_init(void) { - /* set defaults for daemon configuration, if not set by cmdline or cfgfile */ + /* set defaults for daemon configuration, + * if not set by cmdline or cfgfile */ if (debug_level == -1) debug_level = LOG_LVL_INFO; if (log_output == NULL) - { log_output = stderr; - } start = last_time = timeval_ms(); - - return ERROR_OK; } int set_log_output(struct command_context *cmd_ctx, FILE *output) diff --git a/src/helper/log.h b/src/helper/log.h index 6f7c24a..f2d19d1 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -66,7 +66,10 @@ void log_printf_lf(enum log_levels level, const char *file, unsigned line, const char *function, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6))); -int log_init(struct command_context *cmd_ctx); +/** + * Initialize logging module. Call during program startup. + */ +void log_init(void); int set_log_output(struct command_context *cmd_ctx, FILE *output); int log_register_commands(struct command_context *cmd_ctx); diff --git a/src/openocd.c b/src/openocd.c index 1f29acd..629d50a 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -182,6 +182,9 @@ struct command_context *global_cmd_ctx; /* NB! this fn can be invoked outside this file for non PC hosted builds */ struct command_context *setup_command_handler(void) { + log_init(); + LOG_DEBUG("log_init: complete"); + struct command_context *cmd_ctx; global_cmd_ctx = cmd_ctx = command_init(openocd_startup_tcl); @@ -202,11 +205,7 @@ struct command_context *setup_command_handler(void) pld_register_commands(cmd_ctx); mflash_register_commands(cmd_ctx); - if (log_init(cmd_ctx) != ERROR_OK) - { - exit(-1); - } - LOG_DEBUG("log init complete"); + LOG_DEBUG("command registration: complete"); LOG_OUTPUT(OPENOCD_VERSION "\n"); commit ed90b6659f6d6b98b59d65f7a889e0221bdffa87 Author: Zachary T Welch <zw...@su...> Date: Tue Nov 24 18:47:35 2009 -0800 update command handler documentation Adds sections on command registration and chaining, giving an overview to developers that want to use these features. diff --git a/doc/manual/helper.txt b/doc/manual/helper.txt index e7454b6..aa52355 100644 --- a/doc/manual/helper.txt +++ b/doc/manual/helper.txt @@ -80,6 +80,42 @@ command handlers and helpers: - @c CMD_ARGC - the number of command arguments - @c CMD_ARGV - array of command argument strings +@section helpercmdregister Command Registration + +In order to use a command handler, it must be registered with the +command subsystem. All commands are registered with command_registration +structures, specifying the name of the command, its handler, its allowed +mode(s) of execution, and strings that provide usage and help text. +A single handler may be registered using multiple names, but any name +may have only one handler associated with it. + +The @c register_commands() and @c register_commands() functions provide +registration, while the @c unregister_command() and +@c unregister_all_commands() functions will remove existing commands. +These may be called at any time, allowing the command set to change in +response to system actions. + +@subsection helpercmdjim Jim Command Registration + +The command_registration structure provides support for registering +native Jim command handlers (@c jim_handler) too. For these handlers, +the module can provide help and usage support; however, this mechanism +allows Jim handlers to be called as sub-commands of other commands. +These commands may be registered with a private data value (@c +jim_handler_data) that will be available when called, as with low-level +Jim command registration. + +A command may have a normal @c handler or a @c jim_handler, but not both. + +@subsection helpercmdregisterchains Command Chaining + +When using register_commands(), the array of commands may reference +other arrays. When the @c chain field is filled in a +command_registration record, the commands on in the chained list will +added in one of two places. If the record defines a new command, then +the chained commands are added under it; otherwise, the commands are +added in the same context as the other commands in the array. + @section helpercmdprimer Command Development Primer This @ref primercommand provides details about the @c hello module, diff --git a/doc/manual/primer/commands.txt b/doc/manual/primer/commands.txt index b15f669..c9db7cc 100644 --- a/doc/manual/primer/commands.txt +++ b/doc/manual/primer/commands.txt @@ -63,42 +63,71 @@ Before this new function can be used, it must be registered somehow. For a new module, registering should be done in a new function for the purpose, which must be called from @c openocd.c: @code + +static const struct command_registration hello_command_handlers[] = { + { + .name = "hello", + .mode = COMMAND_ANY, + .handler = &handle_hello_command, + .help = "print a warm greetings", + .usage = "[<name>]", + }, + { + .chain = foo_command_handlers, + } + COMMAND_REGISTRATION_DONE +}; + int hello_register_commands(struct command_context_s *cmd_ctx) { - struct command_s *cmd = register_command(cmd_ctx, NULL, "hello", - NULL, COMMAND_ANY, "print greetings"); - return cmd ? ERROR_OK : -ENOMEM; + return register_commands(cmd_ctx, NULL, handle_command_handlers); } @endcode That's it! The command should now be registered and avaiable to scripts. +@section primercmdchain Command Chaining + +This example also shows how to chain command handler registration, so +your modules can "inherit" commands provided by other (sub)modules. +Here, the hello module includes the foo commands in the same context +that the 'hello' command will be registered. + +If the @c chain field had been put in the 'hello' command, then the +@c foo module commands would be registered under it. Indeed, that +technique is used to define the 'foo bar' and 'foo baz' commands, +as well as for the example drivers that use these modules. + +The code for the 'foo' command handlers can be found in @c hello.c. + @section primercmdcode Trying These Example Commands -The commands may be enabled by editing src/openocd.c and uncommenting -the call to @c hello_register_commands and rebuilding the source tree. +These commands have been inherited by the dummy interface, faux flash, +and testee target drivers. The easiest way to test these is by using the +dummy interface. -Once OpenOCD has been built with this example code, the following script -demonstrate the abilities that the @c hello module provides: +Once OpenOCD has been built with this example code, the following command +demonstrates the abilities that the @c hello module provides: @code -hello -hello World -hello {John Doe} -hello John Doe # error: too many arguments +openocd -c 'interface dummy' \ + -c 'dummy hello' \ + -c 'dummy hello World' \ + -c 'dummy hello {John Doe}' \ + -c 'dummy hello John Doe' # error: too many arguments @endcode If saved in @c hello.cfg, then running <code>openocd -f hello.cfg</code> -should produce the following output before exiting: +should produce the following output before displaying the help text and +exiting: @code Greetings! Greetings, World! Greetings, John Doe! -Error: ocd_hello: too many arguments +Error: hello: too many arguments +Runtime error, file "openocd.cfg", line 14: + hello: too many arguments +dummy hello [<name>] + prints a warm welcome @endcode -This difference between the registered and displayed command name comes from -the fact that the TCL scripts are provided with a stub that calls the munged -name. This stub wraps the internal <code>ocd_</code>-prefixed routine, -providing a measure of high-level error handling. - */ commit 9d4c89f37f814df05837cec280b362ad2962c667 Author: Zachary T Welch <zw...@su...> Date: Sat Nov 21 22:09:53 2009 -0800 add 'testee' target type Alliteration aside, this should provide the final piece of the puzzle for developers that want to get started writing a new target type. In this way, it also seeks to complement the 'dummy' interface driver and 'faux' NOR flash driver. diff --git a/src/target/Makefile.am b/src/target/Makefile.am index a367fd4..d00b0e4 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -42,7 +42,8 @@ TARGET_CORE_SRC = \ image.c \ breakpoints.c \ target.c \ - target_request.c + target_request.c \ + testee.c ARMV4_5_SRC = \ armv4_5.c \ diff --git a/src/target/target.c b/src/target/target.c index 4a9095a..97a93c0 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -65,6 +65,7 @@ extern struct target_type cortexa8_target; extern struct target_type arm11_target; extern struct target_type mips_m4k_target; extern struct target_type avr_target; +extern struct target_type testee_target; struct target_type *target_types[] = { @@ -83,6 +84,7 @@ struct target_type *target_types[] = &arm11_target, &mips_m4k_target, &avr_target, + &testee_target, NULL, }; diff --git a/src/target/testee.c b/src/target/testee.c new file mode 100644 index 0000000..ca3d56e --- /dev/null +++ b/src/target/testee.c @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2009 Zachary T Welch <zw...@su...> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "target.h" +#include "target_type.h" +#include "log.h" +#include "../hello.h" + +static const struct command_registration testee_command_handlers[] = { + { + .name = "testee", + .mode = COMMAND_ANY, + .help = "testee target commands", + + .chain = hello_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +static int testee_init(struct command_context *cmd_ctx, struct target *target) +{ + return ERROR_OK; +} + +struct target_type testee_target = { + .name = "testee", + .init_target = &testee_init, + .commands = testee_command_handlers, +}; commit a93b404161dc42f8dee805c8f95bc4974aded9cb Author: Zachary T Welch <zw...@su...> Date: Sat Nov 21 19:27:20 2009 -0800 improve command handling examples Removes hello and foo commands from top-level registration. Instead, the dummy interface driver and faux flash driver have been augmented to register these commands as sub-commands. diff --git a/src/flash/faux.c b/src/flash/faux.c index adfc7bd..caec2c7 100644 --- a/src/flash/faux.c +++ b/src/flash/faux.c @@ -23,6 +23,7 @@ #include "flash.h" #include "image.h" +#include "../hello.h" struct faux_flash_bank @@ -123,8 +124,19 @@ static int faux_probe(struct flash_bank *bank) return ERROR_OK; } +static const struct command_registration faux_command_handlers[] = { + { + .name = "faux", + .mode = COMMAND_ANY, + .help = "faux flash command group", + .chain = hello_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + struct flash_driver faux_flash = { .name = "faux", + .commands = faux_command_handlers, .flash_bank_command = &faux_flash_bank_command, .erase = &faux_erase, .protect = &faux_protect, diff --git a/src/hello.c b/src/hello.c index 9a1bf92..2e5c928 100644 --- a/src/hello.c +++ b/src/hello.c @@ -101,7 +101,7 @@ COMMAND_HANDLER(handle_hello_command) return retval; } -static const struct command_registration hello_command_handlers[] = { +const struct command_registration hello_command_handlers[] = { { .name = "hello", .handler = &handle_hello_command, diff --git a/src/hello.h b/src/hello.h new file mode 100644 index 0000000..fc674ad --- /dev/null +++ b/src/hello.h @@ -0,0 +1,35 @@ +/*************************************************************************** + * Copyright (C) 2009 Zachary T Welch <zw...@su...> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef OPENOCD_HELLO_H +#define OPENOCD_HELLO_H + +struct command_context; +struct command_registration; + +/// Register the hello commands in the specified command_context +int hello_register_commands(struct command_context *cmd_ctx); + +/** + * Export the registration for the hello command group, so it can be + * embedded in example drivers. + */ +extern const struct command_registration hello_command_handlers[]; + +#endif // OPENOCD_HELLO_H diff --git a/src/jtag/dummy.c b/src/jtag/dummy.c index 11b6f71..c2beb09 100644 --- a/src/jtag/dummy.c +++ b/src/jtag/dummy.c @@ -23,6 +23,7 @@ #include "interface.h" #include "bitbang.h" +#include "../hello.h" /* my private tap controller state, which tracks state for calling code */ @@ -146,12 +147,25 @@ static int dummy_quit(void) return ERROR_OK; } +static const struct command_registration dummy_command_handlers[] = { + { + .name = "dummy", + .mode = COMMAND_ANY, + .help = "dummy interface driver commands", + + .chain = hello_command_handlers, + }, + COMMAND_REGISTRATION_DONE, +}; + /* The dummy driver is used to easily check the code path * where the target is unresponsive. */ struct jtag_interface dummy_interface = { .name = "dummy", + .commands = dummy_command_handlers, + .execute_queue = &bitbang_execute_queue, .speed = &dummy_speed, diff --git a/src/openocd.c b/src/openocd.c index e38c84e..1f29acd 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -179,9 +179,6 @@ static const struct command_registration openocd_command_handlers[] = { struct command_context *global_cmd_ctx; -/// src/hello.c gives a simple example for writing new command modules -int hello_register_commands(struct command_context *cmd_ctx); - /* NB! this fn can be invoked outside this file for non PC hosted builds */ struct command_context *setup_command_handler(void) { @@ -191,7 +188,6 @@ struct command_context *setup_command_handler(void) register_commands(cmd_ctx, NULL, openocd_command_handlers); /* register subsystem commands */ - hello_register_commands(cmd_ctx); server_register_commands(cmd_ctx); telnet_register_commands(cmd_ctx); gdb_register_commands(cmd_ctx); commit d89c6310146d9e5fd1a4ab364f09c0f841da5c73 Author: Zachary T Welch <zw...@su...> Date: Tue Nov 24 19:51:49 2009 -0800 add script_command_run helper Eliminates duplicated code in script_command and handle_unknown_command. Fixes bug with duplicated help output generated by placeholder commands. diff --git a/src/helper/command.c b/src/helper/command.c index 8b29ab4..62fb487 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -150,33 +150,41 @@ static struct command_context *current_command_context(void) return cmd_ctx; } -static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +static int script_command_run(Jim_Interp *interp, + int argc, Jim_Obj *const *argv, struct command *c, bool capture) { - /* the private data is stashed in the interp structure */ - - struct command *c = interp->cmdPrivData; - assert(c); - target_call_timer_callbacks_now(); LOG_USER_N("%s", ""); /* Keep GDB connection alive*/ - script_debug(interp, c->name, argc, argv); - unsigned nwords; const char **words = script_command_args_alloc(argc, argv, &nwords); if (NULL == words) return JIM_ERR; - Jim_Obj *tclOutput = command_log_capture_start(interp); + Jim_Obj *tclOutput = NULL; + if (capture) + tclOutput = command_log_capture_start(interp); struct command_context *cmd_ctx = current_command_context(); int retval = run_command(cmd_ctx, c, (const char **)words, nwords); - command_log_capture_finish(interp, tclOutput); + if (capture) + command_log_capture_finish(interp, tclOutput); + script_command_args_free(words, nwords); return command_retval_set(interp, retval); } +static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + /* the private data is stashed in the interp structure */ + + struct command *c = interp->cmdPrivData; + assert(c); + script_debug(interp, c->name, argc, argv); + return script_command_run(interp, argc, argv, c, true); +} + /* nice short description of source file */ #define __THIS__FILE__ "command.c" @@ -922,22 +930,7 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return (*c->jim_handler)(interp, count, start); } - unsigned nwords; - const char **words = script_command_args_alloc(count, start, &nwords); - if (NULL == words) - return JIM_ERR; - - Jim_Obj *tclOutput = command_log_capture_start(interp); - - int retval = run_command(cmd_ctx, c, words, nwords); - - command_log_capture_finish(interp, tclOutput); - script_command_args_free(words, nwords); - - if (!found && ERROR_OK == retval) - retval = ERROR_FAIL; - - return command_retval_set(interp, retval); + return script_command_run(interp, count, start, c, found); } int help_add_command(struct command_context *cmd_ctx, struct command *parent, commit 9e5d8a94f1ea28ee6764511f0cb3c38b22ca8b51 Author: Zachary T Welch <zw...@su...> Date: Tue Nov 24 19:13:03 2009 -0800 encapsulate and re-use log capture, retval setup Factors log capture while running script commands, eliminating duplicated code between script_command and jim_capture. Factors setting a command's Jim "retval" into a new helper as well. Using these new helpers in the new unknown command handler's fixes possible regressions caused by these bits being missing. diff --git a/src/helper/command.c b/src/helper/command.c index 54eec3b..8b29ab4 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -56,6 +56,34 @@ static void tcl_output(void *privData, const char *file, unsigned line, Jim_AppendString(interp, tclOutput, string, strlen(string)); } +static Jim_Obj *command_log_capture_start(Jim_Interp *interp) +{ + /* capture log output and return it. A garbage collect can + * happen, so we need a reference count to this object */ + Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0); + if (NULL == tclOutput) + return NULL; + Jim_IncrRefCount(tclOutput); + log_add_callback(tcl_output, tclOutput); + return tclOutput; +} + +static void command_log_capture_finish(Jim_Interp *interp, Jim_Obj *tclOutput) +{ + log_remove_callback(tcl_output, tclOutput); + Jim_SetResult(interp, tclOutput); + Jim_DecrRefCount(interp, tclOutput); +} + +static int command_retval_set(Jim_Interp *interp, int retval) +{ + int *return_retval = Jim_GetAssocData(interp, "retval"); + if (return_retval != NULL) + *return_retval = retval; + + return (retval == ERROR_OK) ? JIM_OK : JIM_ERR; +} + extern struct command_context *global_cmd_ctx; void script_debug(Jim_Interp *interp, const char *name, @@ -125,20 +153,10 @@ static struct command_context *current_command_context(void) static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { /* the private data is stashed in the interp structure */ - struct command *c; - int retval; - /* DANGER!!!! be careful what we invoke here, since interp->cmdPrivData might - * get overwritten by running other Jim commands! Treat it as an - * emphemeral global variable that is used in lieu of an argument - * to the fn and fish it out manually. - */ - c = interp->cmdPrivData; - if (c == NULL) - { - LOG_ERROR("BUG: interp->cmdPrivData == NULL"); - return JIM_ERR; - } + struct command *c = interp->cmdPrivData; + assert(c); + target_call_timer_callbacks_now(); LOG_USER_N("%s", ""); /* Keep GDB connection alive*/ @@ -149,31 +167,14 @@ static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (NULL == words) return JIM_ERR; - /* capture log output and return it */ - Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0); - /* a garbage collect can happen, so we need a reference count to this object */ - Jim_IncrRefCount(tclOutput); - - log_add_callback(tcl_output, tclOutput); + Jim_Obj *tclOutput = command_log_capture_start(interp); struct command_context *cmd_ctx = current_command_context(); - retval = run_command(cmd_ctx, c, (const char **)words, nwords); - - log_remove_callback(tcl_output, tclOutput); - - /* We dump output into this local variable */ - Jim_SetResult(interp, tclOutput); - Jim_DecrRefCount(interp, tclOutput); + int retval = run_command(cmd_ctx, c, (const char **)words, nwords); + command_log_capture_finish(interp, tclOutput); script_command_args_free(words, nwords); - - int *return_retval = Jim_GetAssocData(interp, "retval"); - if (return_retval != NULL) - { - *return_retval = retval; - } - - return (retval == ERROR_OK)?JIM_OK:JIM_ERR; + return command_retval_set(interp, retval); } /* nice short description of source file */ @@ -766,23 +767,13 @@ static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 2) return JIM_ERR; - int retcode; - const char *str = Jim_GetString(argv[1], NULL); - - /* capture log output and return it */ - Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0); - /* a garbage collect can happen, so we need a reference count to this object */ - Jim_IncrRefCount(tclOutput); - - log_add_callback(tcl_output, tclOutput); - retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__); + Jim_Obj *tclOutput = command_log_capture_start(interp); - log_remove_callback(tcl_output, tclOutput); + const char *str = Jim_GetString(argv[1], NULL); + int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__); - /* We dump output into this local variable */ - Jim_SetResult(interp, tclOutput); - Jim_DecrRefCount(interp, tclOutput); + command_log_capture_finish(interp, tclOutput); return retcode; } @@ -936,14 +927,17 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (NULL == words) return JIM_ERR; + Jim_Obj *tclOutput = command_log_capture_start(interp); + int retval = run_command(cmd_ctx, c, words, nwords); + command_log_capture_finish(interp, tclOutput); script_command_args_free(words, nwords); if (!found && ERROR_OK == retval) retval = ERROR_FAIL; - return retval; + return command_retval_set(interp, retval); } int help_add_command(struct command_context *cmd_ctx, struct command *parent, commit 910bb250c479b4de9c30231e1a090e9a2d647434 Author: Zachary T Welch <zw...@su...> Date: Tue Nov 24 22:18:28 2009 -0800 combine help and usage command handlers Remove duplicated handler code by checking the running command name. diff --git a/src/helper/command.c b/src/helper/command.c index a1ba358..54eec3b 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -861,30 +861,18 @@ static COMMAND_HELPER(command_help_show, struct command *c, unsigned n, } COMMAND_HANDLER(handle_help_command) { - struct command *c = CMD_CTX->commands; - - if (0 == CMD_ARGC) - return CALL_COMMAND_HANDLER(command_help_show_list, c, 0, true); + bool full = strcmp(CMD_NAME, "help") == 0; - int retval = CALL_COMMAND_HANDLER(command_help_find, c, &c); - if (ERROR_OK != retval) - return retval; - - return CALL_COMMAND_HANDLER(command_help_show, c, 0, true); -} - -COMMAND_HANDLER(handle_usage_command) -{ struct command *c = CMD_CTX->commands; if (0 == CMD_ARGC) - return CALL_COMMAND_HANDLER(command_help_show_list, c, 0, false); + return CALL_COMMAND_HANDLER(command_help_show_list, c, 0, full); int retval = CALL_COMMAND_HANDLER(command_help_find, c, &c); if (ERROR_OK != retval) return retval; - return CALL_COMMAND_HANDLER(command_help_show, c, 0, false); + return CALL_COMMAND_HANDLER(command_help_show, c, 0, full); } static int command_unknown_find(unsigned argc, Jim_Obj *const *argv, @@ -1106,15 +1094,15 @@ static const struct command_registration command_builtin_handlers[] = { .name = "help", .handler = &handle_help_command, .mode = COMMAND_ANY, - .help = "show built-in command help", - .usage = "[<command_name> ...]", + .help = "show full command help", + .usage = "[<command> ...]", }, { .name = "usage", - .handler = &handle_usage_command, + .handler = &handle_help_command, .mode = COMMAND_ANY, - .help = "show command usage", - .usage = "[<command_name> ...]", + .help = "show basic command usage", + .usage = "[<command> ...]", }, COMMAND_REGISTRATION_DONE }; commit c297a14f7072d98bdad6bd7b9bac3a3069de9ed9 Author: Zachary T Welch <zw...@su...> Date: Mon Nov 23 12:00:31 2009 -0800 improve usage and help command output Rewrite formatting code in C, removing last remenants of TCL help code. Sinificantly improves the readability by using smarter indent and wrap. diff --git a/src/helper/command.c b/src/helper/command.c index 1263a93..a1ba358 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -811,20 +811,48 @@ static COMMAND_HELPER(command_help_show_list, struct command *head, unsigned n, CALL_COMMAND_HANDLER(command_help_show, c, n, show_help); return ERROR_OK; } + +#define HELP_LINE_WIDTH(_n) (int)(76 - (2 * _n)) + +static void command_help_show_indent(unsigned n) +{ + for (unsigned i = 0; i < n; i++) + LOG_USER_N(" "); +} +static void command_help_show_wrap(const char *str, unsigned n, unsigned n2) +{ + const char *cp = str, *last = str; + while (*cp) + { + const char *next = last; + do { + cp = next; + do { + next++; + } while (*next != ' ' && *next != '\t' && *next != '\0'); + } while ((next - last < HELP_LINE_WIDTH(n)) && *next != '\0'); + if (next - last < HELP_LINE_WIDTH(n)) + cp = next; + command_help_show_indent(n); + LOG_USER_N("%.*s", (int)(cp - last), last); + LOG_USER_N("\n"); + last = cp + 1; + n = n2; + } +} static COMMAND_HELPER(command_help_show, struct command *c, unsigned n, bool show_help) { - const char *usage = c->usage ? : ""; - const char *help = ""; - const char *sep = ""; - if (show_help && c->help) - { - help = c->help ? : ""; - sep = c->usage ? " | " : ""; + command_help_show_indent(n); + LOG_USER_N("%s", command_name(c, ' ')); + if (c->usage) { + LOG_USER_N(" "); + command_help_show_wrap(c->usage, 0, n + 5); } - command_run_linef(CMD_CTX, "cmd_help {%s} {%s%s%s} %d", - command_name(c, ' '), usage, sep, help, n); - + else + LOG_USER_N("\n"); + if (show_help && c->help) + command_help_show_wrap(c->help, n + 3, n + 3); if (++n >= 2) return ERROR_OK; diff --git a/src/helper/startup.tcl b/src/helper/startup.tcl index 5969cfe..f11d5b6 100644 --- a/src/helper/startup.tcl +++ b/src/helper/startup.tcl @@ -10,40 +10,6 @@ proc exit {} { ocd_throw exit } -# Help text list. A list of command + help text pairs. -proc cmd_help {cmdname h indent} { - set indent [expr $indent * 2] - - set fmt_str [format "%%%ds%%-%ds %%s" $indent [expr 25 - $indent]] - set w [expr 50 - $indent] - set n 0 - - while 1 { - if {$n > [string length $h]} {break} - - set next_a [expr $n + $w] - if {[string length $h] > $n + $w} \ - { - set xxxx [string range $h $n [expr $n + $w]] - for {set lastpos [expr [string length $xxxx] - 1]} \ - {$lastpos >= 0 && [string compare \ - [string range $xxxx $lastpos $lastpos] " "] != 0} \ - {set lastpos [expr $lastpos - 1]} \ - { - } - #set next_a -1 - if {$lastpos != -1} { - set next_a [expr $lastpos + $n + 1] - } - } - - puts [format $fmt_str "" $cmdname \ - [string range $h $n [expr $next_a - 1]] ] - set cmdname "" - set n [expr $next_a] - } -} - # Try flipping / and \ to find file if the filename does not # match the precise spelling proc find {filename} { commit 6b066cd17073d868b88414556d1ca3f0580449ec Author: Zachary T Welch <zw...@su...> Date: Mon Nov 23 12:16:27 2009 -0800 allow scripts to update usage information The add_usage_text command uses the same C handler, which was updated to support its new polymorphic role. This patch updates the two script commands that needed this support: 'find' and 'script'. diff --git a/src/helper/command.c b/src/helper/command.c index 3cb36ea..1263a93 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -951,8 +951,9 @@ int help_add_command(struct command_context *cmd_ctx, struct command *parent, return ERROR_FAIL; } LOG_DEBUG("added '%s' help text", cmd_name); + return ERROR_OK; } - else + if (help_text) { bool replaced = false; if (nc->help) @@ -961,12 +962,25 @@ int help_add_command(struct command_context *cmd_ctx, struct command *parent, replaced = true; } nc->help = strdup(help_text); - if (replaced) LOG_INFO("replaced existing '%s' help", cmd_name); else LOG_DEBUG("added '%s' help text", cmd_name); } + if (usage) + { + bool replaced = false; + if (nc->usage) + { + free((void *)nc->usage); + replaced = true; + } + nc->usage = strdup(usage); + if (replaced) + LOG_INFO("replaced existing '%s' usage", cmd_name); + else + LOG_DEBUG("added '%s' usage text", cmd_name); + } return ERROR_OK; } @@ -979,7 +993,14 @@ COMMAND_HANDLER(handle_help_add_command) } // save help text and remove it from argument list - const char *help_text = CMD_ARGV[--CMD_ARGC]; + const char *str = CMD_ARGV[--CMD_ARGC]; + const char *help = !strcmp(CMD_NAME, "add_help_text") ? str : NULL; + const char *usage = !strcmp(CMD_NAME, "add_usage_text") ? str : NULL; + if (!help && !usage) + { + LOG_ERROR("command name '%s' is unknown", CMD_NAME); + return ERROR_INVALID_ARGUMENTS; + } // likewise for the leaf command name const char *cmd_name = CMD_ARGV[--CMD_ARGC]; @@ -991,7 +1012,7 @@ COMMAND_HANDLER(handle_help_add_command) if (ERROR_OK != retval) return retval; } - return help_add_command(CMD_CTX, c, cmd_name, help_text, NULL); + return help_add_command(CMD_CTX, c, cmd_name, help, usage); } /* sleep command sleeps for <n> miliseconds @@ -1039,6 +1060,13 @@ static const struct command_registration command_builtin_handlers[] = { .usage = "<command> [...] <help_text>]", }, { + .name = "add_usage_text", + .handler = &handle_help_add_command, + .mode = COMMAND_ANY, + .help = "add new command usage text", + .usage = "<command> [...] <usage_text>]", + }, + { .name = "sleep", .handler = &handle_sleep_command, .mode = COMMAND_ANY, diff --git a/src/helper/startup.tcl b/src/helper/startup.tcl index ede8cdb..5969cfe 100644 --- a/src/helper/startup.tcl +++ b/src/helper/startup.tcl @@ -59,14 +59,15 @@ proc find {filename} { # make sure error message matches original input string return -code error "Can't find $filename" } -add_help_text find "<file> - print full path to file according to OpenOCD search rules" +add_usage_text find "<file>" +add_help_text find "print full path to file according to OpenOCD search rules" # Run script proc script {filename} { source [find $filename] } - -add_help_text script "<filename> - filename of OpenOCD script (tcl) to run" +add_help_text script "filename of OpenOCD script (tcl) to run" +add_usage_text script "<file>" ######### commit 8f5ff3ddcf0ab11b0ec6fc9215144154fb0519f9 Author: Zachary T Welch <zw...@su...> Date: Tue Nov 24 10:58:32 2009 -0800 httpd: use register_commands() Updates httpd_start() to use register_commands() for 'readform' and 'writeform' commands. Adds server/httpd.h to export the new signatures for this function (and httpd_stop), which allows removing the obsoleted declarations inside openocd.c. diff --git a/src/openocd.c b/src/openocd.c index 63289e4..e38c84e 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -41,6 +41,7 @@ #include "telnet_server.h" #include "gdb_server.h" #include "tcl_server.h" +#include "httpd.h" #ifdef HAVE_STRINGS_H #include <strings.h> @@ -216,10 +217,6 @@ struct command_context *setup_command_handler(void) return cmd_ctx; } -int httpd_start(void); -void httpd_stop(void); - - #if !BUILD_HTTPD && !BUILD_ECOSBOARD /* implementations of OpenOCD that uses multithreading needs to know when * OpenOCD is sleeping. No-op in vanilla OpenOCD @@ -269,7 +266,7 @@ int openocd_main(int argc, char *argv[]) return EXIT_FAILURE; #if BUILD_HTTPD - if (httpd_start() != ERROR_OK) + if (httpd_start(cmd_ctx) != ERROR_OK) return EXIT_FAILURE; #endif diff --git a/src/server/Makefile.am b/src/server/Makefile.am index bb7d5ef..95fb519 100644 --- a/src/server/Makefile.am +++ b/src/server/Makefile.am @@ -14,6 +14,7 @@ libserver_la_SOURCES = server.c telnet_server.c gdb_server.c if HTTPD libserver_la_SOURCES += httpd.c endif +noinst_HEADERS += httpd.h libserver_la_CFLAGS = if IS_MINGW diff --git a/src/server/httpd.c b/src/server/httpd.c index 1c5e6d2..8c1d3db 100644 --- a/src/server/httpd.c +++ b/src/server/httpd.c @@ -460,7 +460,25 @@ static int ahc_echo(void * cls, struct MHD_Connection * connection, static struct MHD_Daemon * d; -int httpd_start(void) +static const struct command_registration httpd_command_handlers[] = { + { + .name = "formfetch", + .jim_handler = &httpd_Jim_Command_formfetch, + .mode = COMMAND_EXEC, + .usage = "<parameter_name>", + .help = "Reads a posted form value.", + }, + { + .name = "writeform", + .jim_handler = &httpd_Jim_Command_writeform, + .mode = COMMAND_EXEC, + .usage = "<parameter_name> <file>", + .help = "Writes a form value to a file.", + }, + COMMAND_REGISTRATION_DONE +}; + +int httpd_start(struct command_context *cmd_ctx) { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); @@ -475,20 +493,7 @@ int httpd_start(void) if (d == NULL) return ERROR_FAIL; - Jim_CreateCommand(interp, - "formfetch", - httpd_Jim_Command_formfetch, - NULL, - NULL); - - Jim_CreateCommand(interp, - "writeform", - httpd_Jim_Command_writeform, - NULL, - NULL); - - - return ERROR_OK; + return register_commands(cmd_ctx, NULL, httpd_command_handlers); } void httpd_stop(void) diff --git a/src/server/httpd.h b/src/server/httpd.h new file mode 100644 index 0000000..0502deb --- /dev/null +++ b/src/server/httpd.h @@ -0,0 +1,28 @@ +/*************************************************************************** + * Copyright (C) 2009 Zachary T Welch <zw...@su...> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef OPENOCD_SERVER_HTTPD_H +#define OPENOCD_SERVER_HTTPD_H + +struct command_context; + +int httpd_start(struct command_context *cmd_ctx); +void httpd_stop(void); + +#endif // OPENOCD_SERVER_HTTPD_H commit 17a9dea53a71e9d7e241262725f3dd707b620d37 Author: Zachary T Welch <zw...@su...> Date: Mon Nov 23 15:03:04 2009 -0800 add jim_handler to command_registration Adding jim_handler field to command_registration allows removing the register_jim helper. All command registrations now go through the register_command{,s}() functions. diff --git a/src/flash/flash.c b/src/flash/flash.c index 4584c5d..bbdbaa8 100644 --- a/src/flash/flash.c +++ b/src/flash/flash.c @@ -1368,8 +1368,6 @@ static const struct command_registration flash_exec_command_handlers[] = { int flash_init_drivers(struct command_context *cmd_ctx) { - register_jim(cmd_ctx, "ocd_flash_banks", - jim_flash_banks, "return information about the flash banks"); if (!flash_banks) return ERROR_OK; @@ -1377,7 +1375,6 @@ int flash_init_drivers(struct command_context *cmd_ctx) return register_commands(cmd_ctx, parent, flash_exec_command_handlers); } - static const struct command_registration flash_config_command_handlers[] = { { .name = "bank", @@ -1389,6 +1386,12 @@ static const struct command_registration flash_config_command_handlers[] = { .help = "Define a new bank with the given name, " "using the specified NOR flash driver.", }, + { + .name = "banks", + .mode = COMMAND_ANY, + .jim_handler = &jim_flash_banks, + .help = "return information about the flash banks", + }, COMMAND_REGISTRATION_DONE }; static const struct command_registration flash_command_handlers[] = { diff --git a/src/helper/command.c b/src/helper/command.c index 8d710c9..3cb36ea 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -252,6 +252,8 @@ static struct command *command_new(struct command_context *cmd_ctx, c->usage = strdup(cr->usage); c->parent = parent; c->handler = cr->handler; + c->jim_handler = cr->jim_handler; + c->jim_handler_data = cr->jim_handler_data; c->mode = cr->mode; command_add_child(command_list_for_parent(cmd_ctx, parent), c); @@ -327,16 +329,22 @@ struct command* register_command(struct command_context *context, } c = command_new(context, parent, cr); - /* if allocation failed or it is a placeholder (no handler), we're done */ - if (NULL == c || NULL == c->handler) - return c; + if (NULL == c) + return NULL; - int retval = register_command_handler(c); - if (ERROR_OK != retval) + if (NULL != c->handler) { - unregister_command(context, parent, name); - c = NULL; + int retval = register_command_handler(c); + if (ERROR_OK != retval) + { + unregister_command(context, parent, name); + return NULL; + } } + + if (NULL != cr->jim_handler && NULL == parent) + Jim_CreateCommand(interp, cr->name, cr->jim_handler, cr->jim_handler_data, NULL); + return c; } @@ -882,7 +890,7 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) bool found = true; Jim_Obj *const *start; unsigned count; - if (c->handler) + if (c->handler || c->jim_handler) { // include the command name in the list count = remaining + 1; @@ -900,6 +908,12 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) start = argv; found = false; } + // pass the command through to the intended handler + if (c->jim_handler) + { + interp->cmdPrivData = c->jim_handler_data; + return (*c->jim_handler)(interp, count, start); + } unsigned nwords; const char **words = script_command_args_alloc(count, start, &nwords); @@ -1149,18 +1163,6 @@ void process_jim_events(void) #endif } -void register_jim(struct command_context *cmd_ctx, const char *name, - Jim_CmdProc cmd, const char *help) -{ - Jim_CreateCommand(interp, name, cmd, NULL, NULL); - - Jim_Obj *cmd_list = Jim_NewListObj(interp, NULL, 0); - Jim_ListAppendElement(interp, cmd_list, - Jim_NewStringObj(interp, name, -1)); - - help_add_command(cmd_ctx, NULL, name, help, NULL); -} - #define DEFINE_PARSE_NUM_TYPE(name, type, func, min, max) \ int parse##name(const char *str, type *ul) \ { \ diff --git a/src/helper/command.h b/src/helper/command.h index 2edeca9..84bdb71 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -164,6 +164,8 @@ struct command struct command *parent; struct command *children; command_handler_t handler; + Jim_CmdProc jim_handler; + void *jim_handler_data; enum command_mode mode; struct command *next; }; @@ -198,6 +200,8 @@ char *command_name(struct command *c, char delim); struct command_registration { const char *name; command_handler_t handler; + Jim_CmdProc jim_handler; + void *jim_handler_data; enum command_mode mode; const char *help; /// a string listing the options and arguments, required or optional @@ -319,9 +323,6 @@ void process_jim_events(void); extern Jim_Interp *interp; -void register_jim(struct command_context *context, const char *name, - Jim_CmdProc cmd, const char *help); - int parse_ulong(const char *str, unsigned long *ul); int parse_ullong(const char *str, unsigned long long *ul); diff --git a/src/helper/ioutil.c b/src/helper/ioutil.c index 58521ee..e13f590 100644 --- a/src/helper/ioutil.c +++ b/src/helper/ioutil.c @@ -685,27 +685,51 @@ static const struct command_registration ioutil_command_handlers[] = { .mode = COMMAND_ANY, .help = "display available ram memory", }, + // jim handlers + { + .name = "rm", + .mode = COMMAND_ANY, + .jim_handler = &zylinjtag_Jim_Command_rm, + .help = "remove a file", + .usage = "<file>", + }, + { + .name = "peek", + .mode = COMMAND_ANY, + .jim_handler = &zylinjtag_Jim_Command_peek, + .help = "peek at a memory address", + .usage = "<addr>", + }, + { + .name = "poke", + .mode = COMMAND_ANY, + .jim_handler = &zylinjtag_Jim_Command_poke, + .help = "poke at a memory address", + .usage = "<addr> <value>", + }, + { + .name = "ls", + .mode = COMMAND_ANY, + .jim_handler = &zylinjtag_Jim_Command_ls, + .help = "show a listing of files", + .usage = "<dir>", + }, + { + .name = "mac", + .mode = COMMAND_ANY, + .jim_handler = &zylinjtag_Jim_Command_mac, + .help = "show MAC address", + }, + { + .name = "ip", + .jim_handler = &zylinjtag_Jim_Command_ip, + .mode = COMMAND_ANY, + .help = "show IP address", + }, COMMAND_REGISTRATION_DONE }; - int ioutil_init(str... [truncated message content] |