From cbfaa373a403f54b2466f9d8ed6ed47466d7ae61 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 22 Mar 2020 15:11:09 -0400 Subject: [PATCH] SCP: Updated to current. --- scp.c | 120 +++++++++++++++++++++++++++++++++++++++++----------- sim_ether.c | 8 ++-- sim_sock.c | 11 +++-- sim_sock.h | 2 +- sim_timer.c | 8 ++++ sim_timer.h | 1 + sim_tmxr.c | 24 ++++++++--- 7 files changed, 136 insertions(+), 38 deletions(-) diff --git a/scp.c b/scp.c index e1c36b5..562b9df 100644 --- a/scp.c +++ b/scp.c @@ -267,7 +267,7 @@ #define SCH_GE 6 #define SCH_LE 7 -#define MAX_DO_NEST_LVL 20 /* DO cmd nesting level */ +#define MAX_DO_NEST_LVL 20 /* DO cmd nesting level limit */ #define SRBSIZ 1024 /* save/restore buffer */ #define SIM_BRK_INILNT 4096 /* bpt tbl length */ #define SIM_BRK_ALLTYP 0xFFFFFFFB @@ -481,6 +481,7 @@ t_stat show_version (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char t_stat show_default (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat show_break (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat show_on (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); +t_stat show_do (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat show_runlimit (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_send (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_expect (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); @@ -1543,6 +1544,7 @@ static const char simh_help[] = "+sh{ow} clocks show calibrated timer information\n" "+sh{ow} throttle show throttle info\n" "+sh{ow} on show on condition actions\n" + "+sh{ow} do show do nesting state\n" "+sh{ow} runlimit show execution limit states\n" "+h{elp} show displays the device specific show commands\n" "++++++++ available\n" @@ -1569,6 +1571,7 @@ static const char simh_help[] = #define HLP_SHOW_VIDEO "*Commands SHOW" #define HLP_SHOW_CLOCKS "*Commands SHOW" #define HLP_SHOW_ON "*Commands SHOW" +#define HLP_SHOW_DO "*Commands SHOW" #define HLP_SHOW_RUNLIMIT "*Commands SHOW" #define HLP_SHOW_SEND "*Commands SHOW" #define HLP_SHOW_EXPECT "*Commands SHOW" @@ -2539,7 +2542,8 @@ static SHTAB show_glob_tab[] = { { "CLOCKS", &sim_show_timers, 0, HLP_SHOW_CLOCKS }, { "SEND", &sim_show_send, 0, HLP_SHOW_SEND }, { "EXPECT", &sim_show_expect, 0, HLP_SHOW_EXPECT }, - { "ON", &show_on, 0, HLP_SHOW_ON }, + { "ON", &show_on, -1, HLP_SHOW_ON }, + { "DO", &show_do, 0, HLP_SHOW_DO }, { "RUNLIMIT", &show_runlimit, 0, HLP_SHOW_RUNLIMIT }, { NULL, NULL, 0 } }; @@ -2825,7 +2829,8 @@ while (stat != SCPE_EXIT) { /* in case exit */ if (sim_on_actions[sim_do_depth][ON_SIGINT_ACTION]) sim_brk_setact (sim_on_actions[sim_do_depth][ON_SIGINT_ACTION]); } - if ((cptr = sim_brk_getact (cbuf, sizeof(cbuf)))) { /* pending action? */ + sim_do_ocptr[sim_do_depth] = cptr = sim_brk_getact (cbuf, sizeof(cbuf)); /* get bkpt action */ + if (sim_do_ocptr[sim_do_depth]) { /* pending action? */ if (sim_do_echo) printf ("%s+ %s\n", sim_prompt, cptr); /* echo */ sim_cptr_is_action[sim_do_depth] = TRUE; @@ -2837,6 +2842,7 @@ while (stat != SCPE_EXIT) { /* in case exit */ } else cptr = read_line_p (sim_prompt, cbuf, sizeof(cbuf), stdin);/* read with prompt*/ + sim_do_ocptr[sim_do_depth] = cptr; sim_cptr_is_action[sim_do_depth] = FALSE; } if (cptr == NULL) { /* EOF? or SIGINT? */ @@ -2855,13 +2861,13 @@ while (stat != SCPE_EXIT) { /* in case exit */ fprintf (sim_log, "%s%s\n", sim_prompt, cptr); if (sim_deb && (sim_deb != sim_log) && (sim_deb != stdout)) fprintf (sim_deb, "%s%s\n", sim_prompt, cptr); + cptr = get_glyph_cmd (cptr, gbuf); /* get command glyph */ + sim_switches = 0; /* init switches */ if (!sim_cptr_is_action[sim_do_depth]) { sim_if_cmd_last[sim_do_depth] = sim_if_cmd[sim_do_depth]; sim_if_result_last[sim_do_depth] = sim_if_result[sim_do_depth]; sim_if_result[sim_do_depth] = sim_if_cmd[sim_do_depth] = FALSE; } - cptr = get_glyph_cmd (cptr, gbuf); /* get command glyph */ - sim_switches = 0; /* init switches */ if ((cmdp = find_cmd (gbuf))) { /* lookup command */ if (do_called && (cmdp->action == &return_cmd)) /* RETURN command? */ break; @@ -3747,7 +3753,7 @@ if (NULL == (c = sim_filepath_parts (cbuf, "f"))) { stat = SCPE_MEM; goto Cleanup_Return; } -strlcpy( sim_do_filename[sim_do_depth], c, +strlcpy( sim_do_filename[sim_do_depth], strcasecmp (cbuf, "") ? c : cbuf, sizeof (sim_do_filename[sim_do_depth])); /* stash away full path of do file name for possible use by 'call' command */ free (c); sim_do_label[sim_do_depth] = label; /* stash away do label for possible use in messages */ @@ -5033,7 +5039,10 @@ long fpos; int32 saved_do_echo = sim_do_echo; int32 saved_goto_line = sim_goto_line[sim_do_depth]; -if (NULL == sim_gotofile) return SCPE_UNK; /* only valid inside of do_cmd */ +if ((NULL == sim_gotofile) || + (0 == strcasecmp (sim_do_filename[sim_do_depth], ""))) + return SCPE_UNK; /* only valid inside of do_cmd */ + get_glyph (fcptr, gbuf1, 0); if ('\0' == gbuf1[0]) /* unspecified goto target */ return sim_messagef (SCPE_ARG, "Missing goto target\n"); @@ -5075,7 +5084,7 @@ return sim_messagef (SCPE_ARG, "goto target '%s' not found\n", gbuf1); t_stat return_cmd (int32 flag, CONST char *fcptr) { -return SCPE_UNK; /* only valid inside of do_cmd */ +return sim_messagef (SCPE_UNK, "Invalid Command\n"); /* only valid inside of do_cmd */ } /* Shift command */ @@ -6329,32 +6338,78 @@ if ((dptr->flags & DEV_DEBUG) || (dptr->debflags)) { else return SCPE_NOFNC; } -/* Show On actions */ +/* Show On actions for one level (default current level) */ t_stat show_on (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) { int32 lvl, i; if (cptr && (*cptr != 0)) return SCPE_2MARG; /* now eol? */ -for (lvl=sim_do_depth; lvl >= 0; --lvl) { +if (flag < 0) + lvl = sim_do_depth; +else + if (flag > sim_do_depth) + return SCPE_ARG; + else + lvl = flag; +if (flag == -1) { 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= 0; --lvl) { + if (lvl > 0) + fprintf(st, "Do Nest Level: %d\n", lvl); + else { + if (sim_do_filename[lvl][0]) + fprintf(st, "Initial Input "); + else + fprintf(st, "Console Input commands\n"); } - fprintf(st, "\n"); + if (sim_do_filename[lvl][0]) { + fprintf (st, "File: %s\n", sim_do_filename[lvl]); + if (strcasecmp (sim_do_filename[lvl], "")) + fprintf (st, "Line: %d\n", sim_goto_line[lvl]); + } + if (sim_if_cmd[lvl]) + fprintf (st, "Processing IF command\n"); + if (sim_if_cmd_last[lvl]) + fprintf (st, "IF command last\n"); + if (sim_if_result[lvl]) + fprintf (st, "IF result\n"); + if (sim_if_result_last[lvl]) + fprintf (st, "IF result last\n"); + if (sim_cptr_is_action[lvl]) + fprintf (st, "Command is Action\n"); + fprintf (st, "Command is: %s\n", sim_do_ocptr[lvl]); + show_on (st, dptr, uptr, lvl, cptr); } if (sim_on_inherit) fprintf(st, "on state and actions are inherited by nested do commands and subroutines\n"); @@ -6950,6 +7005,8 @@ char gbuf[CBUFSIZE]; int32 num; t_stat r; double usec_factor = 1.0; +const char *units = ""; +char runlimit[32]; GET_SWITCHES (cptr); /* get switches */ if (0 == flag) { @@ -6959,6 +7016,8 @@ if (0 == flag) { sim_runlimit_switches = 0; sim_runlimit_enabled = FALSE; sim_cancel (&sim_runlimit_unit); + unsetenv ("SIM_RUNLIMIT"); + unsetenv ("SIM_RUNLIMIT_UNITS"); return SCPE_OK; } @@ -6968,8 +7027,10 @@ if ((r != SCPE_OK) || (num == 0)) /* error? */ return sim_messagef (SCPE_ARG, "Invalid argument: %s\n", gbuf); cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ if ((gbuf[0] == '\0') || - (MATCH_CMD (gbuf, sim_vm_interval_units) == 0)) + (MATCH_CMD (gbuf, sim_vm_interval_units) == 0)) { sim_switches &= ~SWMASK ('T'); + units = sim_vm_interval_units; + } else { int i; struct { @@ -6987,6 +7048,7 @@ else { if (MATCH_CMD (gbuf, time_units[i].name) == 0) { sim_switches |= SWMASK ('T'); usec_factor = time_units[i].usec_factor; + units = time_units[i].name; break; } } @@ -6999,11 +7061,19 @@ sim_runlimit_enabled = TRUE; sim_cancel (&sim_runlimit_unit); sim_runlimit_switches = sim_switches; if (sim_runlimit_switches & SWMASK ('T')) { - sim_runlimit_d_initial = sim_runlimit_d = num * usec_factor; + sim_runlimit_d_initial = sim_runlimit_d = num * usec_factor * sim_host_speed_factor (); + if (sim_host_speed_factor () > 1.0) + sim_messagef (SCPE_OK, "Slow host - adjusting RUNLIMIT from %d %s to %.1f %s\n", num, units, num * sim_host_speed_factor (), units); + snprintf (runlimit, sizeof (runlimit), "%.f", num * sim_host_speed_factor ()); + setenv ("SIM_RUNLIMIT", runlimit, 1); + setenv ("SIM_RUNLIMIT_UNITS", units, 1); return sim_activate_after_d (&sim_runlimit_unit, sim_runlimit_d); } else { sim_runlimit_initial = sim_runlimit = num; + snprintf (runlimit, sizeof (runlimit), "%d", num); + setenv ("SIM_RUNLIMIT", runlimit, 1); + setenv ("SIM_RUNLIMIT_UNITS", units, 1); return sim_activate (&sim_runlimit_unit, sim_runlimit); } } diff --git a/sim_ether.c b/sim_ether.c index 531ac66..58adb23 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -1958,7 +1958,8 @@ return NULL; t_stat eth_set_async (ETH_DEV *dev, int latency) { #if !defined(USE_READER_THREAD) || !defined(SIM_ASYNCH_IO) -char *msg = "Eth: can't operate asynchronously, must poll\n"; +char *msg = "Eth: Can't operate asynchronously, must poll.\n" + " *** Build with USE_READER_THREAD defined and link with pthreads for asynchronous operation. ***\n"; return sim_messagef (SCPE_NOFNC, "%s", msg); #else int wakeup_needed; @@ -2069,13 +2070,14 @@ if (0 == strncmp("tap:", savname, 4)) { } else { *fd_handle = (SOCKET)tun; - strcpy(savname, devname); + memmove(savname, devname, strlen(devname) + 1); } #if defined (__APPLE__) - if (tun < 0) { /* Not good yet? */ + if (tun >= 0) { /* Good so far? */ struct ifreq ifr; int s; + /* Now make sure the interface is up */ memset (&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = AF_INET; strlcpy(ifr.ifr_name, savname, sizeof(ifr.ifr_name)); diff --git a/sim_sock.c b/sim_sock.c index 01b2529..428a19a 100644 --- a/sim_sock.c +++ b/sim_sock.c @@ -917,7 +917,7 @@ if (sta == SOCKET_ERROR) /* bind error? */ if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) { sta = sim_setnonblock (newsock); /* set nonblocking */ if (sta == SOCKET_ERROR) /* fcntl error? */ - return sim_err_sock (newsock, "fcntl"); + return sim_err_sock (newsock, "setnonblock"); } sta = listen (newsock, 1); /* listen on socket */ if (sta == SOCKET_ERROR) /* listen error? */ @@ -989,7 +989,7 @@ if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) { sta = sim_setnonblock (newsock); /* set nonblocking */ if (sta == SOCKET_ERROR) { /* fcntl error? */ p_freeaddrinfo (result); - return sim_err_sock (newsock, "fcntl"); + return sim_err_sock (newsock, "setnonblock"); } } if ((!(opt_flags & SIM_SOCK_OPT_DATAGRAM)) && (opt_flags & SIM_SOCK_OPT_NODELAY)) { @@ -1007,6 +1007,11 @@ if (!(opt_flags & SIM_SOCK_OPT_DATAGRAM)) { if (sta == -1) return sim_err_sock (newsock, "setsockopt KEEPALIVE"); } +if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) { + sta = sim_setnonblock (newsock); /* set nonblocking */ + if (sta == SOCKET_ERROR) /* fcntl error? */ + return sim_err_sock (newsock, "setnonblock"); + } sta = connect (newsock, result->ai_addr, result->ai_addrlen); p_freeaddrinfo (result); if (sta == SOCKET_ERROR) { @@ -1076,7 +1081,7 @@ if (connectaddr != NULL) { if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) { sta = sim_setnonblock (newsock); /* set nonblocking */ if (sta == SOCKET_ERROR) /* fcntl error? */ - return sim_err_sock (newsock, "fcntl"); + return sim_err_sock (newsock, "setnonblock"); } if ((opt_flags & SIM_SOCK_OPT_NODELAY)) { diff --git a/sim_sock.h b/sim_sock.h index 6cf4365..f42e8f1 100644 --- a/sim_sock.h +++ b/sim_sock.h @@ -120,7 +120,7 @@ int sim_parse_addr_ex (const char *cptr, char *host, size_t hostlen, const char SOCKET sim_master_sock_ex (const char *hostport, int *parse_status, int opt_flags); #define sim_master_sock(hostport, parse_status) sim_master_sock_ex(hostport, parse_status, ((sim_switches & SWMASK ('U')) ? SIM_SOCK_OPT_REUSEADDR : 0)) SOCKET sim_connect_sock_ex (const char *sourcehostport, const char *hostport, const char *default_host, const char *default_port, int opt_flags); -#define sim_connect_sock(hostport, default_host, default_port) sim_connect_sock_ex(NULL, hostport, default_host, default_port, 0) +#define sim_connect_sock(hostport, default_host, default_port) sim_connect_sock_ex(NULL, hostport, default_host, default_port, SIM_SOCK_OPT_BLOCKING) SOCKET sim_accept_conn_ex (SOCKET master, char **connectaddr, int opt_flags); #define sim_accept_conn(master, connectaddr) sim_accept_conn_ex(master, connectaddr, 0) int sim_check_conn (SOCKET sock, int rd); diff --git a/sim_timer.c b/sim_timer.c index 6ff3191..8dd4cf0 100644 --- a/sim_timer.c +++ b/sim_timer.c @@ -3467,3 +3467,11 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { sim_inst_per_sec_last = sim_precalibrate_ips; sim_idle_stable = 0; } + +double +sim_host_speed_factor (void) +{ +if (sim_precalibrate_ips > SIM_INITIAL_IPS) + return 1.0; +return (double)SIM_INITIAL_IPS / (double)sim_precalibrate_ips; +} diff --git a/sim_timer.h b/sim_timer.h index 5ea2591..cf53771 100644 --- a/sim_timer.h +++ b/sim_timer.h @@ -158,6 +158,7 @@ t_stat sim_os_set_thread_priority (int below_normal_above); uint32 sim_get_rom_delay_factor (void); void sim_set_rom_delay_factor (uint32 delay); int32 sim_rom_read_with_delay (int32 val); +double sim_host_speed_factor (void); extern t_bool sim_idle_enab; /* idle enabled flag */ extern volatile t_bool sim_idle_wait; /* idle waiting flag */ diff --git a/sim_tmxr.c b/sim_tmxr.c index 710cf14..2c3796b 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -1284,7 +1284,9 @@ for (i = 0; i < mp->lines; i++) { /* check each line in se (!lp->modem_control || (lp->modembits & TMXR_MDM_DTR))) { snprintf (msg, sizeof (msg) - 1, "tmxr_poll_conn() - establishing outgoing connection to: %s", lp->destination); tmxr_debug_connect_line (lp, msg); - lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (lp->mp->packet ? SIM_SOCK_OPT_NODELAY : 0)); + lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | + (lp->mp->packet ? SIM_SOCK_OPT_NODELAY : 0) | + SIM_SOCK_OPT_BLOCKING); } } @@ -1354,7 +1356,9 @@ if ((lp->destination) && (!lp->serport)) { if ((!lp->modem_control) || (lp->modembits & TMXR_MDM_DTR)) { sprintf (msg, "tmxr_reset_ln_ex() - connecting to %s", lp->destination); tmxr_debug_connect_line (lp, msg); - lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (lp->packet ? SIM_SOCK_OPT_NODELAY : 0)); + lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | + (lp->packet ? SIM_SOCK_OPT_NODELAY : 0) | + SIM_SOCK_OPT_BLOCKING); } } tmxr_init_line (lp); /* initialize line state */ @@ -1644,7 +1648,9 @@ if (lp->mp && lp->modem_control) { /* This API ONLY works on mo sprintf (msg, "tmxr_set_get_modem_bits() - establishing outgoing connection to: %s", lp->destination); tmxr_debug_connect_line (lp, msg); - lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (lp->packet ? SIM_SOCK_OPT_NODELAY : 0)); + lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | + (lp->packet ? SIM_SOCK_OPT_NODELAY : 0) | + SIM_SOCK_OPT_BLOCKING); } } } @@ -2799,7 +2805,9 @@ while (*tptr) { else return sim_messagef (SCPE_ARG, "Unexpected specifier: %s\n", eptr); } - sock = sim_connect_sock_ex (NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (packet ? SIM_SOCK_OPT_NODELAY : 0)); + sock = sim_connect_sock_ex (NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | + (packet ? SIM_SOCK_OPT_NODELAY : 0) | + SIM_SOCK_OPT_BLOCKING); if (sock != INVALID_SOCKET) sim_close_sock (sock); else @@ -2951,7 +2959,9 @@ while (*tptr) { return sim_messagef (SCPE_ARG, "Missing listen port for Datagram socket\n"); } lp->packet = packet; - sock = sim_connect_sock_ex (datagram ? listen : NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (packet ? SIM_SOCK_OPT_NODELAY : 0)); + sock = sim_connect_sock_ex (datagram ? listen : NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | + (packet ? SIM_SOCK_OPT_NODELAY : 0) | + SIM_SOCK_OPT_BLOCKING); if (sock != INVALID_SOCKET) { _mux_detach_line (lp, FALSE, TRUE); lp->destination = (char *)malloc(1+strlen(hostport)); @@ -3066,7 +3076,9 @@ while (*tptr) { else return sim_messagef (SCPE_ARG, "Missing listen port for Datagram socket\n"); } - sock = sim_connect_sock_ex (datagram ? listen : NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (packet ? SIM_SOCK_OPT_NODELAY : 0)); + sock = sim_connect_sock_ex (datagram ? listen : NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | + (packet ? SIM_SOCK_OPT_NODELAY : 0) | + SIM_SOCK_OPT_BLOCKING); if (sock != INVALID_SOCKET) { _mux_detach_line (lp, FALSE, TRUE); lp->destination = (char *)malloc(1+strlen(hostport));