helper: command: rewrite common command_print()

Avoid code duplication by merging command_print() and
command_print_sameline().

Detect the allocation error, keep track of it and let the command
return error.

Add a FIXME as the functions should always have 'cmd' properly
set. Should this be an assert()?

Change-Id: Iff704c42969a7ca9ea884520942adecd40bebbd6
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/9090
Tested-by: jenkins
This commit is contained in:
Antonio Borneo
2025-08-18 11:49:49 +02:00
parent 6420e83aff
commit 1dedd6918b
2 changed files with 53 additions and 24 deletions
+48 -24
View File
@@ -345,44 +345,60 @@ void command_output_text(struct command_context *context, const char *data)
context->output_handler(context, data);
}
static void command_vprint(struct command_invocation *cmd,
va_list ap, const char *format, bool add_lf)
{
/*
* FIXME: Why this check on !cmd ?
* Commit 7f260f5009a7 that introduces it, does not explain why!
* Was author not confident on the code change?
*/
if (!cmd)
return;
// Quit on previous allocation error
if (cmd->output == CMD_PRINT_OOM)
return;
char *string = alloc_vprintf(format, ap);
if (!string)
goto alloc_error;
char *output = cmd->output ? cmd->output : "";
output = alloc_printf("%s%s%s", output, string, add_lf ? "\n" : "");
free(string);
if (!output)
goto alloc_error;
free(cmd->output);
cmd->output = output;
return;
alloc_error:
LOG_ERROR("Out of memory");
free(cmd->output);
cmd->output = CMD_PRINT_OOM;
}
void command_print_sameline(struct command_invocation *cmd, const char *format, ...)
{
char *string;
va_list ap;
va_start(ap, format);
string = alloc_vprintf(format, ap);
if (string && cmd) {
char *output = cmd->output ? cmd->output : "";
output = alloc_printf("%s%s", output, string);
if (output) {
free(cmd->output);
cmd->output = output;
}
free(string);
}
bool add_lf = false;
command_vprint(cmd, ap, format, add_lf);
va_end(ap);
}
void command_print(struct command_invocation *cmd, const char *format, ...)
{
char *string;
va_list ap;
va_start(ap, format);
string = alloc_vprintf(format, ap);
if (string && cmd) {
char *output = cmd->output ? cmd->output : "";
output = alloc_printf("%s%s\n", output, string);
if (output) {
free(cmd->output);
cmd->output = output;
}
free(string);
}
bool add_lf = true;
command_vprint(cmd, ap, format, add_lf);
va_end(ap);
}
@@ -435,6 +451,14 @@ static int jim_exec_command(Jim_Interp *interp, struct command_context *context,
};
int retval = c->handler(&cmd);
// Handle allocation error in command_print()
if (cmd.output == CMD_PRINT_OOM) {
cmd.output = NULL;
if (retval == ERROR_OK)
retval = ERROR_FAIL;
}
if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
// Print command syntax
Jim_EvalObjPrefix(context->interp, Jim_NewStringObj(context->interp, "usage", -1), 1, argv);
+5
View File
@@ -83,6 +83,11 @@ struct command_invocation {
char *output;
};
/**
* Assigned to command_invocation::output on allocation error
*/
#define CMD_PRINT_OOM ((char *)(-1L))
/**
* Return true if the command @c cmd is registered by OpenOCD.
*/