diff --git a/scp.c b/scp.c index e548935c..a90e8fd8 100644 --- a/scp.c +++ b/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,}\"\" {actioncommand {; actioncommand}...}\n\n" + "++EXPECT {dev:line} {[count]} {HALTAFTER=n,}\"\" {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; isize; i++) +for (i=start_rule; isize; 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; isize; 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 */ diff --git a/sim_defs.h b/sim_defs.h index d25f95e3..60e04d85 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -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 */ };