mirror of
https://github.com/open-simh/simh.git
synced 2026-01-11 23:53:30 +00:00
SCP: Cleaned up help for EXPECT and SEND commands. Added optional case insensitive match option to regular expression EXPECT rules.
This commit is contained in:
parent
1413e762a4
commit
916bab3c2a
13
README.md
13
README.md
@ -169,6 +169,17 @@ ASSERT failure have several different actions:
|
||||
Other related changes/extensions:
|
||||
The "!" command (execute a command on the local OS), now returns the command's exit status as the status from the "!" command. This allows ON conditions to handle error status responses from OS commands and act as desired.
|
||||
|
||||
#### Scriptable interactions with running simulators.
|
||||
|
||||
The EXPECT command now exists to provide a means of reacting to simulator output and the SEND command exists to inject data into programs running within a simulator.
|
||||
|
||||
EXPECT {HALTAFTER=n,}"\r\nPassword: "
|
||||
SEND {AFTER=n,}{DELAY=m,}"mypassword\r"
|
||||
|
||||
or
|
||||
|
||||
EXPECT {HALTAFTER=n,}"\r\nPassword: " SEND {AFTER=n,}{DELAY=m,}"mypassword\r"; GO
|
||||
|
||||
|
||||
#### Help
|
||||
|
||||
@ -219,6 +230,8 @@ The "!" command (execute a command on the local OS), now returns the command's e
|
||||
DIR {path|file} Display file listing
|
||||
LS {path|file} Display file listing
|
||||
NEXT Step across a subroutine call or step a single instruction.
|
||||
EXPECT React to output produced by a simulated system
|
||||
SEND Inject input to a simulated system's console
|
||||
|
||||
#### Command Processing Enhancements
|
||||
|
||||
|
||||
110
scp.c
110
scp.c
@ -1378,18 +1378,30 @@ ASSERT failure have several different actions:
|
||||
"3Injecting Console Input\n"
|
||||
" The SEND command provides a way to insert input into the console device of\n"
|
||||
" a simulated system as if it was entered by a user.\n\n"
|
||||
"++SEND {delay=nn,}\"<string>\" send input string into console\n\n"
|
||||
"++SEND {after=nn,}{delay=nn,}\"<string>\"\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"
|
||||
" 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"
|
||||
"++SEND <dev>:line {delay=nn,}\"<string>\"\n\n"
|
||||
"++SEND <dev>:line {after=nn,}{delay=nn,}\"<string>\"\n\n"
|
||||
"4Delay\n"
|
||||
" Specifies a positive integer representing a minimal instruction delay\n"
|
||||
" before and between characdters being sent. The value specified in a delay\n"
|
||||
" argument persists across SEND commands. The delay parameter can be set by\n"
|
||||
" itself with SEND DELAY=n\n"
|
||||
" between characters being sent. The value specified in a delay\n"
|
||||
" argument persists across SEND commands to the same device (console or\n"
|
||||
" serial device). The delay parameter can be set by itself with\n\n"
|
||||
"++SEND DELAY=n\n\n"
|
||||
" The default value of the delay parameter is 1000.\n"
|
||||
/***************** 80 character line width template *************************/
|
||||
"4After\n"
|
||||
" Specifies a positive integer representing a minimal number of instructions\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"
|
||||
" 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"
|
||||
" If the after parameter isn't explicitly set, it defaults to the value of\n"
|
||||
" the delay parameter.\n"
|
||||
"4Escaping String Data\n"
|
||||
" The following character escapes are explicitly supported:\n"
|
||||
" ++\\r Sends the ASCII Carriage Return character (Decimal value 13)\n"
|
||||
@ -1413,11 +1425,20 @@ 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"
|
||||
" a simulated system as if it was entered by a user.\n\n"
|
||||
"++EXPECT {dev:line} \"<string>\" {actioncommand {; actioncommand}...}\n\n"
|
||||
"++EXPECT {dev:line} {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"
|
||||
" must match. Data in the string may contain escaped character strings.\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, rules matching\n"
|
||||
" is not specifically line oriented. If line oriented matching is desired\n"
|
||||
" then rules should be defined which contain the simulated system's line\n"
|
||||
" ending character sequence (i.e. \"\r\n\").\n"
|
||||
" Once data has matched any expect rule, that data is no longer eligible\n"
|
||||
" to match other expect rules which may already be defined.\n"
|
||||
" Data which is output prior to the definition of an expect rule is not\n"
|
||||
" eligible to be matched against.\n"
|
||||
/***************** 80 character line width template *************************/
|
||||
"4Switches\n"
|
||||
" Switches can be used to influence the behavior of EXPECT rules\n\n"
|
||||
@ -1429,8 +1450,43 @@ ASSERT failure have several different actions:
|
||||
" If an expect rule is defined with the -c switch, it will cause all\n"
|
||||
" pending expect rules on the current device to be cleared when the rule\n"
|
||||
" matches data in the device output stream.\n"
|
||||
"5-r\n"
|
||||
" If an expect rule is defined with the -r switch, the string is interpreted\n"
|
||||
" as a regular expression applied to the output data stream. This regular\n"
|
||||
" expression may contain parentheses delimited sub-groups.\n\n"
|
||||
/***************** 80 character line width template *************************/
|
||||
#if defined (HAVE_PCREPOSIX_H)
|
||||
" The syntax of the regular expressions available are those supported by\n"
|
||||
" the Perl Compatible Regular Expression package (aka PCRE). As the name\n"
|
||||
" implies, the syntax is generally the same as Perl regular expressions.\n"
|
||||
" See http://perldoc.perl.org/perlre.html for more details\n"
|
||||
#elif defined (HAVE_REGEX_H)
|
||||
" The syntax of the regular expressions available are those supported by\n"
|
||||
" your local system's Regular Expression library using the Extended POSIX\n"
|
||||
" Regular Expressiona\n"
|
||||
#else
|
||||
" Regular expression support is not currently available on your environment.\n"
|
||||
" This simulator could use regular expression support provided by the\n"
|
||||
" Perl Compatible Regular Expression (PCRE) package if it was available\n"
|
||||
" when you simulator was compiled.\n"
|
||||
#endif
|
||||
"5-i\n"
|
||||
" If a regular expression expect rule is defined with the -i switch,\n"
|
||||
" character matching for that expression will be case independent.\n"
|
||||
" The -i switch is only valid for regular expression expect rules.\n"
|
||||
"4Determining Which Output Matched\n"
|
||||
" When an expect rule matches data in the output stream, the rule which\n"
|
||||
" matched is recorded in the environment variable _EXPECT_MATCH_PATTERN.\n"
|
||||
" If the expect rule was a regular expression rule, then the environment\n"
|
||||
" variable _EXPECT_MATCH_GROUP_0 is set to the whole string which matched\n"
|
||||
" and if the match pattern had any parentheses delimited sub-groups, the\n"
|
||||
" environment variables _EXPECT_MATCH_PATTERN_1 thru _EXPECT_MATCH_PATTERN_n\n"
|
||||
" are set to the values within the string which matched the respective\n"
|
||||
" sub-groups.\n"
|
||||
/***************** 80 character line width template *************************/
|
||||
"4Escaping String Data\n"
|
||||
" The following character escapes are explicitly supported:\n"
|
||||
" The following character escapes are explicitly supported when NOT using\n"
|
||||
" regular expression match patterns:\n"
|
||||
" ++\\r Sends the ASCII Carriage Return character (Decimal value 13)\n"
|
||||
" ++\\n Sends the ASCII Linefeed character (Decimal value 10)\n"
|
||||
" ++\\f Sends the ASCII Formfeed character (Decimal value 12)\n"
|
||||
@ -1446,7 +1502,20 @@ ASSERT failure have several different actions:
|
||||
" ++\\n{n{n}} where each n is an octal digit (0-7)\n"
|
||||
" and hext character values of the form:\n"
|
||||
" ++\\xh{h} where each h is a hex digit (0-9A-Fa-f)\n"
|
||||
/***************** 80 character line width template *************************/
|
||||
"4HaltAfter\n"
|
||||
" Specifies the number of instructions which should be executed before\n"
|
||||
" simulator instruction execution should stop. The default is to stop\n"
|
||||
" executing instructions immediately (i.e. HALTAFTER=0).\n"
|
||||
" The HaltAfter delay, once set, persists for all expect behaviors for\n"
|
||||
" that device.\n"
|
||||
" The HaltAfter parameter value can be set by itself with:\n\n"
|
||||
"++EXPECT HALTAFTER=n\n\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"
|
||||
" enough for more than one expect rule to match before an earlier haltafter\n"
|
||||
" delay has expired, only a single EXPECT rule can be defined if a non-zero\n"
|
||||
" HaltAfter parameter has been set.\n"
|
||||
/***************** 80 character line width template *************************/
|
||||
#define HLP_ASSERT "*Commands Executing_Command_Files Testing_Simulator_State"
|
||||
"3Testing Simulator State\n"
|
||||
" The ASSERT command tests a simulator state condition and halts command\n"
|
||||
@ -8340,7 +8409,7 @@ if ((*cptr != '"') && (*cptr != '\'')) {
|
||||
cptr = get_glyph_quoted (cptr, gbuf, 0);
|
||||
if (*cptr != '\0')
|
||||
return SCPE_2MARG; /* No more arguments */
|
||||
return sim_exp_set (exp, gbuf, cnt, after, sim_switches, cptr);
|
||||
return sim_exp_set (exp, gbuf, cnt, (after ? after : exp->after), sim_switches, cptr);
|
||||
}
|
||||
|
||||
/* Clear expect */
|
||||
@ -8452,7 +8521,7 @@ if (switches & EXP_TYP_REGEX) {
|
||||
memset (&re, 0, sizeof(re));
|
||||
memcpy (match_buf, match+1, strlen(match)-2); /* extract string without surrounding quotes */
|
||||
match_buf[strlen(match)-2] = '\0';
|
||||
res = regcomp (&re, (char *)match_buf, REG_EXTENDED);
|
||||
res = regcomp (&re, (char *)match_buf, REG_EXTENDED | ((switches & EXP_TYP_REGEX_I) ? REG_ICASE : 0));
|
||||
if (res) {
|
||||
size_t err_size = regerror (res, &re, NULL, 0);
|
||||
char *err_buf = calloc (err_size+1, 1);
|
||||
@ -8468,6 +8537,10 @@ if (switches & EXP_TYP_REGEX) {
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
if (switches & EXP_TYP_REGEX_I) {
|
||||
sim_printf ("Case independed matching is only valid for RegEx expect rules\n");
|
||||
return SCPE_ARG|SCPE_NOMESSAGE;
|
||||
}
|
||||
if (SCPE_OK != sim_decode_quoted_string (match, match_buf, &match_size)) {
|
||||
free (match_buf);
|
||||
return SCPE_ARG;
|
||||
@ -8477,6 +8550,10 @@ free (match_buf);
|
||||
ep = sim_exp_fnd (exp, match); /* present? */
|
||||
if (ep) /* no, allocate */
|
||||
sim_exp_clr_tab (exp, ep); /* clear it */
|
||||
if (after && exp->size) {
|
||||
sim_printf ("Multiple concurrent EXPECT rules aren't valid when a HALTAFTER parameter is non-zero\n");
|
||||
return SCPE_ARG|SCPE_NOMESSAGE;
|
||||
}
|
||||
exp->rules = (EXPTAB *) realloc (exp->rules, sizeof (*exp->rules)*(exp->size + 1));
|
||||
ep = &exp->rules[exp->size];
|
||||
exp->size += 1;
|
||||
@ -8543,6 +8620,8 @@ if (ep->switches & EXP_TYP_CLEARALL)
|
||||
fprintf (st, " -c");
|
||||
if (ep->switches & EXP_TYP_REGEX)
|
||||
fprintf (st, " -r");
|
||||
if (ep->switches & EXP_TYP_REGEX_I)
|
||||
fprintf (st, " -i");
|
||||
fprintf (st, " %s", ep->match_pattern);
|
||||
if (ep->cnt > 0)
|
||||
fprintf (st, " [%d]", ep->cnt);
|
||||
@ -8603,7 +8682,7 @@ for (i=0; i < exp->size; i++) {
|
||||
++regex_checks;
|
||||
matches = calloc ((ep->regex.re_nsub + 1), sizeof(*matches));
|
||||
exp->buf[exp->buf_ins] = '\0';
|
||||
if (!regexec (&ep->regex, (char *)exp->buf, ep->regex.re_nsub + 1, matches, 0)) {
|
||||
if (!regexec (&ep->regex, (char *)exp->buf, ep->regex.re_nsub + 1, matches, REG_NOTBOL|REG_NOTEOL)) {
|
||||
size_t j;
|
||||
char *buf = malloc (1 + exp->buf_ins);
|
||||
|
||||
@ -8651,7 +8730,8 @@ if (exp->buf_ins == exp->buf_size) { /* At end of match buffe
|
||||
/* When processing regular expressions, let the match buffer fill
|
||||
up and then shuffle the buffer contents down by half the buffer size
|
||||
so that the regular expression has a single contiguous buffer to
|
||||
match against instead of the wrapping buffer which is used otherwise */
|
||||
match against instead of the wrapping buffer paradigm which is
|
||||
used when no regular expression rules are in effect */
|
||||
memmove (exp->buf, &exp->buf[exp->buf_size/2], exp->buf_size-(exp->buf_size/2));
|
||||
exp->buf_ins -= exp->buf_size/2;
|
||||
}
|
||||
@ -8680,6 +8760,8 @@ if (i != exp->size) { /* Found? */
|
||||
sim_exp_clrall (exp); /* delete all rules */
|
||||
sim_activate (&sim_expect_unit, exp->after); /* schedule simulation stop when indicated */
|
||||
}
|
||||
/* Matched data is no longer available for future matching */
|
||||
exp->buf_ins = 0;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -655,6 +655,7 @@ struct sim_exptab {
|
||||
#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_REGEX (SWMASK ('R')) /* rule pattern is a regular expression */
|
||||
#define EXP_TYP_REGEX_I (SWMASK ('I')) /* regular expression pattern matching should be case independent */
|
||||
#if defined(USE_REGEX)
|
||||
regex_t regex; /* compiled regular expression */
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user