Merge branch 'ControlFlow' into simv3.8-2-rc2
Conflicts: scp.c
This commit is contained in:
commit
8eb9caff10
4 changed files with 338 additions and 86 deletions
|
@ -149,7 +149,6 @@ extern const t_bool rtc_avail;
|
|||
extern uint32 PCX;
|
||||
extern int32 sim_switches;
|
||||
extern int32 sim_quiet;
|
||||
extern const char *scp_error_messages[];
|
||||
extern int32 SR;
|
||||
extern UNIT cpu_unit;
|
||||
extern volatile int32 stop_cpu;
|
||||
|
@ -1189,7 +1188,7 @@ static void attachCPM(UNIT *uptr) {
|
|||
sim_quiet = sim_switches & SWMASK ('Q'); /* -q means quiet */
|
||||
lastCPMStatus = attach_unit(uptr, cpmCommandLine);
|
||||
if ((lastCPMStatus != SCPE_OK) && (simh_device.dctrl & VERBOSE_MSG))
|
||||
printf("SIMH: " ADDRESS_FORMAT " Cannot open '%s' (%s)." NLP, PCX, cpmCommandLine, scp_error_messages[lastCPMStatus - SCPE_BASE]);
|
||||
printf("SIMH: " ADDRESS_FORMAT " Cannot open '%s' (%s)." NLP, PCX, cpmCommandLine, sim_error_text(lastCPMStatus));
|
||||
}
|
||||
|
||||
/* setClockZSDOSAdr points to 6 byte block in M: YY MM DD HH MM SS in BCD notation */
|
||||
|
|
414
scp.c
414
scp.c
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-Jan-11 MP Added SET ON, SET NOON, ON, GOTO and RETURN command support
|
||||
13-Jan-11 MP Added "SHOW SHOW" and "SHOW <dev> SHOW" commands
|
||||
05-Jan-11 RMS Fixed bug in deposit stride for numeric input (John Dundas)
|
||||
23-Dec-10 RMS Clarified some help messages (Mark Pizzolato)
|
||||
|
@ -187,6 +188,7 @@
|
|||
#include "sim_rev.h"
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined(HAVE_READLINE)
|
||||
#include <readline/readline.h>
|
||||
|
@ -211,7 +213,7 @@
|
|||
#define SSH_SH 1 /* show */
|
||||
#define SSH_CL 2 /* clear */
|
||||
|
||||
#define DO_NEST_LVL 10 /* DO cmd nesting level */
|
||||
#define MAX_DO_NEST_LVL 10 /* DO cmd nesting level */
|
||||
#define SRBSIZ 1024 /* save/restore buffer */
|
||||
#define SIM_BRK_INILNT 4096 /* bpt tbl length */
|
||||
#define SIM_BRK_ALLTYP 0xFFFFFFFF
|
||||
|
@ -298,6 +300,7 @@ t_stat show_dev_modifiers (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char
|
|||
t_stat show_dev_show_commands (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_version (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_break (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_on (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_device (FILE *st, DEVICE *dptr, int32 flag);
|
||||
t_stat show_unit (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag);
|
||||
t_stat show_all_mods (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flg);
|
||||
|
@ -360,6 +363,8 @@ t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr,
|
|||
UNIT *uptr, int32 dfltinc);
|
||||
t_stat step_svc (UNIT *ptr);
|
||||
void sub_args (char *instr, char *tmpbuf, int32 maxstr, char *do_arg[]);
|
||||
t_stat set_on (int32 flag, char *cptr);
|
||||
|
||||
|
||||
/* Global data */
|
||||
|
||||
|
@ -376,7 +381,7 @@ int32 sim_is_running = 0;
|
|||
uint32 sim_brk_summ = 0;
|
||||
uint32 sim_brk_types = 0;
|
||||
uint32 sim_brk_dflt = 0;
|
||||
char *sim_brk_act = NULL;
|
||||
char *sim_brk_act[MAX_DO_NEST_LVL];
|
||||
BRKTAB *sim_brk_tab = NULL;
|
||||
int32 sim_brk_ent = 0;
|
||||
int32 sim_brk_lnt = 0;
|
||||
|
@ -393,6 +398,13 @@ t_value *sim_eval = NULL;
|
|||
int32 sim_deb_close = 0; /* 1 = close debug */
|
||||
FILE *sim_log = NULL; /* log file */
|
||||
FILE *sim_deb = NULL; /* debug file */
|
||||
|
||||
static FILE *sim_gotofile;
|
||||
static int32 sim_do_depth = 0;
|
||||
|
||||
static int32 sim_on_check[MAX_DO_NEST_LVL+1];
|
||||
static char *sim_on_actions[MAX_DO_NEST_LVL+1][SCPE_MAX_ERR+1];
|
||||
|
||||
static SCHTAB sim_stab;
|
||||
|
||||
static UNIT sim_step_unit = { UDATA (&step_svc, 0, 0) };
|
||||
|
@ -417,51 +429,54 @@ static const char *sim_snet = "no Ethernet";
|
|||
const char save_vercur[] = "V3.5";
|
||||
const char save_ver32[] = "V3.2";
|
||||
const char save_ver30[] = "V3.0";
|
||||
const char *scp_error_messages[] = {
|
||||
"Address space exceeded",
|
||||
"Unit not attached",
|
||||
"I/O error",
|
||||
"Checksum error",
|
||||
"Format error",
|
||||
"Unit not attachable",
|
||||
"File open error",
|
||||
"Memory exhausted",
|
||||
"Invalid argument",
|
||||
"Step expired",
|
||||
"Unknown command",
|
||||
"Read only argument",
|
||||
"Command not completed",
|
||||
"Simulation stopped",
|
||||
"Goodbye",
|
||||
"Console input I/O error",
|
||||
"Console output I/O error",
|
||||
"End of file",
|
||||
"Relocation error",
|
||||
"No settable parameters",
|
||||
"Unit already attached",
|
||||
"Hardware timer error",
|
||||
"SIGINT handler setup error",
|
||||
"Console terminal setup error",
|
||||
"Subscript out of range",
|
||||
"Command not allowed",
|
||||
"Unit disabled",
|
||||
"Read only operation not allowed",
|
||||
"Invalid switch",
|
||||
"Missing value",
|
||||
"Too few arguments",
|
||||
"Too many arguments",
|
||||
"Non-existent device",
|
||||
"Non-existent unit",
|
||||
"Non-existent register",
|
||||
"Non-existent parameter",
|
||||
"Nested DO command limit exceeded",
|
||||
"Internal error",
|
||||
"Invalid magtape record length",
|
||||
"Console Telnet connection lost",
|
||||
"Console Telnet connection timed out",
|
||||
"Console Telnet output stall",
|
||||
"Assertion failed"
|
||||
};
|
||||
const struct scp_error {
|
||||
char *code;
|
||||
char *message;
|
||||
} scp_errors[1+SCPE_MAX_ERR-SCPE_BASE] =
|
||||
{{"NXM", "Address space exceeded"},
|
||||
{"UNATT", "Unit not attached"},
|
||||
{"IOERR", "I/O error"},
|
||||
{"CSUM", "Checksum error"},
|
||||
{"FMT", "Format error"},
|
||||
{"NOATT", "Unit not attachable"},
|
||||
{"OPENERR", "File open error"},
|
||||
{"MEM", "Memory exhausted"},
|
||||
{"ARG", "Invalid argument"},
|
||||
{"STEP", "Step expired"},
|
||||
{"UNK", "Unknown command"},
|
||||
{"RO", "Read only argument"},
|
||||
{"INCOMP", "Command not completed"},
|
||||
{"STOP", "Simulation stopped"},
|
||||
{"EXIT", "Goodbye"},
|
||||
{"TTIERR", "Console input I/O error"},
|
||||
{"TTOERR", "Console output I/O error"},
|
||||
{"EOF", "End of file"},
|
||||
{"REL", "Relocation error"},
|
||||
{"NOPARAM", "No settable parameters"},
|
||||
{"ALATT", "Unit already attached"},
|
||||
{"TIMER", "Hardware timer error"},
|
||||
{"SIGERR", "SIGINT handler setup error"},
|
||||
{"TTYERR", "Console terminal setup error"},
|
||||
{"SUB", "Subscript out of range"},
|
||||
{"NOFNC", "Command not allowed"},
|
||||
{"UDIS", "Unit disabled"},
|
||||
{"NORO", "Read only operation not allowed"},
|
||||
{"INVSW", "Invalid switch"},
|
||||
{"MISVAL", "Missing value"},
|
||||
{"2FARG", "Too few arguments"},
|
||||
{"2MARG", "Too many arguments"},
|
||||
{"NXDEV", "Non-existent device"},
|
||||
{"NXUN", "Non-existent unit"},
|
||||
{"NXREG", "Non-existent register"},
|
||||
{"NXPAR", "Non-existent parameter"},
|
||||
{"NEST", "Nested DO command limit exceeded"},
|
||||
{"IERR", "Internal error"},
|
||||
{"MTRLNT", "Invalid magtape record length"},
|
||||
{"LOST", "Console Telnet connection lost"},
|
||||
{"TTMO", "Console Telnet connection timed out"},
|
||||
{"STALL", "Console Telnet output stall"},
|
||||
{"AFAIL", "Assertion failed"},
|
||||
};
|
||||
|
||||
const size_t size_map[] = { sizeof (int8),
|
||||
sizeof (int8), sizeof (int16), sizeof (int32), sizeof (int32)
|
||||
|
@ -556,6 +571,8 @@ static CTAB cmd_table[] = {
|
|||
"set <unit> ENABLED enable unit\n"
|
||||
"set <unit> DISABLED disable unit\n"
|
||||
"set <unit> arg{,arg...} set unit parameters (see show modifiers)\n"
|
||||
"set on enables error checking after command execution\n"
|
||||
"set noon disables error checking after command execution\n"
|
||||
},
|
||||
{ "SHOW", &show_cmd, 0,
|
||||
"sh{ow} br{eak} <list> show breakpoints\n"
|
||||
|
@ -575,9 +592,18 @@ static CTAB cmd_table[] = {
|
|||
"sh{ow} <dev> NAMES show device logical name\n"
|
||||
"sh{ow} <dev> SHOW show device SHOW commands\n"
|
||||
"sh{ow} <dev> {arg,...} show device parameters\n"
|
||||
"sh{ow} <unit> {arg,...} show unit parameters\n" },
|
||||
"sh{ow} <unit> {arg,...} show unit parameters\n"
|
||||
"sh{ow} on show on condition actions\n" },
|
||||
{ "DO", &do_cmd, 1,
|
||||
"do <file> {arg,arg...} process command file\n" },
|
||||
{ "GOTO", &goto_cmd, 1,
|
||||
"goto <label> goto label in command file\n" },
|
||||
{ "RETURN", &return_cmd, 0,
|
||||
"return return from command file with last command status\n"
|
||||
"return <status> return from command file with specific status\n" },
|
||||
{ "ON", &on_cmd, 0,
|
||||
"on <condition> <action> perform action after condition\n"
|
||||
"on <condition> clear action for specific condition\n" },
|
||||
{ "ECHO", &echo_cmd, 0,
|
||||
"echo <string> display <string>\n" },
|
||||
{ "ASSERT", &assert_cmd, 0,
|
||||
|
@ -647,7 +673,7 @@ sim_timer_init ();
|
|||
|
||||
if ((stat = sim_ttinit ()) != SCPE_OK) {
|
||||
fprintf (stderr, "Fatal terminal initialization error\n%s\n",
|
||||
scp_error_messages[stat - SCPE_BASE]);
|
||||
sim_error_text (stat));
|
||||
return 0;
|
||||
}
|
||||
if ((sim_eval = (t_value *) calloc (sim_emax, sizeof (t_value))) == NULL) {
|
||||
|
@ -656,12 +682,12 @@ if ((sim_eval = (t_value *) calloc (sim_emax, sizeof (t_value))) == NULL) {
|
|||
};
|
||||
if ((stat = reset_all_p (0)) != SCPE_OK) {
|
||||
fprintf (stderr, "Fatal simulator initialization error\n%s\n",
|
||||
scp_error_messages[stat - SCPE_BASE]);
|
||||
sim_error_text (stat));
|
||||
return 0;
|
||||
}
|
||||
if ((stat = sim_brk_init ()) != SCPE_OK) {
|
||||
fprintf (stderr, "Fatal breakpoint table initialization error\n%s\n",
|
||||
scp_error_messages[stat - SCPE_BASE]);
|
||||
sim_error_text (stat));
|
||||
return 0;
|
||||
}
|
||||
if (!sim_quiet) {
|
||||
|
@ -703,9 +729,9 @@ while (stat != SCPE_EXIT) { /* in case exit */
|
|||
stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */
|
||||
else stat = SCPE_UNK;
|
||||
if (stat >= SCPE_BASE) { /* error? */
|
||||
printf ("%s\n", scp_error_messages[stat - SCPE_BASE]);
|
||||
printf ("%s\n", sim_error_text (stat));
|
||||
if (sim_log)
|
||||
fprintf (sim_log, "%s\n", scp_error_messages[stat - SCPE_BASE]);
|
||||
fprintf (sim_log, "%s\n", sim_error_text (stat));
|
||||
}
|
||||
if (sim_vm_post != NULL)
|
||||
(*sim_vm_post) (TRUE);
|
||||
|
@ -785,6 +811,7 @@ return SCPE_OK;
|
|||
|
||||
t_stat spawn_cmd (int32 flag, char *cptr)
|
||||
{
|
||||
t_stat status;
|
||||
if ((cptr == NULL) || (strlen (cptr) == 0))
|
||||
cptr = getenv("SHELL");
|
||||
if ((cptr == NULL) || (strlen (cptr) == 0))
|
||||
|
@ -796,12 +823,12 @@ if ((cptr == NULL) || (strlen (cptr) == 0))
|
|||
fflush(stdout); /* flush stdout */
|
||||
if (sim_log) /* flush log if enabled */
|
||||
fflush (sim_log);
|
||||
system (cptr);
|
||||
status = system (cptr);
|
||||
#if defined (VMS)
|
||||
printf ("\n");
|
||||
#endif
|
||||
|
||||
return SCPE_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Echo command */
|
||||
|
@ -847,7 +874,7 @@ t_stat do_cmd (int32 flag, char *fcptr)
|
|||
char *cptr, cbuf[CBUFSIZE], gbuf[CBUFSIZE], *c, quote, *do_arg[10];
|
||||
FILE *fpin;
|
||||
CTAB *cmdp;
|
||||
int32 echo, nargs, errabort;
|
||||
int32 echo, nargs, errabort, i;
|
||||
t_bool interactive, isdo, staying;
|
||||
t_stat stat;
|
||||
char *ocptr;
|
||||
|
@ -891,6 +918,9 @@ if ((fpin = fopen (do_arg[0], "r")) == NULL) { /* file failed to open?
|
|||
}
|
||||
if (flag < 1) /* start at level 1 */
|
||||
flag = 1;
|
||||
++sim_do_depth;
|
||||
if (errabort) /* -e flag? */
|
||||
set_on (1, NULL); /* equivalent to ON ERROR RETURN */
|
||||
|
||||
do {
|
||||
ocptr = cptr = sim_brk_getact (cbuf, CBUFSIZE); /* get bkpt action */
|
||||
|
@ -907,13 +937,18 @@ do {
|
|||
printf("do> %s\n", cptr);
|
||||
if (echo && sim_log)
|
||||
fprintf (sim_log, "do> %s\n", cptr);
|
||||
if (*cptr == ':') /* ignore label */
|
||||
continue;
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
|
||||
sim_switches = 0; /* init switches */
|
||||
isdo = FALSE;
|
||||
sim_gotofile = fpin;
|
||||
if (cmdp = find_cmd (gbuf)) { /* lookup command */
|
||||
if ((cmdp->action == &return_cmd)) /* RETURN command? */
|
||||
break; /* done! */
|
||||
isdo = (cmdp->action == &do_cmd);
|
||||
if (isdo) { /* DO command? */
|
||||
if (flag >= DO_NEST_LVL) /* nest too deep? */
|
||||
if (flag >= MAX_DO_NEST_LVL) /* nest too deep? */
|
||||
stat = SCPE_NEST;
|
||||
else stat = do_cmd (flag + 1, cptr); /* exec DO cmd */
|
||||
}
|
||||
|
@ -923,6 +958,10 @@ do {
|
|||
staying = (stat != SCPE_EXIT) && /* decide if staying */
|
||||
(stat != SCPE_AFAIL) &&
|
||||
(!errabort || (stat < SCPE_BASE) || (stat == SCPE_STEP));
|
||||
if ((stat == SCPE_AFAIL) && /* handle special case AFAIL */
|
||||
sim_on_check[sim_do_depth] && /* and use trap action if defined */
|
||||
sim_on_actions[sim_do_depth][stat]) /* otherwise exit */
|
||||
staying = TRUE;
|
||||
if ((stat >= SCPE_BASE) && (stat != SCPE_EXIT) && /* error from cmd? */
|
||||
(stat != SCPE_STEP)) {
|
||||
if (!echo && !sim_quiet && /* report if not echoing */
|
||||
|
@ -935,19 +974,42 @@ do {
|
|||
}
|
||||
if ((staying || !interactive) && /* report error if staying */
|
||||
(stat >= SCPE_BASE)) { /* or in cmdline file */
|
||||
printf ("%s\n", scp_error_messages[stat - SCPE_BASE]);
|
||||
printf ("%s\n", sim_error_text (stat));
|
||||
if (sim_log)
|
||||
fprintf (sim_log, "%s\n", scp_error_messages[stat - SCPE_BASE]);
|
||||
fprintf (sim_log, "%s\n", sim_error_text (stat));
|
||||
}
|
||||
if (staying &&
|
||||
(sim_on_check[sim_do_depth]) &&
|
||||
(stat != SCPE_OK) &&
|
||||
(stat != SCPE_STEP))
|
||||
if (sim_on_actions[sim_do_depth][stat])
|
||||
sim_brk_act[sim_do_depth] = sim_on_actions[sim_do_depth][stat];
|
||||
else
|
||||
sim_brk_act[sim_do_depth] = sim_on_actions[sim_do_depth][0];
|
||||
if (sim_vm_post != NULL)
|
||||
(*sim_vm_post) (TRUE);
|
||||
} while (staying);
|
||||
|
||||
fclose (fpin); /* close file */
|
||||
return stat;
|
||||
sim_gotofile = NULL;
|
||||
for (i=0; i<SCPE_MAX_ERR; i++) { /* release any on commands */
|
||||
free (sim_on_actions[sim_do_depth][i]);
|
||||
sim_on_actions[sim_do_depth][i] = NULL;
|
||||
}
|
||||
sim_on_check[sim_do_depth] = 0; /* clear on mode */
|
||||
sim_brk_clract (); /* defang breakpoint actions */
|
||||
--sim_do_depth; /* unwind nesting */
|
||||
if (cmdp && (cmdp->action == &return_cmd)) { /* return command? */
|
||||
if (0 == *cptr)
|
||||
return stat; /* return with last command status */
|
||||
sim_string_to_stat (cptr, &stat);
|
||||
return stat; /* return with explicit return status */
|
||||
}
|
||||
return (stat == SCPE_EXIT) ? SCPE_EXIT : SCPE_OK;
|
||||
}
|
||||
|
||||
/* Substitute_args - replace %n tokens in 'instr' with the do command's arguments
|
||||
and other enviroment variables
|
||||
|
||||
Calling sequence
|
||||
instr = input string
|
||||
|
@ -973,16 +1035,49 @@ for (ip = instr, op = tmpbuf; *ip && (op < oend); ) {
|
|||
ip++; /* skip '\' */
|
||||
*op++ = *ip++; /* copy escaped char */
|
||||
}
|
||||
else if ((*ip == '%') && /* %n = sub */
|
||||
((ip[1] >= '0') && (ip[1] <= ('9')))) {
|
||||
ap = do_arg[ip[1] - '0'];
|
||||
ip = ip + 2;
|
||||
if (ap) { /* non-null arg? */
|
||||
while (*ap && (op < oend)) /* copy the argument */
|
||||
*op++ = *ap++;
|
||||
else
|
||||
if (*ip == '%') { /* sub? */
|
||||
if ((ip[1] >= '0') && (ip[1] <= ('9'))) { /* %n = sub */
|
||||
ap = do_arg[ip[1] - '0'];
|
||||
ip = ip + 2;
|
||||
}
|
||||
else { /* environment variable */
|
||||
char gbuf[CBUFSIZE];
|
||||
|
||||
ap = NULL;
|
||||
get_glyph_gen (ip+1, gbuf, '%', FALSE);
|
||||
ip += 1 + strlen (gbuf);
|
||||
if (*ip == '%') ++ip;
|
||||
ap = getenv(gbuf);
|
||||
if (!ap) {
|
||||
static char rbuf[CBUFSIZE];
|
||||
time_t now;
|
||||
struct tm *tmnow;
|
||||
|
||||
time(&now);
|
||||
tmnow = localtime(&now);
|
||||
if (!strcmp ("DATE", gbuf)) {
|
||||
sprintf (rbuf, "%4d/%02d/%02d", tmnow->tm_year+1900, tmnow->tm_mon+1, tmnow->tm_mday);
|
||||
ap = rbuf;
|
||||
}
|
||||
else if (!strcmp ("TIME", gbuf)) {
|
||||
sprintf (rbuf, "%02d:%02d:%02d", tmnow->tm_hour, tmnow->tm_min, tmnow->tm_sec);
|
||||
ap = rbuf;
|
||||
}
|
||||
else if (!strcmp ("CTIME", gbuf)) {
|
||||
strcpy (rbuf, ctime(&now));
|
||||
rbuf[strlen (rbuf)-1] = '\0'; /* remove trailing \n */
|
||||
ap = rbuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ap) { /* non-null arg? */
|
||||
while (*ap && (op < oend)) /* copy the argument */
|
||||
*op++ = *ap++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else *op++ = *ip++; /* literal character */
|
||||
else
|
||||
*op++ = *ip++; /* literal character */
|
||||
}
|
||||
*op = 0; /* term buffer */
|
||||
strcpy (instr, tmpbuf);
|
||||
|
@ -1041,6 +1136,92 @@ if (test_search (val, &sim_stab)) /* test condition */
|
|||
return SCPE_AFAIL; /* condition fails */
|
||||
}
|
||||
|
||||
|
||||
/* Goto command */
|
||||
|
||||
t_stat goto_cmd (int32 flag, char *fcptr)
|
||||
{
|
||||
char *cptr, cbuf[CBUFSIZE], gbuf[CBUFSIZE], gbuf1[CBUFSIZE];
|
||||
long fpos;
|
||||
|
||||
if (NULL == sim_gotofile) return SCPE_UNK; /* only valid inside of do_cmd */
|
||||
get_glyph (fcptr, gbuf1, 0);
|
||||
if ('\0' == gbuf1[0]) return SCPE_ARG; /* unspecified goto target */
|
||||
fpos = ftell(sim_gotofile); /* Save start position */
|
||||
rewind(sim_gotofile); /* start search for label */
|
||||
while (1) {
|
||||
cptr = read_line (cbuf, CBUFSIZE, sim_gotofile); /* get cmd line */
|
||||
if (cptr == NULL) break; /* exit on eof */
|
||||
if (*cptr == 0) continue; /* ignore blank */
|
||||
if (*cptr != ':') continue; /* ignore non-labels */
|
||||
++cptr; /* skip : */
|
||||
while (isspace (*cptr)) ++cptr; /* skip blanks */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get label glyph */
|
||||
if (0 == strcmp(gbuf, gbuf1)) {
|
||||
sim_brk_clract (); /* goto defangs current actions */
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
fseek(sim_gotofile, fpos, SEEK_SET); /* resture start position */
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
/* Return command */
|
||||
/* The return command is invalid unless encountered in a do_cmd context, */
|
||||
/* and in that context, it is handled as a special case inside of do_cmd() */
|
||||
/* and not dispatched here, so if we get here a return has been issued from */
|
||||
/* interactive input */
|
||||
|
||||
t_stat return_cmd (int32 flag, char *fcptr)
|
||||
{
|
||||
return SCPE_UNK; /* only valid inside of do_cmd */
|
||||
}
|
||||
|
||||
/* On command */
|
||||
|
||||
t_stat on_cmd (int32 flag, char *cptr)
|
||||
{
|
||||
char gbuf[CBUFSIZE];
|
||||
int32 cond;
|
||||
|
||||
cptr = get_glyph (cptr, gbuf, 0);
|
||||
if ('\0' == gbuf[0]) return SCPE_ARG; /* unspecified condition */
|
||||
if (0 == strcmp("ERROR", gbuf))
|
||||
cond = 0;
|
||||
else
|
||||
if (SCPE_OK != sim_string_to_stat (gbuf, &cond))
|
||||
return SCPE_ARG;
|
||||
if ((NULL == cptr) || ('\0' == *cptr)) { /* Empty Action */
|
||||
free(sim_on_actions[sim_do_depth][cond]); /* Clear existing condition */
|
||||
sim_on_actions[sim_do_depth][cond] = NULL; }
|
||||
else {
|
||||
sim_on_actions[sim_do_depth][cond] =
|
||||
realloc(sim_on_actions[sim_do_depth][cond], 1+strlen(cptr));
|
||||
strcpy(sim_on_actions[sim_do_depth][cond], cptr);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat set_on (int32 flag, char *cptr)
|
||||
{
|
||||
if (cptr && (*cptr != 0)) /* now eol? */
|
||||
return SCPE_2MARG;
|
||||
sim_on_check[sim_do_depth] = flag;
|
||||
if ((sim_do_depth != 0) &&
|
||||
(NULL == sim_on_actions[sim_do_depth][0])) { /* default handler set? */
|
||||
sim_on_actions[sim_do_depth][0] = /* No, so make "RETURN" */
|
||||
malloc(1+strlen("RETURN")); /* be the default action */
|
||||
strcpy(sim_on_actions[sim_do_depth][0], "RETURN");
|
||||
}
|
||||
if ((sim_do_depth != 0) &&
|
||||
(NULL == sim_on_actions[sim_do_depth][SCPE_AFAIL])) {/* handler set for AFAIL? */
|
||||
sim_on_actions[sim_do_depth][SCPE_AFAIL] = /* No, so make "RETURN" */
|
||||
malloc(1+strlen("RETURN")); /* be the action */
|
||||
strcpy(sim_on_actions[sim_do_depth][SCPE_AFAIL], "RETURN");
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set command */
|
||||
|
||||
t_stat set_cmd (int32 flag, char *cptr)
|
||||
|
@ -1065,6 +1246,8 @@ static CTAB set_glob_tab[] = {
|
|||
{ "NODEBUG", &sim_set_deboff, 0 }, /* deprecated */
|
||||
{ "THROTTLE", &sim_set_throt, 1 },
|
||||
{ "NOTHROTTLE", &sim_set_throt, 0 },
|
||||
{ "ON", &set_on, 1 },
|
||||
{ "NOON", &set_on, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -1328,6 +1511,7 @@ static SHTAB show_glob_tab[] = {
|
|||
{ "TELNET", &sim_show_telnet, 0 }, /* deprecated */
|
||||
{ "DEBUG", &sim_show_debug, 0 }, /* deprecated */
|
||||
{ "THROTTLE", &sim_show_throt, 0 },
|
||||
{ "ON", &show_on, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -1636,6 +1820,31 @@ if (dptr->flags & DEV_DEBUG) {
|
|||
else return SCPE_NOFNC;
|
||||
}
|
||||
|
||||
/* Show On actions */
|
||||
|
||||
t_stat show_on (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
|
||||
{
|
||||
int32 lvl, i;
|
||||
if (cptr && (*cptr != 0)) return SCPE_2MARG; /* now eol? */
|
||||
for (lvl=sim_do_depth; lvl >= 0; --lvl) {
|
||||
if (lvl > 0)
|
||||
fprintf(st, "On Processing at Do Nest Level: %d", lvl);
|
||||
else
|
||||
fprintf(st, "On Processing for input commands");
|
||||
fprintf(st, " is %s\n", (sim_on_check[lvl]) ? "enabled" : "disabled");
|
||||
for (i=1; i<SCPE_BASE; ++i) {
|
||||
if (sim_on_actions[lvl][i])
|
||||
fprintf(st, " on %5d %s\n", i, sim_on_actions[lvl][i]); }
|
||||
for (i=SCPE_BASE; i<=SCPE_MAX_ERR; ++i) {
|
||||
if (sim_on_actions[lvl][i])
|
||||
fprintf(st, " on %-5s %s\n", scp_errors[i-SCPE_BASE].code, sim_on_actions[lvl][i]); }
|
||||
if (sim_on_actions[lvl][0])
|
||||
fprintf(st, " on ERROR %s\n", sim_on_actions[lvl][0]);
|
||||
fprintf(st, "\n");
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show modifiers */
|
||||
|
||||
t_stat show_mod_names (FILE *st, DEVICE *dnotused, UNIT *unotused, int32 flag, char *cptr)
|
||||
|
@ -2739,7 +2948,7 @@ t_addr k;
|
|||
t_value pcval;
|
||||
|
||||
if (v >= SCPE_BASE) fprintf (st, "\n%s, %s: ",
|
||||
scp_error_messages[v - SCPE_BASE], pc->name);
|
||||
sim_error_text (v), pc->name);
|
||||
else fprintf (st, "\n%s, %s: ", sim_stop_messages[v], pc->name);
|
||||
pcval = get_rval (pc, 0);
|
||||
if (sim_vm_fprint_addr)
|
||||
|
@ -4486,7 +4695,7 @@ sim_brk_tab = (BRKTAB *) calloc (sim_brk_lnt, sizeof (BRKTAB));
|
|||
if (sim_brk_tab == NULL)
|
||||
return SCPE_MEM;
|
||||
sim_brk_ent = sim_brk_ins = 0;
|
||||
sim_brk_act = NULL;
|
||||
sim_brk_act[sim_do_depth] = NULL;
|
||||
sim_brk_npc (0);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -4687,7 +4896,7 @@ if ((bp = sim_brk_fnd (loc)) && (btyp & bp->typ)) { /* in table, type match?
|
|||
bp->cnt = 0; /* reset count */
|
||||
sim_brk_ploc[spc] = loc; /* save location */
|
||||
sim_brk_pend[spc] = TRUE; /* don't do twice */
|
||||
sim_brk_act = bp->act; /* set up actions */
|
||||
sim_brk_act[sim_do_depth] = bp->act; /* set up actions */
|
||||
return (btyp & bp->typ);
|
||||
}
|
||||
sim_brk_pend[spc] = FALSE;
|
||||
|
@ -4701,21 +4910,21 @@ char *sim_brk_getact (char *buf, int32 size)
|
|||
char *ep;
|
||||
size_t lnt;
|
||||
|
||||
if (sim_brk_act == NULL) /* any action? */
|
||||
if (sim_brk_act[sim_do_depth] == NULL) /* any action? */
|
||||
return NULL;
|
||||
while (isspace (*sim_brk_act)) /* skip spaces */
|
||||
sim_brk_act++;
|
||||
if (*sim_brk_act == 0) /* now empty? */
|
||||
return (sim_brk_act = NULL);
|
||||
if (ep = strchr (sim_brk_act, ';')) { /* cmd delimiter? */
|
||||
lnt = ep - sim_brk_act; /* cmd length */
|
||||
memcpy (buf, sim_brk_act, lnt + 1); /* copy with ; */
|
||||
while (isspace (*sim_brk_act[sim_do_depth])) /* skip spaces */
|
||||
sim_brk_act[sim_do_depth]++;
|
||||
if (*sim_brk_act[sim_do_depth] == 0) /* now empty? */
|
||||
return (sim_brk_act[sim_do_depth] = NULL);
|
||||
if (ep = strchr (sim_brk_act[sim_do_depth], ';')) { /* cmd delimiter? */
|
||||
lnt = ep - sim_brk_act[sim_do_depth]; /* cmd length */
|
||||
memcpy (buf, sim_brk_act[sim_do_depth], lnt + 1); /* copy with ; */
|
||||
buf[lnt] = 0; /* erase ; */
|
||||
sim_brk_act = sim_brk_act + lnt + 1; /* adv ptr */
|
||||
sim_brk_act[sim_do_depth] += lnt + 1; /* adv ptr */
|
||||
}
|
||||
else {
|
||||
strncpy (buf, sim_brk_act, size); /* copy action */
|
||||
sim_brk_act = NULL; /* no more */
|
||||
strncpy (buf, sim_brk_act[sim_do_depth], size); /* copy action */
|
||||
sim_brk_act[sim_do_depth] = NULL; /* no more */
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
@ -4724,7 +4933,7 @@ return buf;
|
|||
|
||||
void sim_brk_clract (void)
|
||||
{
|
||||
sim_brk_act = NULL;
|
||||
sim_brk_act[sim_do_depth] = NULL;
|
||||
}
|
||||
|
||||
/* New PC */
|
||||
|
@ -4753,6 +4962,43 @@ if (spc < SIM_BKPT_N_SPC) {
|
|||
return;
|
||||
}
|
||||
|
||||
/* Message Text */
|
||||
|
||||
char *sim_error_text (t_stat stat)
|
||||
{
|
||||
static char msgbuf[64];
|
||||
|
||||
stat &= ~(SCPE_KFLAG|SCPE_BREAK); /* remove any flags */
|
||||
if ((stat >= SCPE_BASE) && (stat <= SCPE_MAX_ERR))
|
||||
return scp_errors[stat-SCPE_BASE].message;
|
||||
sprintf(msgbuf, "Error %d", stat);
|
||||
return msgbuf;
|
||||
}
|
||||
|
||||
t_stat sim_string_to_stat (char *cptr, t_stat *stat)
|
||||
{
|
||||
char gbuf[CBUFSIZE];
|
||||
int32 cond;
|
||||
|
||||
*stat = SCPE_ARG;
|
||||
cptr = get_glyph (cptr, gbuf, 0);
|
||||
if (0 == memcmp("SCPE_", gbuf, 5))
|
||||
strcpy (gbuf, gbuf+5); /* skip leading SCPE_ */
|
||||
for (cond=0; cond < (SCPE_MAX_ERR-SCPE_BASE); cond++)
|
||||
if (0 == strcmp(scp_errors[cond].code, gbuf)) {
|
||||
cond += SCPE_BASE;
|
||||
break;
|
||||
}
|
||||
if (cond == (SCPE_MAX_ERR-SCPE_BASE)) { /* not found? */
|
||||
if (0 == (cond = strtol(gbuf, NULL, 0))) /* try explicit number */
|
||||
return SCPE_ARG;
|
||||
}
|
||||
if (cond > SCPE_MAX_ERR)
|
||||
return SCPE_ARG;
|
||||
*stat = cond;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Debug printout routines, from Dave Hittner */
|
||||
|
||||
const char* debug_bstates = "01_^";
|
||||
|
|
5
scp.h
5
scp.h
|
@ -69,6 +69,9 @@ t_stat set_cmd (int32 flag, char *ptr);
|
|||
t_stat show_cmd (int32 flag, char *ptr);
|
||||
t_stat brk_cmd (int32 flag, char *ptr);
|
||||
t_stat do_cmd (int32 flag, char *ptr);
|
||||
t_stat goto_cmd (int32 flag, char *ptr);
|
||||
t_stat return_cmd (int32 flag, char *ptr);
|
||||
t_stat on_cmd (int32 flag, char *ptr);
|
||||
t_stat assert_cmd (int32 flag, char *ptr);
|
||||
t_stat help_cmd (int32 flag, char *ptr);
|
||||
t_stat spawn_cmd (int32 flag, char *ptr);
|
||||
|
@ -113,6 +116,8 @@ BRKTAB *sim_brk_fnd (t_addr loc);
|
|||
uint32 sim_brk_test (t_addr bloc, uint32 btyp);
|
||||
void sim_brk_clrspc (uint32 spc);
|
||||
char *match_ext (char *fnam, char *ext);
|
||||
char *sim_error_text (t_stat stat);
|
||||
t_stat sim_string_to_stat (char *cptr, t_stat *cond);
|
||||
t_stat sim_cancel_step (void);
|
||||
void sim_debug_u16 (uint32 dbits, DEVICE* dptr, const char* const* bitdefs,
|
||||
uint16 before, uint16 after, int terminate);
|
||||
|
|
|
@ -242,6 +242,8 @@ typedef uint32 t_addr;
|
|||
#define SCPE_TTMO (SCPE_BASE + 40) /* Telnet conn timeout */
|
||||
#define SCPE_STALL (SCPE_BASE + 41) /* Telnet conn stall */
|
||||
#define SCPE_AFAIL (SCPE_BASE + 42) /* assert failed */
|
||||
|
||||
#define SCPE_MAX_ERR (SCPE_BASE + 43) /* Maximum SCPE Error Value */
|
||||
#define SCPE_KFLAG 0010000 /* tti data flag */
|
||||
#define SCPE_BREAK 0020000 /* tti break flag */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue