diff --git a/AltairZ80/altairZ80_sio.c b/AltairZ80/altairZ80_sio.c index 1ae1b9357381b399640f59c2325ffeccb2c62873..e6cf3e362eca528ee37cd4a667d2c7857e106d46 100644 --- a/AltairZ80/altairZ80_sio.c +++ b/AltairZ80/altairZ80_sio.c @@ -148,7 +148,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; @@ -1180,7 +1179,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 */ diff --git a/scp.c b/scp.c index f64196a2af078a6650540cca902b294959fc957b..c8b3bf44a75add82b81c3f911be7c44df9559dd3 100644 --- a/scp.c +++ b/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 08-Feb-09 RMS Fixed warnings in help printouts 29-Dec-08 RMS Fixed implementation of MTAB_NC 24-Nov-08 RMS Revised RESTORE unit logic for consistency @@ -182,6 +183,7 @@ #include "sim_rev.h" #include <signal.h> #include <ctype.h> +#include <time.h> #define EX_D 0 /* deposit */ #define EX_E 1 /* examine */ @@ -201,7 +203,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 @@ -286,6 +288,7 @@ t_stat show_dev_logicals (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char * t_stat show_dev_modifiers (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); @@ -347,6 +350,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 */ @@ -363,7 +368,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; @@ -380,6 +385,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) }; @@ -393,7 +405,7 @@ static const char *sim_sa64 = "64b addresses"; #else static const char *sim_sa64 = "32b addresses"; #endif -#if defined USE_NETWORK +#if defined USE_NETWORK || defined USE_SHARED static const char *sim_snet = "Ethernet support"; #else static const char *sim_snet = "no Ethernet"; @@ -404,51 +416,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) @@ -543,6 +558,8 @@ static CTAB cmd_table[] = { "set <unit> ENABLED enable unit\n" "set <unit> DISABLED disable unit\n" "set <unit> arg{,arg...} set unit parameters\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" @@ -560,9 +577,18 @@ static CTAB cmd_table[] = { "sh{ow} <dev> MODIFIERS show device modifiers\n" "sh{ow} <dev} NAMES show device logical name\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, @@ -632,7 +658,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) { @@ -641,12 +667,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) { @@ -687,9 +713,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); @@ -769,6 +795,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)) @@ -780,12 +807,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 */ @@ -831,7 +858,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; @@ -875,6 +902,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 */ @@ -891,13 +921,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 */ } @@ -907,6 +942,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 */ @@ -919,19 +958,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 @@ -957,16 +1019,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); @@ -1025,6 +1120,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) @@ -1049,6 +1230,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 } }; @@ -1311,6 +1494,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 } }; @@ -1618,6 +1802,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) @@ -2686,7 +2895,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) @@ -4397,7 +4606,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; } @@ -4598,7 +4807,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; @@ -4612,21 +4821,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; } @@ -4635,7 +4844,7 @@ return buf; void sim_brk_clract (void) { -sim_brk_act = NULL; +sim_brk_act[sim_do_depth] = NULL; } /* New PC */ @@ -4664,6 +4873,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_^"; diff --git a/scp.h b/scp.h index cdb2c33a6edcdafbad433a286ccbcbe4706e3ede..cb22baa005ba301354cd4e4ed5564cff94369991 100644 --- a/scp.h +++ b/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); diff --git a/sim_defs.h b/sim_defs.h index 66f67d4450decc9382f15395253ff4821aabb50b..89ea0f8320be85ba4242cc7523be2d3218c2ad7e 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -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 */