FRONTPANEL: sim_frontpanel API release 10

- Reworked STEP, HALT, BOOT, and RUN API's to properly interlock with
   the receive thread.
- Shorten destroy delay while debugging to 1 second.
- Allow execution and text breakpoints to be set and/or cleared while
   simulator is running.
This commit is contained in:
Mark Pizzolato 2017-12-15 13:57:20 -08:00
parent 634a92f8bf
commit 2de2b9bd80
3 changed files with 152 additions and 91 deletions

View file

@ -438,11 +438,11 @@ if (sim_panel_add_register_bits (panel, "PCQ[3]", NULL, 32, PCQ_3_bits)) {
goto Done; goto Done;
} }
if (1) { if (1) {
unsigned int noop_noop_noop_halt = 0x00010101, addr400 = 0x00000400, pc_value; unsigned int noop_noop_noop_halt = 0x00010101, brb_self = 0x0000FE11, addr400 = 0x00000400, pc_value;
int mstime = 0; int mstime = 0;
if (sim_panel_mem_deposit (panel, sizeof(addr400), &addr400, sizeof(noop_noop_noop_halt), &noop_noop_noop_halt)) { if (sim_panel_mem_deposit (panel, sizeof(addr400), &addr400, sizeof(noop_noop_noop_halt), &noop_noop_noop_halt)) {
printf ("Error setting 00000000 to %08X: %s\n", noop_noop_noop_halt, sim_panel_get_error()); printf ("Error setting %08X to %08X: %s\n", addr400, noop_noop_noop_halt, sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_gen_deposit (panel, "PC", sizeof(addr400), &addr400)) { if (sim_panel_gen_deposit (panel, "PC", sizeof(addr400), &addr400)) {
@ -488,6 +488,31 @@ if (1) {
printf ("Unexpected PC value after STEP: %08X, expected: %08X\n", pc_value, addr400 + 1); printf ("Unexpected PC value after STEP: %08X, expected: %08X\n", pc_value, addr400 + 1);
goto Done; goto Done;
} }
if (sim_panel_mem_deposit (panel, sizeof(addr400), &addr400, sizeof(brb_self), &brb_self)) {
printf ("Error setting %08X to %08X: %s\n", addr400, brb_self, sim_panel_get_error());
goto Done;
}
if (sim_panel_gen_deposit (panel, "PC", sizeof(addr400), &addr400)) {
printf ("Error setting PC to %08X: %s\n", addr400, sim_panel_get_error());
goto Done;
}
if (sim_panel_exec_run(panel)) {
printf ("Error starting simulator execution: %s\n", sim_panel_get_error());
goto Done;
}
while ((sim_panel_get_state (panel) == Run) &&
(mstime < 1000)) {
usleep (100000);
mstime += 100;
}
if (sim_panel_exec_halt (panel)) {
printf ("Error executing halt: %s\n", sim_panel_get_error());
goto Done;
}
if (sim_panel_get_state (panel) != Halt) {
printf ("State not Halt after successful Halt\n");
goto Done;
}
} }
return 0; return 0;
@ -511,7 +536,7 @@ if (panel_setup())
if (1) { if (1) {
struct { struct {
unsigned int addr; unsigned int addr;
char *instr; const char *instr;
} long_running_program[] = { } long_running_program[] = {
{0x2000, "MOVL #7FFFFFFF,R0"}, {0x2000, "MOVL #7FFFFFFF,R0"},
{0x2007, "MOVL #7FFFFFFF,R1"}, {0x2007, "MOVL #7FFFFFFF,R1"},
@ -522,7 +547,7 @@ if (1) {
}; };
int i; int i;
sim_panel_debug (panel, "Testing sim_panel_destroy() with simulator in Run State"); sim_panel_debug (panel, "Testing sim_panel_exec_halt and sim_panel_destroy() () with simulator in Run State");
for (i=0; long_running_program[i].instr; i++) for (i=0; long_running_program[i].instr; i++)
if (sim_panel_mem_deposit_instruction (panel, sizeof(long_running_program[i].addr), if (sim_panel_mem_deposit_instruction (panel, sizeof(long_running_program[i].addr),
&long_running_program[i].addr, long_running_program[i].instr)) { &long_running_program[i].addr, long_running_program[i].instr)) {
@ -538,6 +563,17 @@ if (1) {
printf ("Error starting simulator execution: %s\n", sim_panel_get_error()); printf ("Error starting simulator execution: %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
usleep (100000); /* .1 seconds */
sim_panel_debug (panel, "Testing sim_panel_exec_halt");
if (sim_panel_exec_halt (panel)) {
printf ("Error halting simulator execution: %s\n", sim_panel_get_error());
goto Done;
}
sim_panel_debug (panel, "Testing sim_panel_exec_run");
if (sim_panel_exec_run (panel)) {
printf ("Error resuming simulator execution: %s\n", sim_panel_get_error());
goto Done;
}
usleep (2000000); /* 2 Seconds */ usleep (2000000); /* 2 Seconds */
sim_panel_debug (panel, "Shutting down while simulator is running"); sim_panel_debug (panel, "Shutting down while simulator is running");
sim_panel_destroy (panel); sim_panel_destroy (panel);

View file

@ -158,6 +158,7 @@ struct PANEL {
char *io_response; char *io_response;
size_t io_response_data; size_t io_response_data;
size_t io_response_size; size_t io_response_size;
const char *completion_string;
pthread_cond_t io_done; pthread_cond_t io_done;
pthread_cond_t startup_done; pthread_cond_t startup_done;
PANEL_DISPLAY_PCALLBACK callback; PANEL_DISPLAY_PCALLBACK callback;
@ -392,6 +393,8 @@ static void *
_panel_debugflusher(void *arg) _panel_debugflusher(void *arg)
{ {
PANEL *p = (PANEL*)arg; PANEL *p = (PANEL*)arg;
int flush_interval = 15;
int sleeps = 0;
pthread_setspecific (panel_thread_id, "debugflush"); pthread_setspecific (panel_thread_id, "debugflush");
@ -403,7 +406,8 @@ msleep (100);
pthread_mutex_lock (&p->io_lock); pthread_mutex_lock (&p->io_lock);
while (p->sock != INVALID_SOCKET) { while (p->sock != INVALID_SOCKET) {
pthread_mutex_unlock (&p->io_lock); pthread_mutex_unlock (&p->io_lock);
msleep (15000); msleep (1000);
if (0 == (sleeps++)%flush_interval)
sim_panel_flush_debug (p); sim_panel_flush_debug (p);
pthread_mutex_lock (&p->io_lock); pthread_mutex_lock (&p->io_lock);
} }
@ -469,6 +473,9 @@ return sent;
static int static int
_panel_sendf (PANEL *p, int *completion_status, char **response, const char *fmt, ...); _panel_sendf (PANEL *p, int *completion_status, char **response, const char *fmt, ...);
static int
_panel_sendf_completion (PANEL *p, char **response, const char *completion, const char *fmt, ...);
static int static int
_panel_register_query_string (PANEL *panel, char **buf, size_t *buf_size) _panel_register_query_string (PANEL *panel, char **buf, size_t *buf_size)
{ {
@ -1046,15 +1053,8 @@ if (panel) {
sim_panel_set_display_callback_interval (panel, NULL, NULL, 0); sim_panel_set_display_callback_interval (panel, NULL, NULL, 0);
/* Next, attempt a simulator shutdown only with the master panel */ /* Next, attempt a simulator shutdown only with the master panel */
if (panel->parent == NULL) { if (panel->parent == NULL) {
if (panel->State == Run) {
int i;
_panel_send (panel, "\005\r", 2);
for (i=0; (panel->State == Run) && (i < 10); i++)
msleep(100);
if (panel->State == Run) if (panel->State == Run)
_panel_debug (panel, DBG_THR, "Unable to HALT running simulator for shutdown", NULL, 0); sim_panel_exec_halt (panel);
}
_panel_send (panel, "EXIT\r", 5); _panel_send (panel, "EXIT\r", 5);
} }
/* Wait for up to 2 seconds for a graceful shutdown */ /* Wait for up to 2 seconds for a graceful shutdown */
@ -1459,9 +1459,15 @@ if (panel->parent) {
return -1; return -1;
} }
if (panel->State == Run) { if (panel->State == Run) {
if (1 != _panel_send (panel, "\005", 1)) if (_panel_sendf_completion (panel, NULL, sim_prompt, "\005")) {
_panel_debug (panel, DBG_THR, "Error trying to HALT running simulator: %s", NULL, 0, sim_panel_get_error ());
return -1; return -1;
} }
if (panel->State == Run) {
_panel_debug (panel, DBG_THR, "Unable to HALT running simulator", NULL, 0);
return -1;
}
}
return 0; return 0;
} }
@ -1469,6 +1475,7 @@ int
sim_panel_exec_boot (PANEL *panel, const char *device) sim_panel_exec_boot (PANEL *panel, const char *device)
{ {
int cmd_stat; int cmd_stat;
char *response, *simtime;
if (!panel || (panel->State == Error)) { if (!panel || (panel->State == Error)) {
sim_panel_set_error (NULL, "Invalid Panel"); sim_panel_set_error (NULL, "Invalid Panel");
@ -1485,12 +1492,17 @@ if (panel->State == Run) {
/* A BOOT or RUN command will restart the simulator's time base. */ /* A BOOT or RUN command will restart the simulator's time base. */
/* We account for that so that the frontpanel application sees ever */ /* We account for that so that the frontpanel application sees ever */
/* increasing time values when register data is delivered. */ /* increasing time values when register data is delivered. */
if (_panel_sendf (panel, &cmd_stat, NULL, "SHOW TIME\r")) if (_panel_sendf (panel, &cmd_stat, &response, "SHOW TIME\r"))
return -1; return -1;
panel->simulation_time_base += panel->simulation_time; if ((simtime = strstr (response, "Time:"))) {
if (_panel_sendf (panel, NULL, NULL, "BOOT %s\r", device)) panel->simulation_time = strtoull (simtime + 5, NULL, 10);
panel->simulation_time_base += panel->simulation_time;
}
free (response);
if (_panel_sendf_completion (panel, NULL, "Simulator Running...", "BOOT %s\r", device)) {
_panel_debug (panel, DBG_THR, "Unable to BOOT simulator: %s", NULL, 0, sim_panel_get_error());
return -1; return -1;
msleep (100); /* Allow Run/Hslt state to settle */ }
return 0; return 0;
} }
@ -1498,6 +1510,7 @@ int
sim_panel_exec_start (PANEL *panel) sim_panel_exec_start (PANEL *panel)
{ {
int cmd_stat; int cmd_stat;
char *response, *simtime;
if (!panel || (panel->State == Error)) { if (!panel || (panel->State == Error)) {
sim_panel_set_error (NULL, "Invalid Panel"); sim_panel_set_error (NULL, "Invalid Panel");
@ -1514,12 +1527,20 @@ if (panel->State == Run) {
/* A BOOT or RUN command will restart the simulator's time base. */ /* A BOOT or RUN command will restart the simulator's time base. */
/* We account for that so that the frontpanel application sees ever */ /* We account for that so that the frontpanel application sees ever */
/* increasing time values when register data is delivered. */ /* increasing time values when register data is delivered. */
if (_panel_sendf (panel, &cmd_stat, NULL, "SHOW TIME\r")) if (_panel_sendf (panel, &cmd_stat, &response, "SHOW TIME\r")) {
_panel_debug (panel, DBG_THR, "Unable to send SHOW TIME command while starting simulator: %s", NULL, 0, sim_panel_get_error());
return -1; return -1;
}
if ((simtime = strstr (response, "Time:"))) {
panel->simulation_time = strtoull (simtime + 5, NULL, 10);
panel->simulation_time_base += panel->simulation_time;
}
free (response);
panel->simulation_time_base += panel->simulation_time; panel->simulation_time_base += panel->simulation_time;
if (_panel_sendf (panel, NULL, NULL, "RUN -Q\r", 5)) if (_panel_sendf_completion (panel, NULL, "Simulator Running...", "RUN -Q\r", 5)) {
_panel_debug (panel, DBG_THR, "Unable to start simulator: %s", NULL, 0, sim_panel_get_error());
return -1; return -1;
msleep (100); /* Allow Run/Hslt state to settle */ }
return 0; return 0;
} }
@ -1538,9 +1559,8 @@ if (panel->State == Run) {
sim_panel_set_error (NULL, "Not Halted"); sim_panel_set_error (NULL, "Not Halted");
return -1; return -1;
} }
if (_panel_sendf (panel, NULL, NULL, "CONT\r", 5)) if (_panel_sendf_completion (panel, NULL, "Simulator Running...", "CONT\r"))
return -1; return -1;
msleep (100); /* Allow Run/Hslt state to settle */
return 0; return 0;
} }
@ -1559,9 +1579,10 @@ if (panel->State == Run) {
sim_panel_set_error (NULL, "Not Halted"); sim_panel_set_error (NULL, "Not Halted");
return -1; return -1;
} }
if (_panel_sendf_completion (panel, NULL, sim_prompt, "STEP")) {
if (5 != _panel_send (panel, "STEP\r", 5)) _panel_debug (panel, DBG_THR, "Error trying to STEP running simulator: %s", NULL, 0, sim_panel_get_error ());
return -1; return -1;
}
return 0; return 0;
} }
@ -1579,11 +1600,6 @@ if (panel->parent) {
sim_panel_set_error (NULL, "Can't establish a breakpoint from device front panel"); sim_panel_set_error (NULL, "Can't establish a breakpoint from device front panel");
return -1; return -1;
} }
if (panel->State == Run) {
sim_panel_set_error (NULL, "Not Halted");
return -1;
}
if ((_panel_sendf (panel, &cmd_stat, &response, "BREAK %s\r", condition)) || if ((_panel_sendf (panel, &cmd_stat, &response, "BREAK %s\r", condition)) ||
(*response)) { (*response)) {
sim_panel_set_error (NULL, "Error establishing breakpoint at '%s': %s", condition, response ? response : ""); sim_panel_set_error (NULL, "Error establishing breakpoint at '%s': %s", condition, response ? response : "");
@ -1608,11 +1624,6 @@ if (panel->parent) {
sim_panel_set_error (NULL, "Can't clear a breakpoint from device front panel"); sim_panel_set_error (NULL, "Can't clear a breakpoint from device front panel");
return -1; return -1;
} }
if (panel->State == Run) {
sim_panel_set_error (NULL, "Not Halted");
return -1;
}
if ((_panel_sendf (panel, &cmd_stat, &response, "NOBREAK %s\r", condition)) || if ((_panel_sendf (panel, &cmd_stat, &response, "NOBREAK %s\r", condition)) ||
(*response)) { (*response)) {
sim_panel_set_error (NULL, "Error clearing breakpoint at '%s': %s", condition, response ? response : ""); sim_panel_set_error (NULL, "Error clearing breakpoint at '%s': %s", condition, response ? response : "");
@ -1637,11 +1648,6 @@ if (panel->parent) {
sim_panel_set_error (NULL, "Can't establish an output breakpoint from device front panel"); sim_panel_set_error (NULL, "Can't establish an output breakpoint from device front panel");
return -1; return -1;
} }
if (panel->State == Run) {
sim_panel_set_error (NULL, "Not Halted");
return -1;
}
if ((_panel_sendf (panel, &cmd_stat, &response, "EXPECT %s\r", condition)) || if ((_panel_sendf (panel, &cmd_stat, &response, "EXPECT %s\r", condition)) ||
(*response)) { (*response)) {
sim_panel_set_error (NULL, "Error establishing output breakpoint for '%s': %s", condition, response ? response : ""); sim_panel_set_error (NULL, "Error establishing output breakpoint for '%s': %s", condition, response ? response : "");
@ -1666,11 +1672,6 @@ if (panel->parent) {
sim_panel_set_error (NULL, "Can't clear an output breakpoint from device front panel"); sim_panel_set_error (NULL, "Can't clear an output breakpoint from device front panel");
return -1; return -1;
} }
if (panel->State == Run) {
sim_panel_set_error (NULL, "Not Halted");
return -1;
}
if ((_panel_sendf (panel, &cmd_stat, &response, "NOEXPECT %s\r", condition)) || if ((_panel_sendf (panel, &cmd_stat, &response, "NOEXPECT %s\r", condition)) ||
(*response)) { (*response)) {
sim_panel_set_error (NULL, "Error clearing output breakpoint for '%s': %s", condition, response ? response : ""); sim_panel_set_error (NULL, "Error clearing output breakpoint for '%s': %s", condition, response ? response : "");
@ -1962,17 +1963,9 @@ if (!panel || (panel->State == Error)) {
sim_panel_set_error (NULL, "Invalid Panel"); sim_panel_set_error (NULL, "Invalid Panel");
return -1; return -1;
} }
pthread_mutex_lock (&panel->io_lock);
OrigState = panel->State; OrigState = panel->State;
if (OrigState == Run) { if (OrigState == Run)
sim_panel_exec_halt (panel); sim_panel_exec_halt (panel);
while (panel->State == Run) {
pthread_mutex_unlock (&panel->io_lock);
msleep (100);
pthread_mutex_lock (&panel->io_lock);
}
}
pthread_mutex_unlock (&panel->io_lock);
do { do {
if (_panel_sendf (panel, &cmd_stat, &response, "ATTACH %s %s %s", switches, device, path)) { if (_panel_sendf (panel, &cmd_stat, &response, "ATTACH %s %s %s", switches, device, path)) {
stat = -1; stat = -1;
@ -1983,10 +1976,8 @@ do {
stat = -1; stat = -1;
} }
} while (0); } while (0);
pthread_mutex_lock (&panel->io_lock);
if (OrigState == Run) if (OrigState == Run)
sim_panel_exec_run (panel); sim_panel_exec_run (panel);
pthread_mutex_unlock (&panel->io_lock);
free (response); free (response);
return stat; return stat;
} }
@ -2010,17 +2001,9 @@ if (!panel || (panel->State == Error)) {
sim_panel_set_error (NULL, "Invalid Panel"); sim_panel_set_error (NULL, "Invalid Panel");
return -1; return -1;
} }
pthread_mutex_lock (&panel->io_lock);
OrigState = panel->State; OrigState = panel->State;
if (OrigState == Run) { if (OrigState == Run)
sim_panel_exec_halt (panel); sim_panel_exec_halt (panel);
while (panel->State == Run) {
pthread_mutex_unlock (&panel->io_lock);
msleep (100);
pthread_mutex_lock (&panel->io_lock);
}
}
pthread_mutex_unlock (&panel->io_lock);
do { do {
if (_panel_sendf (panel, &cmd_stat, &response, "DETACH %s", device)) { if (_panel_sendf (panel, &cmd_stat, &response, "DETACH %s", device)) {
stat = -1; stat = -1;
@ -2031,10 +2014,8 @@ do {
stat = -1; stat = -1;
} }
} while (0); } while (0);
pthread_mutex_lock (&panel->io_lock);
if (OrigState == Run) if (OrigState == Run)
sim_panel_exec_run (panel); sim_panel_exec_run (panel);
pthread_mutex_unlock (&panel->io_lock);
free (response); free (response);
return stat; return stat;
} }
@ -2302,6 +2283,13 @@ Start_Next_Line:
buf_data = strlen (buf); buf_data = strlen (buf);
if (buf_data) if (buf_data)
_panel_debug (p, DBG_RSP, "Remnant Buffer Contents: '%s'", NULL, 0, buf); _panel_debug (p, DBG_RSP, "Remnant Buffer Contents: '%s'", NULL, 0, buf);
if ((!p->parent) &&
(p->completion_string) &&
(!memcmp (buf, p->completion_string, strlen (p->completion_string)))) {
_panel_debug (p, DBG_RCV, "*Received Command Complete - Match: '%s'", NULL, 0, p->completion_string);
p->io_waiting = 0;
pthread_cond_signal (&p->io_done);
}
if (!memcmp ("Simulator Running...", buf, 20)) { if (!memcmp ("Simulator Running...", buf, 20)) {
_panel_debug (p, DBG_RSP, "State transitioning to Run", NULL, 0); _panel_debug (p, DBG_RSP, "State transitioning to Run", NULL, 0);
p->State = Run; p->State = Run;
@ -2513,20 +2501,20 @@ return -1;
} }
static int static int
_panel_sendf (PANEL *p, int *completion_status, char **response, const char *fmt, ...) _panel_vsendf_completion (PANEL *p, int *completion_status, char **response, const char *completion_string, const char *fmt, va_list arglist)
{ {
char stackbuf[1024]; char stackbuf[1024];
int bufsize = sizeof(stackbuf); int bufsize = sizeof(stackbuf);
char *buf = stackbuf; char *buf = stackbuf;
int len, status_echo_len = 0, sent_len; int len, status_echo_len = 0, sent_len;
int post_fix_len = completion_status ? 7 + sizeof (command_done_echo) + sizeof (command_status) : 1; int post_fix_len = completion_status ? 7 + sizeof (command_done_echo) + sizeof (command_status) : 1;
va_list arglist;
int ret; int ret;
if (completion_status && completion_string) /* one or the other, but */
return -1; /* not both */
while (1) { /* format passed string, args */ while (1) { /* format passed string, args */
va_start (arglist, fmt);
len = vsnprintf (buf, bufsize-1, fmt, arglist); len = vsnprintf (buf, bufsize-1, fmt, arglist);
va_end (arglist);
if (len < 0) if (len < 0)
return sim_panel_set_error (NULL, "Format encoding error while processing '%s'", fmt); return sim_panel_set_error (NULL, "Format encoding error while processing '%s'", fmt);
@ -2554,17 +2542,20 @@ if (len && (buf[len-1] != '\r')) {
pthread_mutex_lock (&p->io_command_lock); pthread_mutex_lock (&p->io_command_lock);
++p->command_count; ++p->command_count;
if (completion_status) { if (completion_status || completion_string) {
if (completion_status) {
sprintf (&buf[len], "%s\r%s\r", command_status, command_done_echo); sprintf (&buf[len], "%s\r%s\r", command_status, command_done_echo);
status_echo_len = strlen (&buf[len]); status_echo_len = strlen (&buf[len]);
}
pthread_mutex_lock (&p->io_lock); pthread_mutex_lock (&p->io_lock);
p->completion_string = completion_string;
p->io_response_data = 0; p->io_response_data = 0;
} }
_panel_debug (p, DBG_REQ, "Command %d Request%s: %*.*s", NULL, 0, p->command_count, completion_status ? " (with response)" : "", len, len, buf); _panel_debug (p, DBG_REQ, "Command %d Request%s: %*.*s", NULL, 0, p->command_count, completion_status ? " (with response)" : "", len, len, buf);
ret = ((len + status_echo_len) == (sent_len = _panel_send (p, buf, len + status_echo_len))) ? 0 : -1; ret = ((len + status_echo_len) == (sent_len = _panel_send (p, buf, len + status_echo_len))) ? 0 : -1;
if (completion_status) { if (completion_status || completion_string) {
if (!ret) { /* Sent OK? */ if (!ret) { /* Sent OK? */
char *tresponse = NULL; char *tresponse = NULL;
@ -2575,6 +2566,7 @@ if (completion_status) {
if (0 == memcmp (buf, p->io_response + strlen (sim_prompt), len)) { if (0 == memcmp (buf, p->io_response + strlen (sim_prompt), len)) {
char *eol, *status; char *eol, *status;
memcpy (tresponse, p->io_response + strlen (sim_prompt) + len + 1, p->io_response_data + 1 - (strlen (sim_prompt) + len + 1)); memcpy (tresponse, p->io_response + strlen (sim_prompt) + len + 1, p->io_response_data + 1 - (strlen (sim_prompt) + len + 1));
if (completion_status) {
*completion_status = -1; *completion_status = -1;
status = strstr (tresponse, command_status); status = strstr (tresponse, command_status);
if (status) { if (status) {
@ -2586,18 +2578,27 @@ if (completion_status) {
sscanf (status, "Status:%08X-", completion_status); sscanf (status, "Status:%08X-", completion_status);
} }
} }
}
else else
memcpy (tresponse, p->io_response, p->io_response_data + 1); memcpy (tresponse, p->io_response, p->io_response_data + 1);
if (response) { if (response) {
*response = tresponse; *response = tresponse;
if (completion_status)
_panel_debug (p, DBG_RSP, "Command %d Response(Status=%d): '%s'", NULL, 0, p->command_count, *completion_status, *response); _panel_debug (p, DBG_RSP, "Command %d Response(Status=%d): '%s'", NULL, 0, p->command_count, *completion_status, *response);
else
_panel_debug (p, DBG_RSP, "Command %d Response - Match '%s': '%s'", NULL, 0, p->command_count, completion_string, *response);
} }
else { else {
free (tresponse); free (tresponse);
if (p->io_response_data) if (p->io_response_data) {
if (completion_status)
_panel_debug (p, DBG_RSP, "Discarded Unwanted Command %d Response Data(Status=%d):", p->io_response, p->io_response_data, p->command_count, *completion_status); _panel_debug (p, DBG_RSP, "Discarded Unwanted Command %d Response Data(Status=%d):", p->io_response, p->io_response_data, p->command_count, *completion_status);
else
_panel_debug (p, DBG_RSP, "Discarded Unwanted Command %d Response Data - Match '%s':", p->io_response, p->io_response_data, p->command_count, completion_string);
} }
} }
}
p->completion_string = NULL;
p->io_response_data = 0; p->io_response_data = 0;
p->io_response[0] = '\0'; p->io_response[0] = '\0';
pthread_mutex_unlock (&p->io_lock); pthread_mutex_unlock (&p->io_lock);
@ -2613,6 +2614,30 @@ if (buf != stackbuf)
return ret; return ret;
} }
static int
_panel_sendf (PANEL *p, int *completion_status, char **response, const char *fmt, ...)
{
va_list arglist;
int status;
va_start (arglist, fmt);
status = _panel_vsendf_completion (p, completion_status, response, NULL, fmt, arglist);
va_end (arglist);
return status;
}
static int
_panel_sendf_completion (PANEL *p, char **response, const char *completion, const char *fmt, ...)
{
va_list arglist;
int status;
va_start (arglist, fmt);
status = _panel_vsendf_completion (p, NULL, response, completion, fmt, arglist);
va_end (arglist);
return status;
}
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -56,7 +56,7 @@ extern "C" {
#if !defined(__VAX) /* Unsupported platform */ #if !defined(__VAX) /* Unsupported platform */
#define SIM_FRONTPANEL_VERSION 9 #define SIM_FRONTPANEL_VERSION 10
/** /**