SCP: Enhance EXPECT support to allow multiple rules with the same match string
Multiple rules with the same match string are processed in the order the EXPECT commands are entered. NOEXPECT will remove all pending EXPECT rules which have the match string provided on the NOEXPECT line.
This commit is contained in:
parent
d9f3743783
commit
c5ee1ad971
2 changed files with 44 additions and 17 deletions
60
scp.c
60
scp.c
|
@ -1477,10 +1477,14 @@ ASSERT failure have several different actions:
|
|||
"3Reacting To Console Output\n"
|
||||
" The EXPECT command provides a way to stop execution and take actions\n"
|
||||
" when specific output has been generated by the simulated system.\n"
|
||||
"++EXPECT {dev:line} {HALTAFTER=n,}\"<string>\" {actioncommand {; actioncommand}...}\n\n"
|
||||
"++EXPECT {dev:line} {[count]} {HALTAFTER=n,}\"<string>\" {actioncommand {; actioncommand}...}\n\n"
|
||||
" The string argument must be delimited by quote characters. Quotes may\n"
|
||||
" be either single or double but the opening and closing quote characters\n"
|
||||
" 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"
|
||||
" If a [count] is specified, the rule will match after the match string\n"
|
||||
" has matched count times.\n\n"
|
||||
" When multiple expect rules are defined with the same match string, they\n"
|
||||
" will match in the same order they were defined in.\n\n"
|
||||
" When expect rules are defined, they are evaluated agains recently\n"
|
||||
" produced output as each character is output to the device. Since this\n"
|
||||
" evaluation processing is done on each output character, rule matching\n"
|
||||
|
@ -9058,6 +9062,7 @@ uint32 sim_brk_test (t_addr loc, uint32 btyp)
|
|||
{
|
||||
BRKTAB *bp;
|
||||
uint32 spc = (btyp >> SIM_BKPT_V_SPC) & (SIM_BKPT_N_SPC - 1);
|
||||
uint32 res = 0;
|
||||
|
||||
if (sim_brk_summ & BRK_TYP_DYN_ALL)
|
||||
btyp |= BRK_TYP_DYN_ALL;
|
||||
|
@ -9067,13 +9072,18 @@ if ((bp = sim_brk_fnd (loc)) && (btyp & bp->typ)) { /* in table, and type ma
|
|||
(--bp->cnt > 0)) /* count > 0? */
|
||||
return 0;
|
||||
bp->cnt = 0; /* reset count */
|
||||
sim_brk_ploc[spc] = loc; /* save location */
|
||||
sim_brk_pend[spc] = TRUE; /* don't do twice */
|
||||
sim_brk_setact (bp->act); /* set up actions */
|
||||
return (btyp & bp->typ);
|
||||
res = btyp & bp->typ; /* set return value */
|
||||
if (bp->typ & BRK_TYP_TEMP)
|
||||
sim_brk_clr (loc, btyp); /* delete one-shot breakpoint */
|
||||
else {
|
||||
sim_brk_ploc[spc] = loc; /* save location */
|
||||
sim_brk_pend[spc] = TRUE; /* don't do twice */
|
||||
}
|
||||
return res;
|
||||
}
|
||||
sim_brk_pend[spc] = FALSE;
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Get next pending action, if any */
|
||||
|
@ -9246,13 +9256,13 @@ return sim_exp_clr (exp, gbuf); /* clear one rule */
|
|||
|
||||
/* Search for an expect rule in an expect context */
|
||||
|
||||
CONST EXPTAB *sim_exp_fnd (CONST EXPECT *exp, const char *match)
|
||||
CONST EXPTAB *sim_exp_fnd (CONST EXPECT *exp, const char *match, int32 start_rule)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
if (!exp->rules)
|
||||
return NULL;
|
||||
for (i=0; i<exp->size; i++)
|
||||
for (i=start_rule; i<exp->size; i++)
|
||||
if (!strcmp (exp->rules[i].match_pattern, match))
|
||||
return &exp->rules[i];
|
||||
return NULL;
|
||||
|
@ -9285,7 +9295,13 @@ return SCPE_OK;
|
|||
|
||||
t_stat sim_exp_clr (EXPECT *exp, const char *match)
|
||||
{
|
||||
return sim_exp_clr_tab (exp, (EXPTAB *)sim_exp_fnd (exp, match));
|
||||
EXPTAB *ep = (EXPTAB *)sim_exp_fnd (exp, match, 0);
|
||||
|
||||
while (ep) {
|
||||
sim_exp_clr_tab (exp, ep);
|
||||
ep = (EXPTAB *)sim_exp_fnd (exp, match, ep - exp->rules);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Clear all expect rules */
|
||||
|
@ -9361,9 +9377,11 @@ else {
|
|||
}
|
||||
}
|
||||
free (match_buf);
|
||||
ep = (EXPTAB *)sim_exp_fnd (exp, match); /* present? */
|
||||
if (ep) /* no, allocate */
|
||||
sim_exp_clr_tab (exp, ep); /* clear it */
|
||||
for (i=0; i<exp->size; i++) { /* Make sure this rule won't be occluded */
|
||||
if ((0 == strcmp (match, exp->rules[i].match_pattern)) &&
|
||||
(exp->rules[i].switches & EXP_TYP_PERSIST))
|
||||
return sim_messagef (SCPE_ARG, "Persistent Expect rule with identical match string already exists\n");
|
||||
}
|
||||
if (after && exp->size)
|
||||
return sim_messagef (SCPE_ARG, "Multiple concurrent EXPECT rules aren't valid when a HALTAFTER parameter is non-zero\n");
|
||||
exp->rules = (EXPTAB *) realloc (exp->rules, sizeof (*exp->rules)*(exp->size + 1));
|
||||
|
@ -9372,11 +9390,12 @@ exp->size += 1;
|
|||
exp->after = after; /* set halt after value */
|
||||
memset (ep, 0, sizeof(*ep));
|
||||
ep->match_pattern = (char *)malloc (strlen (match) + 1);
|
||||
strcpy (ep->match_pattern, match);
|
||||
if (ep->match_pattern)
|
||||
strcpy (ep->match_pattern, match);
|
||||
ep->cnt = cnt; /* set proceed count */
|
||||
ep->switches = switches; /* set switches */
|
||||
match_buf = (uint8 *)calloc (strlen (match) + 1, 1);
|
||||
if (!match_buf) {
|
||||
if ((match_buf == NULL) || (ep->match_pattern == NULL)) {
|
||||
sim_exp_clr_tab (exp, ep); /* clear it */
|
||||
return SCPE_MEM;
|
||||
}
|
||||
|
@ -9446,7 +9465,7 @@ return SCPE_OK;
|
|||
|
||||
t_stat sim_exp_show (FILE *st, CONST EXPECT *exp, const char *match)
|
||||
{
|
||||
CONST EXPTAB *ep = (CONST EXPTAB *)sim_exp_fnd (exp, match);
|
||||
CONST EXPTAB *ep = (CONST EXPTAB *)sim_exp_fnd (exp, match, 0);
|
||||
|
||||
if (exp->buf_size) {
|
||||
char *bstr = sim_encode_quoted_string (exp->buf, exp->buf_ins);
|
||||
|
@ -9460,11 +9479,18 @@ if (exp->after)
|
|||
fprintf (st, "Halt After: %d instructions\n", exp->after);
|
||||
if (exp->dptr && exp->dbit)
|
||||
fprintf (st, "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");
|
||||
if (!*match)
|
||||
return sim_exp_showall (st, exp);
|
||||
if (!ep)
|
||||
if (!ep) {
|
||||
fprintf (st, "No Rules match '%s'\n", match);
|
||||
return SCPE_ARG;
|
||||
return sim_exp_show_tab (st, exp, ep);
|
||||
}
|
||||
do {
|
||||
sim_exp_show_tab (st, exp, ep);
|
||||
ep = (CONST EXPTAB *)sim_exp_fnd (exp, match, 1 + (ep - exp->rules));
|
||||
} while (ep);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show all expect rules */
|
||||
|
|
|
@ -717,6 +717,7 @@ struct BRKTAB {
|
|||
#define BRK_TYP_DYN_STEPOVER (SWMASK ('Z'+1))
|
||||
#define BRK_TYP_DYN_USR (SWMASK ('Z'+2))
|
||||
#define BRK_TYP_DYN_ALL (BRK_TYP_DYN_USR|BRK_TYP_DYN_STEPOVER) /* Mask of All Dynamic types */
|
||||
#define BRK_TYP_TEMP (SWMASK ('Z'+3)) /* Temporary (one-shot) */
|
||||
int32 cnt; /* proceed count */
|
||||
char *act; /* action string */
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue