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:
parent
247bd8d534
commit
932d16da53
5 changed files with 177 additions and 65 deletions
168
scp.c
168
scp.c
|
@ -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,13 +3844,20 @@ 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 ((!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 != '\''))
|
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);
|
||||||
|
@ -3799,9 +3866,6 @@ if (*cptr) {
|
||||||
|
|
||||||
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;
|
||||||
if (after)
|
|
||||||
snd->after = (sim_switches & SWMASK ('T')) ? (uint32)((sim_timer_inst_per_sec()*after)/1000000.0) : 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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
38
sim_tmxr.c
38
sim_tmxr.c
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue