1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-03-27 10:20:52 +00:00

SCP Updated to current version.

This commit is contained in:
Richard Cornwell
2018-06-17 20:01:44 -04:00
parent c41caeb4d0
commit e88dfb3868
9 changed files with 382 additions and 179 deletions

313
scp.c
View File

@@ -519,7 +519,6 @@ t_stat do_cmd_label (int32 flag, CONST char *cptr, CONST char *label);
void int_handler (int signal);
t_stat set_prompt (int32 flag, CONST char *cptr);
t_stat sim_set_asynch (int32 flag, CONST char *cptr);
t_stat sim_set_environment (int32 flag, CONST char *cptr);
static const char *get_dbg_verb (uint32 dbits, DEVICE* dptr, UNIT *uptr);
/* Global data */
@@ -582,7 +581,7 @@ static int32 sim_show_message = 1; /* the message display s
static int32 sim_on_inherit = 0; /* the inherit status of on state and conditions when executing do files */
static int32 sim_do_depth = 0;
static t_bool sim_cmd_echoed = FALSE; /* Command was emitted already prior to message output */
static char **sim_exp_argv = NULL;
static int32 sim_on_check[MAX_DO_NEST_LVL+1];
static char *sim_on_actions[MAX_DO_NEST_LVL+1][SCPE_MAX_ERR+2];
#define ON_SIGINT_ACTION (SCPE_MAX_ERR+1)
@@ -603,8 +602,34 @@ static DEBTAB sim_dflt_debug[] = {
{0}
};
static UNIT sim_step_unit = { UDATA (&step_svc, 0, 0) };
static UNIT sim_expect_unit = { UDATA (&expect_svc, 0, 0) };
static const char *sim_int_step_description (DEVICE *dptr)
{
return "Step/Next facility";
}
static UNIT sim_step_unit = { UDATA (&step_svc, 0, 0) };
DEVICE sim_step_dev = {
"INT-STEP", &sim_step_unit, NULL, NULL,
1, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, DEV_NOSAVE, 0,
NULL, NULL, NULL, NULL, NULL, NULL,
sim_int_step_description};
static const char *sim_int_expect_description (DEVICE *dptr)
{
return "Expect facility";
}
static UNIT sim_expect_unit = { UDATA (&expect_svc, 0, 0) };
DEVICE sim_expect_dev = {
"INT-EXPECT", &sim_expect_unit, NULL, NULL,
1, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, DEV_NOSAVE, 0,
NULL, NULL, NULL, NULL, NULL, NULL,
sim_int_expect_description};
#if defined USE_INT64
static const char *sim_si64 = "64b data";
#else
@@ -2389,6 +2414,8 @@ sim_log = NULL;
if (sim_emax <= 0)
sim_emax = 1;
sim_timer_init ();
sim_register_internal_device (&sim_expect_dev);
sim_register_internal_device (&sim_step_dev);
if ((stat = sim_ttinit ()) != SCPE_OK) {
fprintf (stderr, "Fatal terminal initialization error\n%s\n",
@@ -2507,8 +2534,10 @@ 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? */
printf ("%s%s\n", sim_prompt, cptr); /* echo */
if ((cptr = sim_brk_getact (cbuf, sizeof(cbuf)))) { /* pending action? */
if (sim_do_echo)
printf ("%s+ %s\n", sim_prompt, cptr); /* echo */
}
else {
if (sim_vm_read != NULL) { /* sim routine? */
printf ("%s", sim_prompt); /* prompt */
@@ -3347,6 +3376,7 @@ if (flag >= 0) { /* Only bump nesting fro
}
}
sim_debug (SIM_DBG_DO, sim_dflt_dev, "do_cmd_label(%d, flag=%d, '%s', '%s')\n", sim_do_depth, flag, fcptr, label ? label : "");
strlcpy( sim_do_filename[sim_do_depth], do_arg[0],
sizeof (sim_do_filename[sim_do_depth])); /* stash away do file name for possible use by 'call' command */
sim_do_label[sim_do_depth] = label; /* stash away do label for possible use in messages */
@@ -3379,11 +3409,13 @@ do {
sim_do_ocptr[sim_do_depth] = cptr = read_line (cbuf, sizeof(cbuf), fpin);/* get cmd line */
sim_goto_line[sim_do_depth] += 1;
}
sim_sub_args (cbuf, sizeof(cbuf), do_arg); /* substitute args */
if (cptr == NULL) { /* EOF? */
stat = SCPE_OK; /* set good return */
break;
}
sim_debug (SIM_DBG_DO, sim_dflt_dev, "Input Command: %s\n", cbuf);
sim_sub_args (cbuf, sizeof(cbuf), do_arg); /* substitute args */
sim_debug (SIM_DBG_DO, sim_dflt_dev, "Expanded Command: %s\n", cbuf);
if (*cptr == 0) /* ignore blank */
continue;
if (echo) /* echo if -v */
@@ -3412,6 +3444,7 @@ do {
}
else
stat = SCPE_UNK; /* bad cmd given */
sim_debug (SIM_DBG_DO, sim_dflt_dev, "Command '%s', Result: 0x%X - %s\n", cmdp ? cmdp->name : "", stat, sim_error_text (stat));
echo = sim_do_echo; /* Allow for SET VERIFY */
stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */
stat_nomessage = stat_nomessage || (!sim_show_message);/* Apply global suppression */
@@ -3483,9 +3516,11 @@ if ((flag >= 0) || (!sim_on_inherit)) {
}
sim_on_check[sim_do_depth] = 0; /* clear on mode */
}
if (flag >= 0)
sim_debug (SIM_DBG_DO, sim_dflt_dev, "do_cmd_label - exiting - stat:%d (%d, flag=%d, '%s', '%s')\n", stat, sim_do_depth, flag, fcptr, label ? label : "");
if (flag >= 0) {
sim_brk_clract (); /* defang breakpoint actions */
--sim_do_depth; /* unwind nesting */
sim_brk_clract (); /* defang breakpoint actions */
}
if (cmdp && (cmdp->action == &return_cmd) && (0 != *cptr)) { /* return command with argument? */
sim_string_to_stat (cptr, &stat);
sim_last_cmd_stat = stat; /* save explicit status as command error status */
@@ -3540,7 +3575,7 @@ return stat | SCPE_NOMESSAGE; /* suppress message sinc
*/
static const char *
_sim_get_env_special (const char *gbuf, char *rbuf, size_t rbuf_size)
_sim_gen_env_uplowcase (const char *gbuf, char *rbuf, size_t rbuf_size)
{
const char *ap;
char tbuf[CBUFSIZE];
@@ -3548,11 +3583,23 @@ char tbuf[CBUFSIZE];
ap = getenv(gbuf); /* first try using the literal name */
if (!ap) {
get_glyph (gbuf, tbuf, 0); /* now try using the upcased name */
ap = getenv(tbuf);
if (strcmp (gbuf, tbuf)) /* upcase different? */
ap = getenv(tbuf); /* lookup the upcase name */
}
if (ap) /* environment variable found? */
if (ap) { /* environment variable found? */
strlcpy (rbuf, ap, rbuf_size); /* Return the environment value */
else { /* otherwise, check for Special Names */
ap = rbuf;
}
return ap;
}
static const char *
_sim_get_env_special (const char *gbuf, char *rbuf, size_t rbuf_size)
{
const char *ap;
ap = _sim_gen_env_uplowcase (gbuf, rbuf, rbuf_size);/* Look for environment variable */
if (!ap) { /* no environment variable found? */
time_t now = (time_t)cmd_time.tv_sec;
struct tm *tmnow = localtime(&now);
@@ -3718,6 +3765,22 @@ else { /* otherwise, check for Special Names */
return ap;
}
/* Substitute_args - replace %n tokens in 'instr' with the do command's arguments
Calling sequence
instr = input string
tmpbuf = temp buffer
maxstr = min (len (instr), len (tmpbuf))
do_arg[10] = arguments
Token "%0" represents the command file name.
The input sequence "\%" represents a literal "%", and "\\" represents a
literal "\". All other character combinations are rendered literally.
Omitted parameters result in null-string substitutions.
*/
void sim_sub_args (char *instr, size_t instr_size, char *do_arg[])
{
char gbuf[CBUFSIZE];
@@ -3728,6 +3791,7 @@ int i;
size_t instr_off = 0;
size_t outstr_off = 0;
sim_exp_argv = do_arg;
clock_gettime(CLOCK_REALTIME, &cmd_time);
tmpbuf = (char *)malloc(instr_size);
op = tmpbuf;
@@ -6377,6 +6441,8 @@ for (i = 0; i < start; i++) {
return SCPE_IERR;
}
for (i = start; (dptr = sim_devices[i]) != NULL; i++) {
if (sim_switches & SWMASK('P'))
tmxr_add_debug (dptr); /* Add TMXR debug to MUX devices */
if (dptr->reset != NULL) {
reason = dptr->reset (dptr);
if (reason != SCPE_OK)
@@ -6399,9 +6465,50 @@ static DEBTAB scp_debug[] = {
{"QUEUE", SIM_DBG_AIO_QUEUE, "asynch event queue activities"},
{"EXPSTACK", SIM_DBG_EXP_STACK, "expression stack activities"},
{"EXPEVAL", SIM_DBG_EXP_EVAL, "expression evaluation activities"},
{"ACTION", SIM_DBG_BRK_ACTION, "action activities"},
{"DO", SIM_DBG_DO, "do activities"},
{0}
};
t_stat sim_add_debug_flags (DEVICE *dptr, DEBTAB *debflags)
{
dptr->flags |= DEV_DEBUG;
if (!dptr->debflags)
dptr->debflags = debflags;
else {
DEBTAB *cdptr, *sdptr, *ndptr;
for (sdptr = debflags; sdptr->name; sdptr++) {
for (cdptr = dptr->debflags; cdptr->name; cdptr++) {
if (sdptr->mask == cdptr->mask)
break;
}
if (sdptr->mask != cdptr->mask) {
int i, dcount = 0;
for (cdptr = dptr->debflags; cdptr->name; cdptr++)
dcount++;
for (cdptr = debflags; cdptr->name; cdptr++)
dcount++;
ndptr = (DEBTAB *)calloc (1 + dcount, sizeof (*ndptr));
for (dcount = 0, cdptr = dptr->debflags; cdptr->name; cdptr++)
ndptr[dcount++] = *cdptr;
for (cdptr = debflags; cdptr->name; cdptr++) {
for (i = 0; i < dcount; i++) {
if (cdptr->mask == ndptr[i].mask)
break;
}
if (i == dcount)
ndptr[dcount++] = *cdptr;
}
dptr->debflags = ndptr;
break;
}
}
}
return SCPE_OK;
}
/* Reset to powerup state
Inputs:
@@ -6418,42 +6525,8 @@ int32 old_sw = sim_switches;
sim_switches = SWMASK ('P');
r = reset_all (start);
sim_switches = old_sw;
if (sim_dflt_dev) { /* Make sure that SCP debug options are available */
sim_dflt_dev->flags |= DEV_DEBUG;
if (!sim_dflt_dev->debflags)
sim_dflt_dev->debflags = scp_debug;
else {
DEBTAB *cdptr, *sdptr, *ndptr;
for (sdptr = scp_debug; sdptr->name; sdptr++) {
for (cdptr = sim_dflt_dev->debflags; cdptr->name; cdptr++) {
if (sdptr->mask == cdptr->mask)
break;
}
if (sdptr->mask != cdptr->mask) {
int i, dcount = 0;
for (cdptr = sim_dflt_dev->debflags; cdptr->name; cdptr++)
dcount++;
for (cdptr = scp_debug; cdptr->name; cdptr++)
dcount++;
ndptr = (DEBTAB *)calloc (1 + dcount, sizeof (*ndptr));
for (dcount = 0, cdptr =sim_dflt_dev->debflags; cdptr->name; cdptr++)
ndptr[dcount++] = *cdptr;
for (cdptr = scp_debug; cdptr->name; cdptr++) {
for (i = 0; i < dcount; i++) {
if (cdptr->mask == ndptr[i].mask)
break;
}
if (i == dcount)
ndptr[dcount++] = *cdptr;
}
sim_dflt_dev->debflags = ndptr;
break;
}
}
}
}
if (sim_dflt_dev) /* Make sure that SCP debug options are available */
sim_add_debug_flags (sim_dflt_dev, scp_debug);
return r;
}
@@ -7828,6 +7901,7 @@ t_stat exdep_cmd (int32 flag, CONST char *cptr)
char gbuf[CBUFSIZE];
CONST char *gptr;
CONST char *tptr = NULL;
const char *ap;
int32 opt;
t_addr low, high;
t_stat reason;
@@ -7900,6 +7974,10 @@ for (gptr = gbuf, reason = SCPE_OK;
continue;
}
if ((ap = getenv (gptr))) {
strlcpy (gbuf, ap, sizeof (gbuf));
gptr = gbuf;
}
tptr = get_range (sim_dfdev, gptr, &low, &high, sim_dfdev->aradix,
(((sim_dfunit->capac == 0) || (flag == EX_E))? 0:
sim_dfunit->capac - sim_dfdev->aincr), 0);
@@ -9326,12 +9404,12 @@ t_stat sim_register_internal_device (DEVICE *dptr)
{
uint32 i;
for (i = 0; (sim_devices[i] != NULL); i++)
if (sim_devices[i] == dptr)
return SCPE_OK;
for (i = 0; i < sim_internal_device_count; i++)
if (sim_internal_devices[i] == dptr)
return SCPE_OK;
for (i = 0; (sim_devices[i] != NULL); i++)
if (sim_devices[i] == dptr)
return SCPE_OK;
++sim_internal_device_count;
sim_internal_devices = (DEVICE **)realloc(sim_internal_devices, (sim_internal_device_count+1)*sizeof(*sim_internal_devices));
sim_internal_devices[sim_internal_device_count-1] = dptr;
@@ -10339,14 +10417,18 @@ do {
uptr->next = NULL; /* hygiene */
uptr->time = 0;
if (sim_clock_queue != QUEUE_LIST_END)
sim_interval = sim_clock_queue->time;
sim_interval += sim_clock_queue->time;
else
sim_interval = noqueue_time = NOQUEUE_WAIT;
sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Processing Event for %s\n", sim_uname (uptr));
AIO_EVENT_BEGIN(uptr);
if (uptr->usecs_remaining)
if (uptr->usecs_remaining) {
sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Requeueing %s after %.0f usecs\n", sim_uname (uptr), uptr->usecs_remaining);
reason = sim_timer_activate_after (uptr, uptr->usecs_remaining);
}
else {
sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Processing Event for %s\n", sim_uname (uptr));
if (uptr->uname && ((*uptr->uname == '\0') || (*uptr->uname == ' ')))
reason = SCPE_OK; /* do nothing breakpoint location */
if (uptr->action != NULL)
reason = uptr->action (uptr);
else
@@ -10530,10 +10612,10 @@ AIO_CANCEL(uptr);
AIO_UPDATE_QUEUE;
if (sim_clock_queue == QUEUE_LIST_END)
return SCPE_OK;
sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Canceling Event for %s\n", sim_uname(uptr));
UPDATE_SIM_TIME; /* update sim time */
if (!sim_is_active (uptr))
return SCPE_OK;
sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Canceling Event for %s\n", sim_uname(uptr));
nptr = QUEUE_LIST_END;
if (sim_clock_queue == uptr) {
@@ -11108,9 +11190,11 @@ if (ep != NULL) { /* if a semicolon is pre
}
else {
strlcpy (buf, sim_brk_act[sim_do_depth], size); /* copy action */
sim_brk_act[sim_do_depth] = NULL; /* mark as digested */
sim_brk_clract (); /* no more */
}
sim_trim_endspc (buf);
sim_debug (SIM_DBG_BRK_ACTION, sim_dflt_dev, "sim_brk_getact(%d) - Returning: '%s'\n", sim_do_depth, buf);
return buf;
}
@@ -11118,6 +11202,8 @@ return buf;
char *sim_brk_clract (void)
{
if (sim_brk_act[sim_do_depth])
sim_debug (SIM_DBG_BRK_ACTION, sim_dflt_dev, "sim_brk_clract(%d) - Clearing: '%s'\n", sim_do_depth, sim_brk_act[sim_do_depth]);
free (sim_brk_act_buf[sim_do_depth]);
return sim_brk_act[sim_do_depth] = sim_brk_act_buf[sim_do_depth] = NULL;
}
@@ -11127,8 +11213,25 @@ return sim_brk_act[sim_do_depth] = sim_brk_act_buf[sim_do_depth] = NULL;
void sim_brk_setact (const char *action)
{
if (action) {
sim_brk_act_buf[sim_do_depth] = (char *)realloc (sim_brk_act_buf[sim_do_depth], strlen (action) + 1);
strcpy (sim_brk_act_buf[sim_do_depth], action);
if (sim_brk_act[sim_do_depth] && (*sim_brk_act[sim_do_depth])) {
/* push new actions ahead of whatever is already pending */
size_t old_size = strlen (sim_brk_act[sim_do_depth]);
size_t new_size = strlen (action) + old_size + 3;
char *old_action = (char *)malloc (1 + old_size);
strlcpy (old_action, sim_brk_act[sim_do_depth], 1 + old_size);
sim_brk_act_buf[sim_do_depth] = (char *)realloc (sim_brk_act_buf[sim_do_depth], new_size);
strlcpy (sim_brk_act_buf[sim_do_depth], action, new_size);
strlcat (sim_brk_act_buf[sim_do_depth], "; ", new_size);
strlcat (sim_brk_act_buf[sim_do_depth], old_action, new_size);
sim_debug (SIM_DBG_BRK_ACTION, sim_dflt_dev, "sim_brk_setact(%d) - Pushed: '%s' ahead of: '%s'\n", sim_do_depth, action, old_action);
free (old_action);
}
else {
sim_brk_act_buf[sim_do_depth] = (char *)realloc (sim_brk_act_buf[sim_do_depth], strlen (action) + 1);
strcpy (sim_brk_act_buf[sim_do_depth], action);
sim_debug (SIM_DBG_BRK_ACTION, sim_dflt_dev, "sim_brk_setact(%d) - Set to: '%s'\n", sim_do_depth, action);
}
sim_brk_act[sim_do_depth] = sim_brk_act_buf[sim_do_depth];
}
else
@@ -11721,6 +11824,9 @@ if (i != exp->size) { /* Found? */
ep->cnt, (ep->cnt == 1) ? "" : "es");
}
else {
uint32 after = ep->after;
int32 switches = ep->switches;
if (ep->act && *ep->act) {
sim_debug (exp->dbit, exp->dptr, "Initiating actions: %s\n", ep->act);
}
@@ -11735,9 +11841,9 @@ if (i != exp->size) { /* Found? */
sim_exp_clr_tab (exp, ep); /* delete it */
}
sim_activate (&sim_expect_unit, /* schedule simulation stop when indicated */
(ep->switches & EXP_TYP_TIME) ?
(int32)((sim_timer_inst_per_sec ()*ep->after)/1000000.0) :
ep->after);
(switches & EXP_TYP_TIME) ?
(int32)((sim_timer_inst_per_sec ()*after)/1000000.0) :
after);
}
/* Matched data is no longer available for future matching */
exp->buf_data = exp->buf_ins = 0;
@@ -13505,17 +13611,17 @@ return !data;
static t_svalue _op_log_and (t_svalue data1, t_svalue data2)
{
return data1 && data2;
return data2 && data1;
}
static t_svalue _op_log_or (t_svalue data1, t_svalue data2)
{
return data1 || data2;
return data2 || data1;
}
static t_svalue _op_bit_and (t_svalue data1, t_svalue data2)
{
return data1 & data2;
return data2 & data1;
}
static t_svalue _op_bit_rsh (t_svalue shift, t_svalue data)
@@ -13530,72 +13636,77 @@ return data << shift;
static t_svalue _op_bit_or (t_svalue data1, t_svalue data2)
{
return data1 | data2;
return data2 | data1;
}
static t_svalue _op_bit_xor (t_svalue data1, t_svalue data2)
{
return data1 ^ data2;
return data2 ^ data1;
}
static t_svalue _op_eq (t_svalue data1, t_svalue data2)
{
return data1 == data2;
return data2 == data1;
}
static t_svalue _op_ne (t_svalue data1, t_svalue data2)
{
return data1 != data2;
return data2 != data1;
}
static t_svalue _op_le (t_svalue data1, t_svalue data2)
{
return data1 <= data2;
return data2 <= data1;
}
static t_svalue _op_lt (t_svalue data1, t_svalue data2)
{
return data1 < data2;
return data2 < data1;
}
static t_svalue _op_ge (t_svalue data1, t_svalue data2)
{
return data1 >= data2;
return data2 >= data1;
}
static t_svalue _op_gt (t_svalue data1, t_svalue data2)
{
return data1 > data2;
return data2 > data1;
}
static int _i_strcmp (const char *s1, const char *s2)
{
return ((sim_switches & SWMASK('I')) ? strcasecmp (s2, s1) : strcmp (s2, s1));
}
static t_svalue _op_str_eq (const char *str1, const char *str2)
{
return (0 == strcmp (str1, str2));
return (0 == _i_strcmp (str2, str1));
}
static t_svalue _op_str_ne (const char *str1, const char *str2)
{
return (0 != strcmp (str1, str2));
return (0 != _i_strcmp (str2, str1));
}
static t_svalue _op_str_le (const char *str1, const char *str2)
{
return (0 > strcmp (str1, str2));
return (0 <= _i_strcmp (str2, str1));
}
static t_svalue _op_str_lt (const char *str1, const char *str2)
{
return (0 >= strcmp (str1, str2));
return (0 < _i_strcmp (str2, str1));
}
static t_svalue _op_str_ge (const char *str1, const char *str2)
{
return (0 < strcmp (str1, str2));
return (0 >= _i_strcmp (str2, str1));
}
static t_svalue _op_str_gt (const char *str1, const char *str2)
{
return (0 <= strcmp (str1, str2));
return (0 > _i_strcmp (str2, str1));
}
/*
@@ -13644,7 +13755,7 @@ static const char BinaryDigits[] = "01";
*oper = NULL;
while (isspace (*cptr))
++cptr;
if (isalpha (*cptr)) {
if (isalpha (*cptr) || (*cptr == '_')) {
while (isalnum (*cptr) || (*cptr == '.') || (*cptr == '_'))
*buf++ = *cptr++;
*buf = '\0';
@@ -13656,7 +13767,7 @@ else {
memcpy (buf, cptr, 2);
cptr += 2;
buf += 2;
while (strchr (HexDigits, *cptr))
while (*cptr && strchr (HexDigits, *cptr))
*buf++ = *cptr++;
*buf = '\0';
}
@@ -13666,13 +13777,13 @@ else {
memcpy (buf, cptr, 2);
cptr += 2;
buf += 2;
while (strchr (BinaryDigits, *cptr))
while (*cptr && strchr (BinaryDigits, *cptr))
*buf++ = *cptr++;
*buf = '\0';
}
else {
if (*cptr == '0') { /* Octal Number */
while (strchr (OctalDigits, *cptr))
while (*cptr && strchr (OctalDigits, *cptr))
*buf++ = *cptr++;
*buf = '\0';
}
@@ -13820,8 +13931,9 @@ return cptr; /* return any unprocessed input */
static t_bool _value_of (const char *data, t_svalue *svalue, char *string, size_t string_size)
{
CONST char *gptr;
size_t data_size = strlen (data);
if (isalpha (*data)) {
if (isalpha (*data) || (*data == '_')) {
REG *rptr = NULL;
DEVICE *dptr = sim_dfdev;
const char *dot;
@@ -13842,30 +13954,38 @@ if (isalpha (*data)) {
rptr = find_reg_glob (data, &gptr, &dptr);
if (rptr) {
*svalue = (t_svalue)get_rval (rptr, 0);
sprint_val (string + 1, *svalue, 10, string_size - 2, PV_LEFTSIGN);
*string = '"';
strlcpy (&string[strlen (string)], "\"", string_size - strlen (string));
sprint_val (string, *svalue, 10, string_size - 1, PV_LEFTSIGN);
return TRUE;
}
gptr = _sim_get_env_special (data, string + 1, string_size - 2);
gptr = _sim_get_env_special (data, string, string_size - 1);
if (gptr) {
*svalue = strtotsv(string + 1, &gptr, 0);
*string = '"';
strlcpy (&string[strlen (string)], "\"", string_size - strlen (string));
return (*gptr == '\0');
*svalue = strtotsv(string, &gptr, 0);
return ((*gptr == '\0') && (*string));
}
else
else {
data = "";
data_size = 0;
}
}
*svalue = strtotsv(data, &gptr, 0);
snprintf (string, string_size - 1, "\"%s\"", data);
return (*gptr == '\0');
string[0] = '\0';
if ((data[0] == '\'') && (data_size > 1) && (data[data_size - 1] == '\''))
snprintf (string, string_size - 1, "\"%*.*s\"", (int)(data_size - 2), (int)(data_size - 2), data + 1);
if ((data[0] == '"') && (data_size > 1) && (data[data_size - 1] == '"'))
strlcpy (string, data, string_size);
if (string[0] == '\0') {
*svalue = strtotsv(data, &gptr, 0);
return ((*gptr == '\0') && (*data));
}
sim_sub_args (string, string_size, sim_exp_argv);
*svalue = strtotsv(string, &gptr, 0);
return ((*gptr == '\0') && (*string));
}
/*
* Evaluate a given stack1 containing a postfix expression
*/
static t_svalue sim_eval_postfix (Stack *stack1, t_stat *stat) {
static t_svalue sim_eval_postfix (Stack *stack1, t_stat *stat)
{
Stack *stack2 = new_Stack(); /* local working stack2 which is holds the numbers operators */
char temp_data[CBUFSIZE]; /* Holds the items popped from the stack2 */
Operator *temp_op;
@@ -13942,6 +14062,7 @@ const char *sim_eval_expression (const char *cptr, t_svalue *value, t_bool paren
const char *iptr = cptr;
Stack *postfix = new_Stack (); /* for the postfix expression */
sim_debug (SIM_DBG_EXP_EVAL, sim_dflt_dev, "[Evaluate Expression: %s\n", cptr);
*value = 0;
cptr = sim_into_postfix (postfix, cptr, stat, parens_required);
if (*stat != SCPE_OK) {

2
scp.h
View File

@@ -246,6 +246,7 @@ CONST char *get_glyph_cmd (const char *iptr, char *optr);
t_value get_uint (const char *cptr, uint32 radix, t_value max, t_stat *status);
CONST char *get_range (DEVICE *dptr, CONST char *cptr, t_addr *lo, t_addr *hi,
uint32 rdx, t_addr max, char term);
t_stat sim_set_environment (int32 flag, CONST char *cptr);
t_stat sim_decode_quoted_string (const char *iptr, uint8 *optr, uint32 *osize);
char *sim_encode_quoted_string (const uint8 *iptr, uint32 size);
void fprint_buffer_string (FILE *st, const uint8 *buf, uint32 size);
@@ -304,6 +305,7 @@ CONST char *match_ext (CONST char *fnam, const char *ext);
t_stat show_version (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr);
t_stat set_dev_debug (DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr);
t_stat show_dev_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr);
t_stat sim_add_debug_flags (DEVICE *dptr, DEBTAB *debflags);
const char *sim_error_text (t_stat stat);
t_stat sim_string_to_stat (const char *cptr, t_stat *cond);
t_stat sim_cancel_step (void);

View File

@@ -2155,8 +2155,8 @@ t_stat sim_show_cons_speed (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONS
{
if (sim_con_ldsc.rxbps) {
fprintf (st, "Speed = %d", sim_con_ldsc.rxbps);
if (sim_con_ldsc.bpsfactor != TMXR_BPS_UNIT_SCALE)
fprintf (st, "*%.0f", sim_con_ldsc.bpsfactor / TMXR_BPS_UNIT_SCALE);
if (sim_con_ldsc.bpsfactor != 1.0)
fprintf (st, "*%.0f", sim_con_ldsc.bpsfactor);
fprintf (st, " bps\n");
}
return SCPE_OK;
@@ -2799,7 +2799,7 @@ if (!sim_rem_master_mode) {
(sim_con_ldsc.serport == 0)) { /* and not serial? */
if (c && sim_con_ldsc.rxbps) /* got something && rate limiting? */
sim_con_ldsc.rxnexttime = /* compute next input time */
floor (sim_gtime () + ((sim_con_ldsc.rxdelta * sim_timer_inst_per_sec ()) / sim_con_ldsc.bpsfactor));
floor (sim_gtime () + ((sim_con_ldsc.rxdeltausecs * sim_timer_inst_per_sec ()) / USECS_PER_SECOND));
if (c)
sim_debug (DBG_RCV, &sim_con_telnet, "sim_poll_kbd() returning: '%c' (0x%02X)\n", sim_isprint (c & 0xFF) ? c & 0xFF : '.', c);
return c; /* in-window */

View File

@@ -851,6 +851,8 @@ struct DEBTAB {
#define SIM_DBG_AIO_QUEUE 0x040000 /* asynch event queue activities */
#define SIM_DBG_EXP_STACK 0x080000 /* expression stack activities */
#define SIM_DBG_EXP_EVAL 0x100000 /* expression evaluation activities */
#define SIM_DBG_BRK_ACTION 0x200000 /* action activities */
#define SIM_DBG_DO 0x400000 /* do activities */
/* Open File Reference */
struct FILEREF {

View File

@@ -458,6 +458,16 @@ if (shmem->hMapping != INVALID_HANDLE_VALUE)
free (shmem);
}
int32 sim_shmem_atomic_add (int32 *p, int32 v)
{
return InterlockedExchangeAdd ((volatile long *) p,v) + (v);
}
t_bool sim_shmem_atomic_cas (int32 *ptr, int32 oldv, int32 newv)
{
return (InterlockedCompareExchange ((LONG volatile *) ptr, newv, oldv) == oldv);
}
#else /* !defined(_WIN32) */
#include <unistd.h>
int sim_set_fsize (FILE *fptr, t_addr size)
@@ -537,6 +547,7 @@ if ((stbuf.st_mode & S_IFIFO)) {
return -1;
}
#if defined (__linux__) || defined (__APPLE__)
#include <sys/mman.h>
struct SHMEM {
@@ -604,7 +615,52 @@ if (shmem->shm_fd != -1)
free (shmem);
}
int32 sim_shmem_atomic_add (int32 *p, int32 v)
{
#if defined (HAVE_GCC_SYNC_BUILTINS)
return __sync_add_and_fetch((int *) p, v);
#else
return *p + v;
#endif
}
t_bool sim_shmem_atomic_cas (int32 *ptr, int32 oldv, int32 newv)
{
#if defined (HAVE_GCC_SYNC_BUILTINS)
return __sync_bool_compare_and_swap (ptr, oldv, newv);
#else
if (*ptr == oldv) {
*ptr = newv;
return 1;
}
else
return 0;
#endif
}
#else /* !(defined (__linux__) || defined (__APPLE__)) */
t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr)
{
return SCPE_NOFNC;
}
void sim_shmem_close (SHMEM *shmem)
{
}
int32 sim_shmem_atomic_add (int32 *p, int32 v)
{
return -1;
}
t_bool sim_shmem_atomic_cas (int32 *ptr, int32 oldv, int32 newv)
{
return FALSE;
}
#endif /* defined (__linux__) || defined (__APPLE__) */
#endif /* defined (_WIN32) */
#if defined(__VAX)
/*

View File

@@ -76,6 +76,8 @@ const char *sim_get_os_error_text (int error);
typedef struct SHMEM SHMEM;
t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr);
void sim_shmem_close (SHMEM *shmem);
int32 sim_shmem_atomic_add (int32 *ptr, int32 val);
t_bool sim_shmem_atomic_cas (int32 *ptr, int32 oldv, int32 newv);
extern t_bool sim_taddr_64; /* t_addr is > 32b and Large File Support available */
extern t_bool sim_toffset_64; /* Large File (>2GB) file I/O support */

View File

@@ -1037,6 +1037,7 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
sim_stop_unit.action = &sim_timer_stop_svc;
SIM_INTERNAL_UNIT.flags = UNIT_IDLE;
sim_register_internal_device (&sim_timer_dev); /* Register Clock Assist device */
sim_register_internal_device (&sim_throttle_dev); /* Register Throttle Device */
sim_throttle_unit.action = &sim_throt_svc;
sim_register_clock_unit_tmr (&SIM_INTERNAL_UNIT, SIM_INTERNAL_CLK);
sim_idle_enab = FALSE; /* init idle off */
@@ -1477,6 +1478,7 @@ t_bool sim_idle (uint32 tmr, int sin_cyc)
{
uint32 w_ms, w_idle, act_ms;
int32 act_cyc;
static t_bool in_nowait = FALSE;
if (rtc_clock_catchup_pending[tmr]) { /* Catchup clock tick pending? */
sim_debug (DBG_CAL, &sim_timer_dev, "sim_idle(tmr=%d, sin_cyc=%d) - accelerating pending catch-up tick before idling %s\n", tmr, sin_cyc, sim_uname (sim_clock_unit[tmr]));
@@ -1545,9 +1547,12 @@ else
w_idle = (w_ms * 1000) / sim_idle_rate_ms; /* 1000 * intervals to wait */
if (w_idle < 500) { /* shorter than 1/2 the interval? */
sim_interval -= sin_cyc;
sim_debug (DBG_IDL, &sim_timer_dev, "no wait\n");
if (!in_nowait)
sim_debug (DBG_IDL, &sim_timer_dev, "no wait, too short: %d usecs\n", w_idle);
in_nowait = TRUE;
return FALSE;
}
in_nowait = FALSE;
if (sim_clock_queue == QUEUE_LIST_END)
sim_debug (DBG_IDL, &sim_timer_dev, "sleeping for %d ms - pending event in %d instructions\n", w_ms, sim_interval);
else
@@ -1556,10 +1561,7 @@ act_ms = sim_idle_ms_sleep (w_ms); /* wait */
rtc_clock_time_idled[tmr] += act_ms;
act_cyc = act_ms * sim_idle_cyc_ms;
act_cyc += (sim_idle_cyc_ms * sim_idle_rate_ms) / 2; /* account for half an interval's worth of cycles */
if (sim_interval > act_cyc)
sim_interval = sim_interval - act_cyc; /* count down sim_interval */
else
sim_interval = 0; /* or fire immediately */
sim_interval = sim_interval - act_cyc; /* count down sim_interval to reflect idle period */
if (sim_clock_queue == QUEUE_LIST_END)
sim_debug (DBG_IDL, &sim_timer_dev, "slept for %d ms - pending event in %d instructions\n", act_ms, sim_interval);
else
@@ -1670,7 +1672,6 @@ else {
sim_throt_wait = sim_throt_val;
}
}
sim_register_internal_device (&sim_throttle_dev); /* Register Throttle Device */
if (sim_throt_type == SIM_THROT_SPC) /* Set initial value while correct one is determined */
sim_throt_cps = (int32)((1000.0 * sim_throt_val) / (double)sim_throt_sleep_time);
else
@@ -1974,7 +1975,7 @@ if ((stat == SCPE_OK) &&
if (fabs(skew) > fabs(rtc_clock_skew_max[tmr]))
rtc_clock_skew_max[tmr] = skew;
}
/* First gather the queued events that are scheduled for now */
/* Gather any queued events which are scheduled for right now */
do {
cptr = sim_clock_cosched_queue[tmr];
sim_clock_cosched_queue[tmr] = cptr->next;
@@ -1996,11 +1997,11 @@ if ((stat == SCPE_OK) &&
cptr->cancel = NULL;
cptr->time = 0;
if (cptr->usecs_remaining) {
sim_debug (DBG_QUE, &sim_timer_dev, " remnant: %.0f - next %s after cosched interval: %d ticks\n", cptr->usecs_remaining, (sptr != QUEUE_LIST_END) ? sim_uname (sptr) : "", sim_cosched_interval[tmr]);
sim_debug (DBG_QUE, &sim_timer_dev, "Rescheduling %s after %.0f usecs %s%s\n", sim_uname (cptr), cptr->usecs_remaining, (sptr != QUEUE_LIST_END) ? "- next: " : "", (sptr != QUEUE_LIST_END) ? sim_uname (sptr) : "");
sim_timer_activate_after (cptr, cptr->usecs_remaining);
}
else {
sim_debug (DBG_QUE, &sim_timer_dev, " - next %s after cosched interval: %d ticks\n", (sptr != QUEUE_LIST_END) ? sim_uname (sptr) : "", sim_cosched_interval[tmr]);
sim_debug (DBG_QUE, &sim_timer_dev, "Activating %s now %s%s\n", sim_uname (cptr), (sptr != QUEUE_LIST_END) ? "- next: " : "", (sptr != QUEUE_LIST_END) ? sim_uname (sptr) : "");
_sim_activate (cptr, 0);
}
}
@@ -2399,19 +2400,20 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
_sim_activate (sim_clock_unit[tmr], clock_time);
}
/* Move coscheduled units to the standard event queue */
accum = 0;
/* scheduled to fire at the same time as the related */
/* clock unit is to fire with excess time reflected in */
/* the unit usecs_remaining value */
accum = sim_cosched_interval[tmr];
while (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) {
UNIT *cptr = sim_clock_cosched_queue[tmr];
double usecs_remaining = cptr->usecs_remaining;
cptr->usecs_remaining = 0;
sim_clock_cosched_queue[tmr] = cptr->next;
cptr->next = NULL;
cptr->cancel = NULL;
accum += cptr->time;
sim_debug (DBG_QUE, &sim_timer_dev, "sim_stop_timer_services() - tmr=%d scheduling %s after %d\n", tmr, sim_uname (cptr), clock_time + accum*rtc_currd[tmr]);
_sim_activate (cptr, clock_time + accum*rtc_currd[tmr]);
cptr->usecs_remaining = usecs_remaining;
_sim_activate (cptr, clock_time);
cptr->usecs_remaining = cptr->usecs_remaining + floor(1000000.0 * (accum - ((accum > 0) ? 1 : 0)) * rtc_clock_tick_size[tmr]);
sim_debug (DBG_QUE, &sim_timer_dev, "sim_stop_timer_services() - tmr=%d scheduling %s after %d and %.0f usecs\n", tmr, sim_uname (cptr), clock_time, cptr->usecs_remaining);
}
sim_cosched_interval[tmr] = 0;
}
@@ -2501,12 +2503,13 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++)
}
if (sim_is_active (uptr)) /* already active? */
return SCPE_OK;
uptr->usecs_remaining = 0;
if (usec_delay <= 0.0) {
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - invalid usec value\n",
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - invalid usec value\n",
sim_uname(uptr), usec_delay);
uptr->usecs_remaining = 0.0;
return SCPE_ARG;
}
uptr->usecs_remaining = 0.0;
/*
* Handle long delays by aligning with the calibrated timer's calibration
* activities. Delays which would expire prior to the next calibration
@@ -2528,19 +2531,20 @@ if ((sim_calb_tmr != -1) && (rtc_hz[sim_calb_tmr])) { /* Calibrated Timer
int32 inst_til_calib = inst_til_tick + ((ticks_til_calib - 1) * rtc_currd[sim_calb_tmr]);
uint32 usecs_til_calib = (uint32)ceil(inst_til_calib / inst_per_usec);
if (uptr != &sim_timer_units[sim_calb_tmr]) { /* Not scheduling calibrated timer? */
if ((uptr != &sim_timer_units[sim_calb_tmr]) && /* Not scheduling calibrated timer */
(inst_til_tick > 0)) { /* and tick not pending? */
if (inst_delay_d > (double)inst_til_calib) { /* long wait? */
stat = sim_clock_coschedule_tmr (uptr, sim_calb_tmr, ticks_til_calib - 1);
uptr->usecs_remaining = (stat == SCPE_OK) ? usec_delay - usecs_til_calib : 0.0;
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - coscheduling with with calibrated timer(%d), ticks=%d, usecs_remaining=%.0f usecs, inst_til_tick=%d\n",
sim_uname(uptr), usec_delay, sim_calb_tmr, ticks_til_calib, uptr->usecs_remaining, inst_til_tick);
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - coscheduling with with calibrated timer(%d), ticks=%d, usecs_remaining=%.0f usecs, inst_til_tick=%d, ticks_til_calib=%d\n",
sim_uname(uptr), usec_delay, sim_calb_tmr, ticks_til_calib, uptr->usecs_remaining, inst_til_tick, ticks_til_calib);
sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n",
sim_uname(uptr), usec_delay, sim_timer_activate_time_usecs (ouptr), sim_timer_activate_time_usecs (uptr));
return stat;
}
if ((usec_delay > usecs_per_tick) &&
(ticks_til_calib > 1)) { /* long wait? */
double usecs_til_tick = inst_til_tick / inst_per_usec;
double usecs_til_tick = floor (inst_til_tick / inst_per_usec);
stat = sim_clock_coschedule_tmr (uptr, sim_calb_tmr, 0);
uptr->usecs_remaining = (stat == SCPE_OK) ? usec_delay - usecs_til_tick : 0.0;
@@ -2617,9 +2621,6 @@ if ((sim_asynch_timer) &&
}
#endif
stat = _sim_activate (uptr, inst_delay); /* queue it now */
uptr->usecs_remaining = ((stat == SCPE_OK) && (0.0 < (usec_delay - ceil(inst_delay / inst_per_usec) ))) ?
usec_delay - floor(inst_delay / inst_per_usec) :
0.0;
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - queue addition at %d - remnant: %.0f\n",
sim_uname(uptr), usec_delay, inst_delay, uptr->usecs_remaining);
sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n",
@@ -3018,7 +3019,7 @@ if (uptr->cancel == &_sim_coschedule_cancel) {
accum += cptr->time;
if (cptr == uptr) {
result = uptr->usecs_remaining + ceil(1000000.0 * ((rtc_currd[tmr] * accum) + sim_activate_time (&sim_timer_units[tmr]) - 1) / sim_timer_inst_per_sec ());
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) coscheduled - %.0f usecs, inst_per_sec=%.0f, tmr=%d, ticksize=%d, ticks=%d, inst_til_tick=%d\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), tmr, rtc_currd[tmr], accum, sim_activate_time (&sim_timer_units[tmr]) - 1);
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) coscheduled - %.0f usecs, inst_per_sec=%.0f, tmr=%d, ticksize=%d, ticks=%d, inst_til_tick=%d, usecs_remaining=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), tmr, rtc_currd[tmr], accum, sim_activate_time (&sim_timer_units[tmr]) - 1, uptr->usecs_remaining);
return result;
}
}
@@ -3027,17 +3028,17 @@ if (uptr->cancel == &_sim_coschedule_cancel) {
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
if ((uptr == sim_clock_unit[tmr]) && (uptr->next)) {
result = sim_clock_unit[tmr]->usecs_remaining + (1000000.0 * (sim_activate_time (&sim_timer_units[tmr]) - 1)) / sim_timer_inst_per_sec ();
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ());
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f, usecs_remaining=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), uptr->usecs_remaining);
return result;
}
if ((uptr == &sim_timer_units[tmr]) && (uptr->next)){
result = uptr->usecs_remaining + (1000000.0 * (sim_activate_time (uptr) - 1)) / sim_timer_inst_per_sec ();
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ());
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f, usecs_remaining=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), uptr->usecs_remaining);
return result;
}
}
result = uptr->usecs_remaining + (1000000.0 * (sim_activate_time (uptr) - 1)) / sim_timer_inst_per_sec ();
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ());
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f, usecs_remaining=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), uptr->usecs_remaining);
return result; /* Not found. */
}

View File

@@ -474,7 +474,7 @@ if (!lp->txbfd || lp->notelnet) /* if not buffered telne
lp->txbpr = lp->txbpi = lp->txcnt = lp->txpcnt = 0; /* init transmit indexes */
lp->txdrp = lp->txstall = 0;
tmxr_set_get_modem_bits (lp, 0, 0, NULL);
if ((!lp->mp->buffered) && (!lp->txbfd)) {
if (lp->mp && (!lp->mp->buffered) && (!lp->txbfd)) {
lp->txbfd = 0;
lp->txbsz = TMXR_MAXBUF;
lp->txb = (char *)realloc (lp->txb, lp->txbsz);
@@ -735,7 +735,7 @@ else {
}
}
if ((written > 0) && (lp->txbps) && (sim_is_running))
lp->txnexttime = floor (sim_gtime () + ((written * lp->txdelta * sim_timer_inst_per_sec ()) / lp->bpsfactor));
lp->txnexttime = floor (sim_gtime () + ((written * lp->txdeltausecs * sim_timer_inst_per_sec ()) / USECS_PER_SECOND));
return written;
}
@@ -1784,9 +1784,9 @@ if (lp->rxbpi == lp->rxbpr) /* empty? zero ptrs */
lp->rxbpi = lp->rxbpr = 0;
if (val) { /* Got something? */
if (lp->rxbps)
lp->rxnexttime = floor (sim_gtime () + ((lp->rxdelta * sim_timer_inst_per_sec ()) / lp->bpsfactor));
lp->rxnexttime = floor (sim_gtime () + ((lp->rxdeltausecs * sim_timer_inst_per_sec ()) / USECS_PER_SECOND));
else
lp->rxnexttime = floor (sim_gtime () + ((lp->mp->uptr->wait * sim_timer_inst_per_sec ()) / TMXR_BPS_UNIT_SCALE));
lp->rxnexttime = floor (sim_gtime () + ((lp->mp->uptr->wait * sim_timer_inst_per_sec ()) / USECS_PER_SECOND));
}
tmxr_debug_return(lp, val);
return val;
@@ -2173,8 +2173,8 @@ if ((lp->txbfd && !lp->notelnet) || (TXBUF_AVAIL(lp) > 1)) {/* room for char (+
sim_exp_check (&lp->expect, chr); /* process expect rules as needed */
if (!sim_is_running) { /* attach message or other non simulation time message? */
tmxr_send_buffered_data (lp); /* put data on wire */
sim_os_ms_sleep(((lp->txbps) && (lp->txdelta > 1000)) ? /* rate limiting output slower than 1000 cps */
(lp->txdelta - 1000) / 1000 :
sim_os_ms_sleep(((lp->txbps) && (lp->txdeltausecs > 1000)) ? /* rate limiting output slower than 1000 cps */
(lp->txdeltausecs - 1000) / 1000 :
10); /* wait an approximate character delay */
}
return SCPE_OK; /* char sent */
@@ -2267,10 +2267,8 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */
#endif
if ((lp->xmte == 0) &&
((lp->txbps == 0) ||
(lp->txnexttime <= sim_gtime ()))) {
(lp->txnexttime <= sim_gtime ())))
lp->xmte = 1; /* enable line transmit */
lp->txnexttime = 0.0;
}
}
} /* end for */
}
@@ -2479,24 +2477,21 @@ if (*cptr == '*') {
if (r != SCPE_OK)
return r;
lp->bpsfactor = TMXR_BPS_UNIT_SCALE * bpsfactor;
lp->bpsfactor = bpsfactor;
}
if ((lp->serport) && (lp->bpsfactor != 0.0))
lp->bpsfactor = TMXR_BPS_UNIT_SCALE;
lp->rxdelta = _tmln_speed_delta (speed);
lp->bpsfactor = 1.0;
lp->rxdeltausecs = (uint32)(_tmln_speed_delta (speed) / lp->bpsfactor);
lp->rxnexttime = 0.0;
uptr = lp->uptr;
if ((!uptr) && (lp->mp))
uptr = lp->mp->uptr;
if (uptr)
uptr->wait = lp->rxdelta;
if (lp->bpsfactor == 0.0)
lp->bpsfactor = TMXR_BPS_UNIT_SCALE;
uptr->wait = lp->rxdeltausecs;
lp->txbps = lp->rxbps;
lp->txdelta = lp->rxdelta;
lp->txnexttime = lp->rxnexttime;
lp->txdeltausecs = lp->rxdeltausecs;
if (lp->o_uptr)
lp->o_uptr->wait = lp->txdelta;
lp->o_uptr->wait = lp->txdeltausecs;
return SCPE_OK;
}
@@ -2534,7 +2529,7 @@ for (i = 0; i < mp->lines; i++) { /* initialize lines */
lp->mp = mp; /* set the back pointer */
lp->modem_control = mp->modem_control;
if (lp->bpsfactor == 0.0)
lp->bpsfactor = TMXR_BPS_UNIT_SCALE;
lp->bpsfactor = 1.0;
}
mp->ring_sock = INVALID_SOCKET;
free (mp->ring_ipad);
@@ -2658,7 +2653,9 @@ while (*tptr) {
if ((NULL == cptr) || ('\0' == *cptr) ||
(_tmln_speed_delta (cptr) < 0))
return sim_messagef (SCPE_ARG, "Invalid Speed Specifier: %s\n", (cptr ? cptr : ""));
if (mp->port_speed_control && (_tmln_speed_delta (cptr) > 0) && (!(sim_switches & SIM_SW_REST)))
if (mp->port_speed_control &&
((_tmln_speed_delta (cptr) > 0) || (*cptr != '*')) &&
(!(sim_switches & SIM_SW_REST)))
return sim_messagef (SCPE_ARG, "%s simulator programmatically sets %sport speed\n", sim_name, dev_name);
strlcpy (speed, cptr, sizeof(speed));
continue;
@@ -3802,6 +3799,27 @@ else
return SCPE_OK;
}
static DEBTAB tmxr_debug[] = {
{"XMT", TMXR_DBG_XMT, "Transmit Data"},
{"RCV", TMXR_DBG_RCV, "Received Data"},
{"RET", TMXR_DBG_RET, "Returned Received Data"},
{"MODEM", TMXR_DBG_MDM, "Modem Signals"},
{"CONNECT", TMXR_DBG_CON, "Connection Activities"},
{"ASYNC", TMXR_DBG_ASY, "Asynchronous Activities"},
{"TRACE", TMXR_DBG_TRC, "trace routine calls"},
{"XMTPKT", TMXR_DBG_PXMT, "Transmit Packet Data"},
{"RCVPKT", TMXR_DBG_PRCV, "Received Packet Data"},
{"EXPECT", TMXR_DBG_EXP, "Expect Activities"},
{"SEND", TMXR_DBG_SEND, "Send Activities"},
{0}
};
t_stat tmxr_add_debug (DEVICE *dptr)
{
if (!(dptr->flags & DEV_MUX))
return SCPE_OK;
return sim_add_debug_flags (dptr, tmxr_debug);
}
/* Attach unit to master socket */
@@ -3917,8 +3935,8 @@ else {
if (mp->lines == 1) {
if (mp->ldsc->rxbps) {
fprintf(st, ", Speed=%d", mp->ldsc->rxbps);
if (mp->ldsc->bpsfactor != TMXR_BPS_UNIT_SCALE)
fprintf(st, "*%.0f", mp->ldsc->bpsfactor / TMXR_BPS_UNIT_SCALE);
if (mp->ldsc->bpsfactor != 1.0)
fprintf(st, "*%.0f", mp->ldsc->bpsfactor);
fprintf(st, " bps");
}
}
@@ -3946,13 +3964,13 @@ else {
fprintf(st, ", Loopback");
if (lp->rxbps) {
fprintf(st, ", Speed=%d", lp->rxbps);
if (lp->bpsfactor != TMXR_BPS_UNIT_SCALE)
fprintf(st, "*%.0f", lp->bpsfactor / TMXR_BPS_UNIT_SCALE);
if (lp->bpsfactor != 1.0)
fprintf(st, "*%.0f", lp->bpsfactor);
fprintf(st, " bps");
}
else {
if (lp->bpsfactor != TMXR_BPS_UNIT_SCALE)
fprintf(st, ", Speed=*%.0f bps", lp->bpsfactor / TMXR_BPS_UNIT_SCALE);
if (lp->bpsfactor != 1.0)
fprintf(st, ", Speed=*%.0f bps", lp->bpsfactor);
}
fprintf (st, "\n");
}
@@ -4084,20 +4102,20 @@ for (i=0; i<mp->lines; i++) {
if (lp->rxnexttime > sim_gtime_now)
due = (int32)(lp->rxnexttime - sim_gtime_now);
else
due = sim_processing_event ? 1 : 0; /* avoid potential infinite loop if called from service routine */
due = sim_processing_event ? 1 : 0; /* avoid potential infinite loop if called from service routine */
sooner = MIN(sooner, due);
}
if ((uptr == lp->o_uptr) && /* output completion unit? */
(lp->txbps) && /* while rate limiting */
(lp->txnexttime)) { /* with queued output data */
if ((lp->conn) && /* Connected? */
(uptr == lp->o_uptr) && /* output completion unit? */
(lp->txbps)) { /* while rate limiting */
if ((tmxr_tqln(lp)) && /* pending output data? */
(lp->txnexttime < sim_gtime_now))
tmxr_send_buffered_data (lp);/* flush it */
if (lp->txnexttime > sim_gtime_now)
due = (int32)(lp->txnexttime - sim_gtime_now);
else
due = sim_processing_event ? 1 : 0; /* avoid potential infinite loop if called from service routine */
if (i == 0)
sooner = due;
else
sooner = MIN(sooner, due);
due = sim_processing_event ? 1 : 0; /* avoid potential infinite loop if called from service routine */
sooner = MIN(sooner, due);
}
}
return sooner;
@@ -4113,18 +4131,18 @@ if (!(uptr->dynflags & UNIT_TM_POLL))
return _sim_activate (uptr, interval); /* Handle the non mux case */
sooner = _tmxr_activate_delay (uptr, interval);
if (sooner != interval) {
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %d instructions rather than %d instructions\n", sim_uname (uptr), sooner, interval);
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate() - scheduling %s after %d instructions rather than %d instructions\n", sim_uname (uptr), sooner, interval);
return _sim_activate (uptr, sooner); /* Handle the busy case */
}
#if defined(SIM_ASYNCH_MUX)
if (!sim_asynch_enabled) {
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %d instructions\n", sim_uname (uptr), interval);
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate() - scheduling %s after %d instructions\n", sim_uname (uptr), interval);
return _sim_activate (uptr, interval);
}
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s asynchronously instead of %d instructions\n", sim_uname (uptr), interval);
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate() - scheduling %s asynchronously instead of %d instructions\n", sim_uname (uptr), interval);
return SCPE_OK;
#else
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %d instructions\n", sim_uname (uptr), interval);
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate() - scheduling %s after %d instructions\n", sim_uname (uptr), interval);
return _sim_activate (uptr, interval);
#endif
}
@@ -4147,21 +4165,21 @@ if (!(uptr->dynflags & UNIT_TM_POLL))
sooner = _tmxr_activate_delay (uptr, 0x7FFFFFFF);
if (sooner != 0x7FFFFFFF) {
if (sooner < 0) {
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s for %u usecs produced overflow interval %d instructions, sceduling for %d instructions\n", sim_uname (uptr), usecs_walltime, sooner, 0x7FFFFFFF);
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s for %u usecs produced overflow interval %d instructions, sceduling for %d instructions\n", sim_uname (uptr), usecs_walltime, sooner, 0x7FFFFFFF);
sooner = _tmxr_activate_delay (uptr, 0x7FFFFFFF); /* Breakpoint here on unexpected value */
}
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %d instructions rather than %u usecs\n", sim_uname (uptr), sooner, usecs_walltime);
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s after %d instructions rather than %u usecs\n", sim_uname (uptr), sooner, usecs_walltime);
return _sim_activate (uptr, sooner); /* Handle the busy case directly */
}
#if defined(SIM_ASYNCH_MUX)
if (!sim_asynch_enabled) {
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %u usecs\n", sim_uname (uptr), usecs_walltime);
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s after %u usecs\n", sim_uname (uptr), usecs_walltime);
return _sim_activate_after (uptr, (double)usecs_walltime);
}
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s asynchronously instead of %u usecs\n", sim_uname (uptr), usecs_walltime);
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s asynchronously instead of %u usecs\n", sim_uname (uptr), usecs_walltime);
return SCPE_OK;
#else
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %u usecs\n", sim_uname (uptr), usecs_walltime);
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s after %.0f usecs\n", sim_uname (uptr), (double)usecs_walltime);
return _sim_activate_after (uptr, (double)usecs_walltime);
#endif
}
@@ -4197,17 +4215,17 @@ if (!(uptr->dynflags & UNIT_TM_POLL))
return sim_clock_coschedule_tmr (uptr, tmr, ticks); /* Handle the non mux case */
sooner = _tmxr_activate_delay (uptr, interval);
if (sooner != interval) {
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %d instructions rather than %d ticks (%d instructions)\n", sim_uname (uptr), sooner, ticks, interval);
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_clock_coschedule_tmr(tmr=%d) - scheduling %s after %d instructions rather than %d ticks (%d instructions)\n", tmr, sim_uname (uptr), sooner, ticks, interval);
return _sim_activate (uptr, sooner); /* Handle the busy case directly */
}
#if defined(SIM_ASYNCH_MUX)
if (!sim_asynch_enabled) {
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "coscheduling %s after interval %d ticks\n", sim_uname (uptr), ticks);
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_clock_coschedule_tmr(tmr=%d) - coscheduling %s after interval %d ticks\n", tmr, sim_uname (uptr), ticks);
return sim_clock_coschedule (uptr, tmr, ticks);
}
return SCPE_OK;
#else
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "coscheduling %s after interval %d ticks\n", sim_uname (uptr), ticks);
sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_clock_coschedule_tmr(tmr=%d) - coscheduling %s after interval %d ticks\n", tmr, sim_uname (uptr), ticks);
return sim_clock_coschedule_tmr (uptr, tmr, ticks);
#endif
}
@@ -4653,8 +4671,8 @@ else {
fprintf (st, " speed = %u", lp->rxbps);
else
fprintf (st, " speed = %u/%u", lp->rxbps, lp->txbps);
if (lp->bpsfactor / TMXR_BPS_UNIT_SCALE > 1.0)
fprintf (st, "*%.0f", lp->bpsfactor / TMXR_BPS_UNIT_SCALE);
if (lp->bpsfactor > 1.0)
fprintf (st, "*%.0f", lp->bpsfactor);
fprintf (st, " bps\n");
}
}

View File

@@ -170,11 +170,11 @@ struct tmln {
uint32 rxpboffset; /* rcv packet buffer offset */
uint32 rxbps; /* rcv bps speed (0 - unlimited) */
double bpsfactor; /* receive speed factor (scaled to usecs) */
#define TMXR_BPS_UNIT_SCALE 1000000.0
uint32 rxdelta; /* rcv inter character min time (usecs) */
#define USECS_PER_SECOND 1000000.0
uint32 rxdeltausecs; /* rcv inter character min time (usecs) */
double rxnexttime; /* min time for next receive character */
uint32 txbps; /* xmt bps speed (0 - unlimited) */
uint32 txdelta; /* xmt inter character min time (usecs) */
uint32 txdeltausecs; /* xmt inter character min time (usecs) */
double txnexttime; /* min time for next transmit character */
uint8 *txpb; /* xmt packet buffer */
uint32 txpbsize; /* xmt packet buffer size */
@@ -309,6 +309,7 @@ void _tmxr_debug (uint32 dbits, TMLN *lp, const char *msg, char *buf, int bufsiz
#define tmxr_debug_trace_line(lp, msg) do {if (sim_deb && (lp)->mp && (lp)->mp->dptr && (TMXR_DBG_TRC & (lp)->mp->dptr->dctrl)) sim_debug (TMXR_DBG_TRC, (lp)->mp->dptr, "Ln%d:%s\n", (int)((lp)-(lp)->mp->ldsc), (msg)); } while (0)
#define tmxr_debug_connect(mp, msg) do {if (sim_deb && (mp)->dptr && (TMXR_DBG_CON & (mp)->dptr->dctrl)) sim_debug (TMXR_DBG_CON, mp->dptr, "%s\n", (msg)); } while (0)
#define tmxr_debug_connect_line(lp, msg) do {if (sim_deb && (lp)->mp && (lp)->mp->dptr && (TMXR_DBG_CON & (lp)->mp->dptr->dctrl)) sim_debug (TMXR_DBG_CON, (lp)->mp->dptr, "Ln%d:%s\n", (int)((lp)-(lp)->mp->ldsc), (msg)); } while (0)
t_stat tmxr_add_debug (DEVICE *dptr);
#if defined(SIM_ASYNCH_MUX) && !defined(SIM_ASYNCH_IO)
#undef SIM_ASYNCH_MUX