SCP: Rework SEND and EXPECT commands to provide default and temporary arguments

- EXPECT HALTAFTER=nnn
     --> sets "nnn" as the global/default value

 - EXPECT "some string"
     --> uses the "nnn" global/default value

 - EXPECT HALTAFTER=ttt "some string"
     --> uses the "ttt" temporary value for this EXPECT only

and:

 - SEND AFTER=nnn
     --> sets "nnn" as the global/default value

 - SEND "some string"
     --> uses the "nnn" global/default value

 - SEND AFTER=ttt "some string"
     --> uses the "ttt" temporary value for this SEND only

(and similarly for the SEND DELAY value).
This commit is contained in:
Mark Pizzolato 2017-10-16 13:10:10 -07:00
parent 247bd8d534
commit 932d16da53
5 changed files with 177 additions and 65 deletions

180
scp.c
View file

@ -1621,24 +1621,29 @@ ASSERT failure have several different actions:
" must match. Data in the string may contain escaped character strings.\n\n" " must match. Data in the string may contain escaped character strings.\n\n"
" The SEND command can also insert input into any serial device on a\n" " The SEND command can also insert input into any serial device on a\n"
" simulated system as if it was entered by a user.\n\n" " simulated system as if it was entered by a user.\n\n"
"++SEND {-t} <dev>:line {after=nn,}{delay=nn,}\"<string>\"\n\n" "++SEND {-t} {<dev>:line} {after=nn,}{delay=nn,}\"<string>\"\n"
"++NOSEND {<dev>:line}\n\n"
" The NOSEND command removes any undelivered input data which may be\n"
" pending on a line.\n"
"4Delay\n" "4Delay\n"
" Specifies a positive integer representing a minimal instruction delay\n" " Specifies an integer (>=0) representing a minimal instruction delay\n"
" between characters being sent. The value specified in a delay\n" " between characters being sent. The delay parameter can be set by\n"
" argument persists across SEND commands to the same device (console or\n" " itself with:\n\n"
" serial device). The delay parameter can be set by itself with:\n\n"
"++SEND DELAY=n\n\n" "++SEND DELAY=n\n\n"
" The default value of the delay parameter is 1000.\n" " which will set the default delay value for subsequent SEND commands\n"
" which don't specify an explicit DELAY parameter along with a string\n"
" If a SEND command is processed and no DELAY value has been specified,\n"
" the default value of the delay parameter is 1000.\n"
/***************** 80 character line width template *************************/ /***************** 80 character line width template *************************/
"4After\n" "4After\n"
" Specifies a positive integer representing a minimal number of instructions\n" " Specifies an integer (>=0) representing a minimal number of instructions\n"
" which must execute before the first character in the string is sent.\n" " which must execute before the first character in the string is sent.\n"
" The value specified as the after parameter persists across SEND commands\n" " The after parameter value can be set by itself with:\n\n"
" to the same device (console or serial device). The after parameter value\n"
" can be set by itself with:\n\n"
"++SEND AFTER=n\n\n" "++SEND AFTER=n\n\n"
" If the after parameter isn't explicitly set, it defaults to the value of\n" " which will set the default after value for subsequent SEND commands\n"
" the delay parameter.\n" " which don't specify an explicit AFTER parameter along with a string\n"
" If a SEND command is processed and no AFTER value has been specified,\n"
" the default value of the delay parameter is the DELAY parameter value.\n"
"4Escaping String Data\n" "4Escaping String Data\n"
" The following character escapes are explicitly supported:\n" " The following character escapes are explicitly supported:\n"
"++\\r Sends the ASCII Carriage Return character (Decimal value 13)\n" "++\\r Sends the ASCII Carriage Return character (Decimal value 13)\n"
@ -1757,10 +1762,12 @@ ASSERT failure have several different actions:
" Specifies the number of instructions which should be executed before\n" " Specifies the number of instructions which should be executed before\n"
" simulator instruction execution should stop. The default is to stop\n" " simulator instruction execution should stop. The default is to stop\n"
" executing instructions immediately (i.e. HALTAFTER=0).\n" " executing instructions immediately (i.e. HALTAFTER=0).\n"
" The HaltAfter delay, once set, persists for all expect behaviors for\n" " The default HaltAfter delay, once set, persists for all expect behaviors\n"
" that device.\n" " for that device.\n"
" The HaltAfter parameter value can be set by itself with:\n\n" " The default HaltAfter parameter value can be set by itself with:\n\n"
"++EXPECT HALTAFTER=n\n\n" "++EXPECT HALTAFTER=n\n\n"
" A unique HaltAfter value can be specified with each expect matching rule\n"
" which if it is not specified then the default value will be used.\n"
" To avoid potentially unpredictable system hehavior that will happen\n" " To avoid potentially unpredictable system hehavior that will happen\n"
" if multiple expect rules are in effect and a haltafter value is large\n" " if multiple expect rules are in effect and a haltafter value is large\n"
" enough for more than one expect rule to match before an earlier haltafter\n" " enough for more than one expect rule to match before an earlier haltafter\n"
@ -1955,7 +1962,8 @@ static CTAB cmd_table[] = {
{ "IGNORE", &noop_cmd, 0, HLP_IGNORE }, { "IGNORE", &noop_cmd, 0, HLP_IGNORE },
{ "ECHO", &echo_cmd, 0, HLP_ECHO }, { "ECHO", &echo_cmd, 0, HLP_ECHO },
{ "ASSERT", &assert_cmd, 1, HLP_ASSERT }, { "ASSERT", &assert_cmd, 1, HLP_ASSERT },
{ "SEND", &send_cmd, 0, HLP_SEND }, { "SEND", &send_cmd, 1, HLP_SEND },
{ "NOSEND", &send_cmd, 0, HLP_SEND },
{ "EXPECT", &expect_cmd, 1, HLP_EXPECT }, { "EXPECT", &expect_cmd, 1, HLP_EXPECT },
{ "NOEXPECT", &expect_cmd, 0, HLP_EXPECT }, { "NOEXPECT", &expect_cmd, 0, HLP_EXPECT },
{ "!", &spawn_cmd, 0, HLP_SPAWN }, { "!", &spawn_cmd, 0, HLP_SPAWN },
@ -3717,14 +3725,20 @@ return SCPE_OK;
Syntax: SEND {After=m},{Delay=n},"string-to-send" Syntax: SEND {After=m},{Delay=n},"string-to-send"
After - is a positive integer representing a number of instruction delay After - is an integer (>= 0) representing a number of instruction
before the initial characters is sent. The value specified delay before the initial characters is sent. The after
in a after argument persists across SEND commands. The after parameter can is set by itself (with SEND AFTER=n).
parameter can be set by itself with SEND AFTER=n The value specified then persists across SEND commands,
Delay - is a positive integer representing a minimal instruction delay and is the default value used in subsequent SEND commands
before and between characters being sent. The value specified which don't specify an explicit AFTER parameter. This default
in a delay argument persists across SEND commands. The delay value is visible externally via an environment variable.
parameter can be set by itself with SEND DELAY=n Delay - is an integer (>= 0) representing a number of instruction
delay before and between characters being sent. The
delay parameter can is set by itself (with SEND DELAY=n)
The value specified persists across SEND commands, and is
the default value used in subsequent SEND commands which
don't specify an explicit DELAY parameter. This default
value is visible externally via an environment variable.
String - must be quoted. Quotes may be either single or double but the String - must be quoted. Quotes may be either single or double but the
opening anc closing quote characters must match. Within quotes opening anc closing quote characters must match. Within quotes
C style character escapes are allowed. C style character escapes are allowed.
@ -3746,14 +3760,53 @@ return SCPE_OK;
\xh{h} where each h is a hex digit (0-9A-Fa-f) \xh{h} where each h is a hex digit (0-9A-Fa-f)
*/ */
static uint32 get_default_env_parameter (const char *dev_name, const char *param_name, uint32 default_value)
{
char varname[CBUFSIZE];
uint32 val;
char *endptr;
const char *colon = strchr (dev_name, ':');
if (colon)
snprintf (varname, sizeof(varname), "%s_%*.*s_%s", param_name, (int)(colon-dev_name), (int)(colon-dev_name), dev_name, colon + 1);
else
snprintf (varname, sizeof(varname), "%s_%s", param_name, dev_name);
if (!getenv (varname))
val = default_value;
else {
val = strtoul (getenv (varname), &endptr, 0);
if (*endptr)
val = default_value;
}
return val;
}
static void set_default_env_parameter (const char *dev_name, const char *param_name, uint32 value)
{
char varname[CBUFSIZE];
char valbuf[CBUFSIZE];
const char *colon = strchr (dev_name, ':');
if (colon)
snprintf (varname, sizeof(varname), "%s_%*.*s_%s", param_name, (int)(colon-dev_name), (int)(colon-dev_name), dev_name, colon + 1);
else
snprintf (varname, sizeof(varname), "%s_%s", param_name, dev_name);
snprintf (valbuf, sizeof(valbuf), "%u", value);
setenv(varname, valbuf, 1);
}
t_stat send_cmd (int32 flag, CONST char *cptr) t_stat send_cmd (int32 flag, CONST char *cptr)
{ {
char gbuf[CBUFSIZE]; char gbuf[CBUFSIZE];
CONST char *tptr; CONST char *tptr;
uint8 dbuf[CBUFSIZE]; uint8 dbuf[CBUFSIZE];
uint32 dsize = 0; uint32 dsize = 0;
uint32 delay = 0; const char *dev_name;
uint32 after = 0; uint32 delay;
t_bool delay_set = FALSE;
uint32 after;
t_bool after_set = FALSE;
t_stat r; t_stat r;
SEND *snd; SEND *snd;
@ -3768,7 +3821,11 @@ if (sim_isalpha(gbuf[0]) && (strchr (gbuf, ':'))) {
} }
else else
snd = sim_cons_get_send (); snd = sim_cons_get_send ();
dev_name = tmxr_send_line_name (snd);
if (!flag)
return sim_send_clear (snd);
delay = get_default_env_parameter (dev_name, "SIM_SEND_DELAY", SEND_DEFAULT_DELAY);
after = get_default_env_parameter (dev_name, "SIM_SEND_AFTER", delay);
while (*cptr) { while (*cptr) {
if ((!strncmp(gbuf, "DELAY=", 6)) && (gbuf[6])) { if ((!strncmp(gbuf, "DELAY=", 6)) && (gbuf[6])) {
delay = (uint32)get_uint (&gbuf[6], 10, 10000000, &r); delay = (uint32)get_uint (&gbuf[6], 10, 10000000, &r);
@ -3776,6 +3833,9 @@ while (*cptr) {
return sim_messagef (SCPE_ARG, "Invalid Delay Value\n"); return sim_messagef (SCPE_ARG, "Invalid Delay Value\n");
cptr = tptr; cptr = tptr;
tptr = get_glyph (cptr, gbuf, ','); tptr = get_glyph (cptr, gbuf, ',');
delay_set = TRUE;
if (!after_set)
after = delay;
continue; continue;
} }
if ((!strncmp(gbuf, "AFTER=", 6)) && (gbuf[6])) { if ((!strncmp(gbuf, "AFTER=", 6)) && (gbuf[6])) {
@ -3784,24 +3844,28 @@ while (*cptr) {
return sim_messagef (SCPE_ARG, "Invalid After Value\n"); return sim_messagef (SCPE_ARG, "Invalid After Value\n");
cptr = tptr; cptr = tptr;
tptr = get_glyph (cptr, gbuf, ','); tptr = get_glyph (cptr, gbuf, ',');
after_set = TRUE;
continue; continue;
} }
if ((*cptr == '"') || (*cptr == '\'')) if ((*cptr == '"') || (*cptr == '\''))
break; break;
return SCPE_ARG; return SCPE_ARG;
} }
if (*cptr) { if (!*cptr) {
if ((*cptr != '"') && (*cptr != '\'')) if ((!delay_set) && (!after_set))
return SCPE_2FARG;
set_default_env_parameter (dev_name, "SIM_SEND_DELAY", delay);
set_default_env_parameter (dev_name, "SIM_SEND_AFTER", after);
return SCPE_OK;
}
if ((*cptr != '"') && (*cptr != '\''))
return sim_messagef (SCPE_ARG, "String must be quote delimited\n"); return sim_messagef (SCPE_ARG, "String must be quote delimited\n");
cptr = get_glyph_quoted (cptr, gbuf, 0); cptr = get_glyph_quoted (cptr, gbuf, 0);
if (*cptr != '\0') if (*cptr != '\0')
return SCPE_2MARG; /* No more arguments */ return SCPE_2MARG; /* No more arguments */
if (SCPE_OK != sim_decode_quoted_string (gbuf, dbuf, &dsize)) if (SCPE_OK != sim_decode_quoted_string (gbuf, dbuf, &dsize))
return sim_messagef (SCPE_ARG, "Invalid String\n"); return sim_messagef (SCPE_ARG, "Invalid String\n");
}
if ((dsize == 0) && (delay == 0) && (after == 0))
return SCPE_2FARG;
return sim_send_input (snd, dbuf, dsize, after, delay); return sim_send_input (snd, dbuf, dsize, after, delay);
} }
@ -10414,13 +10478,16 @@ t_stat sim_set_expect (EXPECT *exp, CONST char *cptr)
char gbuf[CBUFSIZE]; char gbuf[CBUFSIZE];
CONST char *tptr; CONST char *tptr;
CONST char *c1ptr; CONST char *c1ptr;
const char *dev_name;
uint32 after;
t_bool after_set = FALSE; t_bool after_set = FALSE;
uint32 after = exp->after;
int32 cnt = 0; int32 cnt = 0;
t_stat r; t_stat r;
if ((cptr == NULL) || (*cptr == 0)) if ((cptr == NULL) || (*cptr == 0))
return SCPE_2FARG; return SCPE_2FARG;
dev_name = tmxr_expect_line_name (exp);
after = get_default_env_parameter (dev_name, "SIM_EXPECT_HALTAFTER", 0);
if (*cptr == '[') { if (*cptr == '[') {
cnt = (int32) strtotv (cptr + 1, &c1ptr, 10); cnt = (int32) strtotv (cptr + 1, &c1ptr, 10);
if ((cptr == c1ptr) || (*c1ptr != ']')) if ((cptr == c1ptr) || (*c1ptr != ']'))
@ -10434,14 +10501,20 @@ if ((!strncmp(gbuf, "HALTAFTER=", 10)) && (gbuf[10])) {
after = (uint32)get_uint (&gbuf[10], 10, 100000000, &r); after = (uint32)get_uint (&gbuf[10], 10, 100000000, &r);
if (r != SCPE_OK) if (r != SCPE_OK)
return sim_messagef (SCPE_ARG, "Invalid Halt After Value\n"); return sim_messagef (SCPE_ARG, "Invalid Halt After Value\n");
after_set = TRUE;
cptr = tptr; cptr = tptr;
after_set = TRUE;
} }
if ((*cptr != '\0') && (*cptr != '"') && (*cptr != '\'')) if ((*cptr != '\0') && (*cptr != '"') && (*cptr != '\''))
return sim_messagef (SCPE_ARG, "String must be quote delimited\n"); return sim_messagef (SCPE_ARG, "String must be quote delimited\n");
cptr = get_glyph_quoted (cptr, gbuf, 0); cptr = get_glyph_quoted (cptr, gbuf, 0);
return sim_exp_set (exp, gbuf, cnt, (after_set ? after : exp->after), sim_switches, cptr); /* Hsndle a bare HALTAFTER=nnn command */
if ((gbuf[0] == '\0') && (*cptr == '\0') && after_set) {
set_default_env_parameter (dev_name, "SIM_EXPECT_HALTAFTER", after);
return SCPE_OK;
}
return sim_exp_set (exp, gbuf, cnt, after, sim_switches, cptr);
} }
/* Clear expect */ /* Clear expect */
@ -10540,11 +10613,6 @@ uint8 *match_buf;
uint32 match_size; uint32 match_size;
int i; int i;
/* Hsndle a bare HALTAFTER=nnn command */
if ((*match == '\0') && (*act == '\0') && after) {
exp->after = after;
return SCPE_OK;
}
/* Validate the match string */ /* Validate the match string */
match_buf = (uint8 *)calloc (strlen (match) + 1, 1); match_buf = (uint8 *)calloc (strlen (match) + 1, 1);
if (!match_buf) if (!match_buf)
@ -10598,8 +10666,8 @@ if (after && exp->size)
exp->rules = (EXPTAB *) realloc (exp->rules, sizeof (*exp->rules)*(exp->size + 1)); exp->rules = (EXPTAB *) realloc (exp->rules, sizeof (*exp->rules)*(exp->size + 1));
ep = &exp->rules[exp->size]; ep = &exp->rules[exp->size];
exp->size += 1; exp->size += 1;
exp->after = after; /* set halt after value */
memset (ep, 0, sizeof(*ep)); memset (ep, 0, sizeof(*ep));
ep->after = after; /* set halt after value */
ep->match_pattern = (char *)malloc (strlen (match) + 1); ep->match_pattern = (char *)malloc (strlen (match) + 1);
if (ep->match_pattern) if (ep->match_pattern)
strcpy (ep->match_pattern, match); strcpy (ep->match_pattern, match);
@ -10660,6 +10728,9 @@ return SCPE_OK;
t_stat sim_exp_show_tab (FILE *st, const EXPECT *exp, const EXPTAB *ep) t_stat sim_exp_show_tab (FILE *st, const EXPECT *exp, const EXPTAB *ep)
{ {
const char *dev_name = dev_name = tmxr_expect_line_name (exp);
uint32 default_haltafter = get_default_env_parameter (dev_name, "SIM_EXPECT_HALTAFTER", 0);
if (!ep) if (!ep)
return SCPE_OK; return SCPE_OK;
fprintf (st, " EXPECT"); fprintf (st, " EXPECT");
@ -10671,6 +10742,8 @@ if (ep->switches & EXP_TYP_REGEX)
fprintf (st, " -r"); fprintf (st, " -r");
if (ep->switches & EXP_TYP_REGEX_I) if (ep->switches & EXP_TYP_REGEX_I)
fprintf (st, " -i"); fprintf (st, " -i");
if (ep->after != default_haltafter)
fprintf (st, " HALTAFTER=%d", (int)ep->after);
fprintf (st, " %s", ep->match_pattern); fprintf (st, " %s", ep->match_pattern);
if (ep->cnt > 0) if (ep->cnt > 0)
fprintf (st, " [%d]", ep->cnt); fprintf (st, " [%d]", ep->cnt);
@ -10683,6 +10756,8 @@ return SCPE_OK;
t_stat sim_exp_show (FILE *st, CONST EXPECT *exp, const char *match) t_stat sim_exp_show (FILE *st, CONST EXPECT *exp, const char *match)
{ {
CONST EXPTAB *ep = (CONST EXPTAB *)sim_exp_fnd (exp, match, 0); CONST EXPTAB *ep = (CONST EXPTAB *)sim_exp_fnd (exp, match, 0);
const char *dev_name = dev_name = tmxr_expect_line_name (exp);
uint32 default_haltafter = get_default_env_parameter (dev_name, "SIM_EXPECT_HALTAFTER", 0);
if (exp->buf_size) { if (exp->buf_size) {
char *bstr = sim_encode_quoted_string (exp->buf, exp->buf_ins); char *bstr = sim_encode_quoted_string (exp->buf, exp->buf_ins);
@ -10690,10 +10765,10 @@ if (exp->buf_size) {
fprintf (st, " Match Buffer Size: %d\n", exp->buf_size); fprintf (st, " Match Buffer Size: %d\n", exp->buf_size);
fprintf (st, " Buffer Insert Offset: %d\n", exp->buf_ins); fprintf (st, " Buffer Insert Offset: %d\n", exp->buf_ins);
fprintf (st, " Buffer Contents: %s\n", bstr); fprintf (st, " Buffer Contents: %s\n", bstr);
if (default_haltafter)
fprintf (st, " Default HaltAfter: %u instructions\n", (unsigned)default_haltafter);
free (bstr); free (bstr);
} }
if (exp->after)
fprintf (st, " Halt After: %d instructions\n", exp->after);
if (exp->dptr && (exp->dbit & exp->dptr->dctrl)) if (exp->dptr && (exp->dbit & exp->dptr->dctrl))
fprintf (st, " Expect Debugging via: SET %s DEBUG%s%s\n", sim_dname(exp->dptr), exp->dptr->debflags ? "=" : "", exp->dptr->debflags ? get_dbg_verb (exp->dbit, exp->dptr) : ""); fprintf (st, " Expect Debugging via: SET %s DEBUG%s%s\n", sim_dname(exp->dptr), exp->dptr->debflags ? "=" : "", exp->dptr->debflags ? get_dbg_verb (exp->dbit, exp->dptr) : "");
fprintf (st, " Match Rules:\n"); fprintf (st, " Match Rules:\n");
@ -10885,8 +10960,8 @@ if (i != exp->size) { /* Found? */
} }
sim_activate (&sim_expect_unit, /* schedule simulation stop when indicated */ sim_activate (&sim_expect_unit, /* schedule simulation stop when indicated */
(ep->switches & EXP_TYP_TIME) ? (ep->switches & EXP_TYP_TIME) ?
(int32)((sim_timer_inst_per_sec ()*exp->after)/1000000.0) : (int32)((sim_timer_inst_per_sec ()*ep->after)/1000000.0) :
exp->after); ep->after);
} }
/* Matched data is no longer available for future matching */ /* Matched data is no longer available for future matching */
exp->buf_data = exp->buf_ins = 0; exp->buf_data = exp->buf_ins = 0;
@ -10911,12 +10986,8 @@ if (snd->insoff+size > snd->bufsize) {
} }
memcpy(snd->buffer+snd->insoff, data, size); memcpy(snd->buffer+snd->insoff, data, size);
snd->insoff += size; snd->insoff += size;
if (delay) snd->delay = (sim_switches & SWMASK ('T')) ? (uint32)((sim_timer_inst_per_sec()*delay)/1000000.0) : delay;
snd->delay = (sim_switches & SWMASK ('T')) ? (uint32)((sim_timer_inst_per_sec()*delay)/1000000.0) : delay; snd->after = (sim_switches & SWMASK ('T')) ? (uint32)((sim_timer_inst_per_sec()*after)/1000000.0) : after;
if (after)
snd->after = (sim_switches & SWMASK ('T')) ? (uint32)((sim_timer_inst_per_sec()*after)/1000000.0) : after;
if (snd->after == 0)
snd->after = snd->delay;
snd->next_time = sim_gtime() + snd->after; snd->next_time = sim_gtime() + snd->after;
return SCPE_OK; return SCPE_OK;
} }
@ -10933,6 +11004,7 @@ return SCPE_OK;
t_stat sim_show_send_input (FILE *st, const SEND *snd) t_stat sim_show_send_input (FILE *st, const SEND *snd)
{ {
fprintf (st, "%s\n", tmxr_send_line_name (snd));
if (snd->extoff < snd->insoff) { if (snd->extoff < snd->insoff) {
fprintf (st, " %d bytes of pending input Data:\n ", snd->insoff-snd->extoff); fprintf (st, " %d bytes of pending input Data:\n ", snd->insoff-snd->extoff);
fprint_buffer_string (st, snd->buffer+snd->extoff, snd->insoff-snd->extoff); fprint_buffer_string (st, snd->buffer+snd->extoff, snd->insoff-snd->extoff);

View file

@ -234,7 +234,7 @@ TMLN sim_con_ldsc = { 0 }; /* console l
TMXR sim_con_tmxr = { 1, 0, 0, &sim_con_ldsc, NULL, &sim_con_telnet };/* console line mux */ TMXR sim_con_tmxr = { 1, 0, 0, &sim_con_ldsc, NULL, &sim_con_telnet };/* console line mux */
SEND sim_con_send = {SEND_DEFAULT_DELAY, &sim_con_telnet, DBG_SND}; SEND sim_con_send = {0, &sim_con_telnet, DBG_SND};
EXPECT sim_con_expect = {&sim_con_telnet, DBG_EXP}; EXPECT sim_con_expect = {&sim_con_telnet, DBG_EXP};
static t_bool sim_con_console_port = TRUE; static t_bool sim_con_console_port = TRUE;
@ -3969,7 +3969,8 @@ else {
(sim_switches & SWMASK ('I')) ? "" : "\n"); (sim_switches & SWMASK ('I')) ? "" : "\n");
free (mbuf); free (mbuf);
mbuf = sim_encode_quoted_string ((uint8 *)mbuf2, strlen (mbuf2)); mbuf = sim_encode_quoted_string ((uint8 *)mbuf2, strlen (mbuf2));
sim_exp_set (&sim_con_expect, mbuf, 0, sim_con_expect.after, EXP_TYP_PERSIST, NULL); sim_switches = EXP_TYP_PERSIST;
sim_set_expect (&sim_con_expect, mbuf);
free (mbuf); free (mbuf);
free (mbuf2); free (mbuf2);
} }
@ -3992,7 +3993,7 @@ else {
rbuf = (uint8 *)malloc (1 + strlen(cptr)); rbuf = (uint8 *)malloc (1 + strlen(cptr));
decode ((char *)rbuf, cptr); /* decod string */ decode ((char *)rbuf, cptr); /* decode string */
sim_send_input (&sim_con_send, rbuf, strlen((char *)rbuf), 0, 0); /* queue it for output */ sim_send_input (&sim_con_send, rbuf, strlen((char *)rbuf), 0, 0); /* queue it for output */
free (rbuf); free (rbuf);
} }
@ -4011,9 +4012,12 @@ if (cptr == NULL || *cptr == 0) /* no argument string? *
return SCPE_2FARG; /* need an argument */ return SCPE_2FARG; /* need an argument */
val = (int32) get_uint (cptr, 10, INT_MAX, &r); /* parse the argument */ val = (int32) get_uint (cptr, 10, INT_MAX, &r); /* parse the argument */
if (r == SCPE_OK) { /* parse OK? */
char gbuf[CBUFSIZE];
if (r == SCPE_OK) /* parse OK? */ snprintf (gbuf, sizeof (gbuf), "HALTAFTER=%d", val);
sim_con_expect.after = val; /* save the delay value */ expect_cmd (1, gbuf);
}
return r; return r;
} }

View file

@ -773,6 +773,7 @@ struct EXPTAB {
uint32 size; /* match string size */ uint32 size; /* match string size */
char *match_pattern; /* match pattern for format */ char *match_pattern; /* match pattern for format */
int32 cnt; /* proceed count */ int32 cnt; /* proceed count */
uint32 after; /* delay before halting */
int32 switches; /* flags */ int32 switches; /* flags */
#define EXP_TYP_PERSIST (SWMASK ('P')) /* rule persists after match, default is once a rule matches, it is removed */ #define EXP_TYP_PERSIST (SWMASK ('P')) /* rule persists after match, default is once a rule matches, it is removed */
#define EXP_TYP_CLEARALL (SWMASK ('C')) /* clear all rules after matching this rule, default is to once a rule matches, it is removed */ #define EXP_TYP_CLEARALL (SWMASK ('C')) /* clear all rules after matching this rule, default is to once a rule matches, it is removed */
@ -792,7 +793,6 @@ struct EXPECT {
uint32 dbit; /* Debugging Bit */ uint32 dbit; /* Debugging Bit */
EXPTAB *rules; /* match rules */ EXPTAB *rules; /* match rules */
int32 size; /* count of match rules */ int32 size; /* count of match rules */
uint32 after; /* delay before halting */
uint8 *buf; /* buffer of output data which has produced */ uint8 *buf; /* buffer of output data which has produced */
uint32 buf_ins; /* buffer insertion point for the next output data */ uint32 buf_ins; /* buffer insertion point for the next output data */
uint32 buf_size; /* buffer size */ uint32 buf_size; /* buffer size */

View file

@ -3542,8 +3542,7 @@ if (!found) {
tmxr_open_devices = (TMXR **)realloc(tmxr_open_devices, (tmxr_open_device_count+1)*sizeof(*tmxr_open_devices)); tmxr_open_devices = (TMXR **)realloc(tmxr_open_devices, (tmxr_open_device_count+1)*sizeof(*tmxr_open_devices));
tmxr_open_devices[tmxr_open_device_count++] = mux; tmxr_open_devices[tmxr_open_device_count++] = mux;
for (i=0; i<mux->lines; i++) for (i=0; i<mux->lines; i++)
if (0 == mux->ldsc[i].send.delay) mux->ldsc[i].send.after = mux->ldsc[i].send.delay = 0;
mux->ldsc[i].send.delay = SEND_DEFAULT_DELAY;
} }
#if defined(SIM_ASYNCH_MUX) #if defined(SIM_ASYNCH_MUX)
pthread_mutex_unlock (&sim_tmxr_poll_lock); pthread_mutex_unlock (&sim_tmxr_poll_lock);
@ -3612,6 +3611,41 @@ t_stat tmxr_locate_line_expect (const char *cptr, EXPECT **exp)
return _tmxr_locate_line_send_expect (cptr, NULL, exp); return _tmxr_locate_line_send_expect (cptr, NULL, exp);
} }
static const char *_tmxr_send_expect_line_name (const SEND *snd, const EXPECT *exp)
{
static char line_name[CBUFSIZE];
int i, j;
strcpy (line_name, "");
for (i=0; i<tmxr_open_device_count; ++i)
for (j=0; j<tmxr_open_devices[i]->lines; ++j)
if ((snd == &tmxr_open_devices[i]->ldsc[j].send) ||
(exp == &tmxr_open_devices[i]->ldsc[j].expect)) {
if (tmxr_open_devices[i]->lines > 1)
snprintf (line_name, sizeof (line_name), "%s:%d", tmxr_open_devices[i]->ldsc[j].send.dptr->name, j);
else
strncpy (line_name, tmxr_open_devices[i]->ldsc[j].send.dptr->name, sizeof (line_name));
break;
}
return line_name;
}
const char *tmxr_send_line_name (const SEND *snd)
{
if (snd == sim_cons_get_send ())
return "CONSOLE";
else
return _tmxr_send_expect_line_name (snd, NULL);
}
const char *tmxr_expect_line_name (const EXPECT *exp)
{
if (exp == sim_cons_get_expect ())
return "CONSOLE";
else
return _tmxr_send_expect_line_name (NULL, exp);
}
t_stat tmxr_change_async (void) t_stat tmxr_change_async (void)
{ {
#if defined(SIM_ASYNCH_IO) #if defined(SIM_ASYNCH_IO)

View file

@ -287,6 +287,8 @@ t_stat tmxr_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 ticks);
t_stat tmxr_change_async (void); t_stat tmxr_change_async (void);
t_stat tmxr_locate_line_send (const char *dev_line, SEND **snd); t_stat tmxr_locate_line_send (const char *dev_line, SEND **snd);
t_stat tmxr_locate_line_expect (const char *dev_line, EXPECT **exp); t_stat tmxr_locate_line_expect (const char *dev_line, EXPECT **exp);
const char *tmxr_send_line_name (const SEND *snd);
const char *tmxr_expect_line_name (const EXPECT *exp);
t_stat tmxr_startup (void); t_stat tmxr_startup (void);
t_stat tmxr_shutdown (void); t_stat tmxr_shutdown (void);
t_stat tmxr_start_poll (void); t_stat tmxr_start_poll (void);