X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fhelper%2Fcommand.h;h=796cd9d3b3860b10f465d0627ca9ad00cd4a5b10;hp=1a26c069956af15e6d3302b444ccc5ff8d8e4aca;hb=0184ddba186fa618775865792e1eda9e86d9bb91;hpb=bb9d9c60264a905926e0d15f84842858d0de80b7 diff --git a/src/helper/command.h b/src/helper/command.h index 1a26c06995..796cd9d3b3 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -22,7 +22,12 @@ #ifndef OPENOCD_HELPER_COMMAND_H #define OPENOCD_HELPER_COMMAND_H -#include +#include +#include + +#include +#include +#include /* To achieve C99 printf compatibility in MinGW, gnu_printf should be * used for __attribute__((format( ... ))), with GCC v4.4 or later @@ -33,10 +38,20 @@ #define PRINTF_ATTRIBUTE_FORMAT printf #endif +/** + * OpenOCD command mode is COMMAND_CONFIG at start, then switches to COMMAND_EXEC + * during the execution of command 'init'. + * The field 'mode' in struct command_registration specifies in which command mode + * the command can be executed: + * - during COMMAND_CONFIG only, + * - during COMMAND_EXEC only, + * - in both modes (COMMAND_ANY). + */ enum command_mode { COMMAND_EXEC, COMMAND_CONFIG, COMMAND_ANY, + COMMAND_UNKNOWN = -1, /* error condition */ }; struct command_context; @@ -48,7 +63,6 @@ typedef int (*command_output_handler_t)(struct command_context *context, struct command_context { Jim_Interp *interp; enum command_mode mode; - struct command *commands; struct target *current_target; /* The target set by 'targets xx' command or the latest created */ struct target *current_target_override; @@ -60,6 +74,7 @@ struct command_context { */ command_output_handler_t output_handler; void *output_handler_priv; + struct list_head *help_list; }; struct command; @@ -75,8 +90,20 @@ struct command_invocation { const char *name; unsigned argc; const char **argv; + Jim_Obj *output; }; +/** + * Return true if the command @c cmd is registered by OpenOCD. + */ +bool jimcmd_is_oocd_command(Jim_Cmd *cmd); + +/** + * Return the pointer to the command's private data specified during the + * registration of command @a cmd . + */ +void *jimcmd_privdata(Jim_Cmd *cmd); + /** * Command handlers may be defined with more parameters than the base * set provided by command.c. This macro uses C99 magic to allow @@ -117,6 +144,11 @@ struct command_invocation { */ #define COMMAND_HELPER(name, extra ...) __COMMAND_HANDLER(name, extra) +/** + * Use this macro to access the command being handled, + * rather than accessing the variable directly. It may be moved. + */ +#define CMD (cmd) /** * Use this macro to access the context of the command being handled, * rather than accessing the variable directly. It may be moved. @@ -158,7 +190,7 @@ struct command_invocation { * * This is *especially* important for commands such as writing * to flash or verifying memory. The reason is that those commands - * can be used by programs to determine if the operation succeded + * can be used by programs to determine if the operation succeeded * or not. If the operation failed, then a program can try * an alternative approach. * @@ -169,37 +201,29 @@ typedef __COMMAND_HANDLER((*command_handler_t)); struct command { char *name; - char *help; - char *usage; - struct command *parent; - struct command *children; command_handler_t handler; Jim_CmdProc *jim_handler; void *jim_handler_data; - /* Currently used only for target of target-prefixed cmd. - * Native OpenOCD commands use jim_handler_data exclusively - * as a target override. - * Jim handlers outside of target cmd tree can use - * jim_handler_data for any handler specific data */ + /* Command handlers can use it for any handler specific data */ + struct target *jim_override_target; + /* Used only for target of target-prefixed cmd */ enum command_mode mode; - struct command *next; }; -/** - * @param c The command to be named. - * @param delim The character to place between command names. - * @returns A malloc'd string containing the full command name, - * which may include one or more ancestor components. Multiple names - * are separated by single spaces. The caller must free() the string - * when done with it. +/* + * Return the struct command pointer kept in private data + * Used to enforce check on data type */ -char *command_name(struct command *c, char delim); +static inline struct command *jim_to_command(Jim_Interp *interp) +{ + return Jim_CmdPrivData(interp); +} /* * Commands should be registered by filling in one or more of these - * structures and passing them to register_command(). + * structures and passing them to [un]register_commands(). * - * A conventioal format should be used for help strings, to provide both + * A conventional format should be used for help strings, to provide both * usage and basic information: * @code * "@ ... - some explanation text" @@ -216,7 +240,6 @@ 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 */ @@ -234,23 +257,9 @@ struct command_registration { /** Use this as the last entry in an array of command_registration records. */ #define COMMAND_REGISTRATION_DONE { .name = NULL, .chain = NULL } -/** - * Register a command @c handler that can be called from scripts during - * the execution @c mode specified. - * - * If @c parent is non-NULL, the new command will be registered as a - * sub-command under it; otherwise, it will be available as a top-level - * command. - * - * @param cmd_ctx The command_context in which to register the command. - * @param parent Register this command as a child of this, or NULL to - * register a top-level command. - * @param rec A command_registration record that contains the desired - * command parameters. - * @returns The new command, if successful; otherwise, NULL. - */ -struct command *register_command(struct command_context *cmd_ctx, - struct command *parent, const struct command_registration *rec); +int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, + const struct command_registration *cmds, void *data, + struct target *override_target); /** * Register one or more commands in the specified context, as children @@ -260,49 +269,77 @@ struct command *register_command(struct command_context *cmd_ctx, * Otherwise, the chained commands are added as children of the command. * * @param cmd_ctx The command_context in which to register the command. - * @param parent Register this command as a child of this, or NULL to + * @param cmd_prefix Register this command as a child of this, or NULL to * register a top-level command. * @param cmds Pointer to an array of command_registration records that * contains the desired command parameters. The last record must have * NULL for all fields. * @returns ERROR_OK on success; ERROR_FAIL if any registration fails. */ -int register_commands(struct command_context *cmd_ctx, struct command *parent, - const struct command_registration *cmds); +static inline int register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, + const struct command_registration *cmds) +{ + return __register_commands(cmd_ctx, cmd_prefix, cmds, NULL, NULL); +} +/** + * Register one or more commands, as register_commands(), plus specify + * that command should override the current target + * + * @param cmd_ctx The command_context in which to register the command. + * @param cmd_prefix Register this command as a child of this, or NULL to + * register a top-level command. + * @param cmds Pointer to an array of command_registration records that + * contains the desired command parameters. The last record must have + * NULL for all fields. + * @param target The target that has to override current target. + * @returns ERROR_OK on success; ERROR_FAIL if any registration fails. + */ +static inline int register_commands_override_target(struct command_context *cmd_ctx, + const char *cmd_prefix, const struct command_registration *cmds, + struct target *target) +{ + return __register_commands(cmd_ctx, cmd_prefix, cmds, NULL, target); +} /** - * Unregisters command @c name from the given context, @c cmd_ctx. - * @param cmd_ctx The context of the registered command. - * @param parent The parent of the given command, or NULL. - * @param name The name of the command to unregister. - * @returns ERROR_OK on success, or an error code. + * Register one or more commands, as register_commands(), plus specify + * a pointer to command private data that would be accessible through + * the macro CMD_DATA. The private data will not be freed when command + * is unregistered. + * + * @param cmd_ctx The command_context in which to register the command. + * @param cmd_prefix Register this command as a child of this, or NULL to + * register a top-level command. + * @param cmds Pointer to an array of command_registration records that + * contains the desired command parameters. The last record must have + * NULL for all fields. + * @param data The command private data. + * @returns ERROR_OK on success; ERROR_FAIL if any registration fails. */ -int unregister_command(struct command_context *cmd_ctx, - struct command *parent, const char *name); +static inline int register_commands_with_data(struct command_context *cmd_ctx, + const char *cmd_prefix, const struct command_registration *cmds, + void *data) +{ + return __register_commands(cmd_ctx, cmd_prefix, cmds, data, NULL); +} + /** - * Unregisters all commands from the specfied context. + * Unregisters all commands from the specified context. * @param cmd_ctx The context that will be cleared of registered commands. - * @param parent If given, only clear commands from under this one command. + * @param cmd_prefix If given, only clear commands from under this one command. * @returns ERROR_OK on success, or an error code. */ int unregister_all_commands(struct command_context *cmd_ctx, - struct command *parent); - -struct command *command_find_in_context(struct command_context *cmd_ctx, - const char *name); -struct command *command_find_in_parent(struct command *parent, - const char *name); + const char *cmd_prefix); /** - * Update the private command data field for a command and all descendents. - * This is used when creating a new heirarchy of commands that depends - * on obtaining a dynamically created context. The value will be available - * in command handlers by using the CMD_DATA macro. - * @param c The command (group) whose data pointer(s) will be updated. - * @param p The new data pointer to use for the command or its descendents. + * Unregisters the help for all commands. Used at exit to remove the help + * added through the commands 'add_help_text' and 'add_usage_text'. + * @param cmd_ctx The context that will be cleared of registered helps. + * @returns ERROR_OK on success, or an error code. */ -void command_set_handler_data(struct command *c, void *p); +int help_del_all_commands(struct command_context *cmd_ctx); void command_set_output_handler(struct command_context *context, command_output_handler_t output_handler, void *priv); @@ -344,9 +381,9 @@ struct command_context *copy_command_context(struct command_context *cmd_ctx); */ void command_done(struct command_context *context); -void command_print(struct command_context *context, const char *format, ...) +void command_print(struct command_invocation *cmd, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3))); -void command_print_sameline(struct command_context *context, const char *format, ...) +void command_print_sameline(struct command_invocation *cmd, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3))); int command_run_line(struct command_context *context, char *line); int command_run_linef(struct command_context *context, const char *format, ...) @@ -393,14 +430,14 @@ DECLARE_PARSE_WRAPPER(_target_addr, target_addr_t); * * This function may cause the calling function to return immediately, * so it should be used carefully to avoid leaking resources. In most - * situations, parsing should be completed in full before proceding + * situations, parsing should be completed in full before proceeding * to allocate resources, and this strategy will most prevents leaks. */ #define COMMAND_PARSE_NUMBER(type, in, out) \ do { \ int retval_macro_tmp = parse_ ## type(in, &(out)); \ - if (ERROR_OK != retval_macro_tmp) { \ - command_print(CMD_CTX, stringify(out) \ + if (retval_macro_tmp != ERROR_OK) { \ + command_print(CMD, stringify(out) \ " option value ('%s') is not valid", in); \ return retval_macro_tmp; \ } \ @@ -409,6 +446,48 @@ DECLARE_PARSE_WRAPPER(_target_addr, target_addr_t); #define COMMAND_PARSE_ADDRESS(in, out) \ COMMAND_PARSE_NUMBER(target_addr, in, out) +/** + * @brief parses the command argument at position @a argn into @a out + * as a @a type, or prints a command error referring to @a name_str + * and passes the error code to the caller. @a argn will be incremented + * if no error occurred. Otherwise the calling function will return + * the error code produced by the parsing function. + * + * This function may cause the calling function to return immediately, + * so it should be used carefully to avoid leaking resources. In most + * situations, parsing should be completed in full before proceeding + * to allocate resources, and this strategy will most prevents leaks. + */ +#define COMMAND_PARSE_ADDITIONAL_NUMBER(type, argn, out, name_str) \ + do { \ + if (argn+1 >= CMD_ARGC || CMD_ARGV[argn+1][0] == '-') { \ + command_print(CMD, "no " name_str " given"); \ + return ERROR_FAIL; \ + } \ + ++argn; \ + COMMAND_PARSE_NUMBER(type, CMD_ARGV[argn], out); \ + } while (0) + +/** + * @brief parses the command argument at position @a argn into @a out + * as a @a type if the argument @a argn does not start with '-'. + * and passes the error code to the caller. @a argn will be incremented + * if no error occurred. Otherwise the calling function will return + * the error code produced by the parsing function. + * + * This function may cause the calling function to return immediately, + * so it should be used carefully to avoid leaking resources. In most + * situations, parsing should be completed in full before proceeding + * to allocate resources, and this strategy will most prevents leaks. + */ +#define COMMAND_PARSE_OPTIONAL_NUMBER(type, argn, out) \ + do { \ + if (argn+1 < CMD_ARGC && CMD_ARGV[argn+1][0] != '-') { \ + ++argn; \ + COMMAND_PARSE_NUMBER(type, CMD_ARGV[argn], out); \ + } \ + } while (0) + /** * Parse the string @c as a binary parameter, storing the boolean value * in @c out. The strings @c on and @c off are used to match different @@ -419,10 +498,10 @@ DECLARE_PARSE_WRAPPER(_target_addr, target_addr_t); do { \ bool value; \ int retval_macro_tmp = command_parse_bool_arg(in, &value); \ - if (ERROR_OK != retval_macro_tmp) { \ - command_print(CMD_CTX, stringify(out) \ + if (retval_macro_tmp != ERROR_OK) { \ + command_print(CMD, stringify(out) \ " option value ('%s') is not valid", in); \ - command_print(CMD_CTX, " choices are '%s' or '%s'", \ + command_print(CMD, " choices are '%s' or '%s'", \ on, off); \ return retval_macro_tmp; \ } \ @@ -439,7 +518,4 @@ COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label); #define COMMAND_PARSE_ENABLE(in, out) \ COMMAND_PARSE_BOOL(in, out, "enable", "disable") -void script_debug(Jim_Interp *interp, const char *cmd, - unsigned argc, Jim_Obj * const *argv); - #endif /* OPENOCD_HELPER_COMMAND_H */