Merge branch 'BufferedConsole' into simhv3.8-2.rc2

Conflicts:
	scp.c
	sim_console.c
	sim_tmxr.c
This commit is contained in:
Mark Pizzolato 2011-04-15 09:22:37 -07:00
commit 87157dc737
6 changed files with 483 additions and 124 deletions

4
scp.c
View file

@ -395,10 +395,10 @@ static uint32 sim_rtime;
static int32 noqueue_time; static int32 noqueue_time;
volatile int32 stop_cpu = 0; volatile int32 stop_cpu = 0;
t_value *sim_eval = NULL; t_value *sim_eval = NULL;
int32 sim_deb_close = 0; /* 1 = close debug */
FILE *sim_log = NULL; /* log file */ FILE *sim_log = NULL; /* log file */
FILEREF *sim_log_ref = NULL; /* log file file reference */
FILE *sim_deb = NULL; /* debug file */ FILE *sim_deb = NULL; /* debug file */
FILEREF *sim_deb_ref = NULL; /* debug file file reference */
static FILE *sim_gotofile; static FILE *sim_gotofile;
static int32 sim_do_depth = 0; static int32 sim_do_depth = 0;

View file

@ -23,7 +23,27 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
20-Jan-11 MP Added support for BREAK key on Windows 20-Jan-11 MP Fixed support for BREAK key on Windows to account
for/ignore other keyboard Meta characters.
18-Jan-11 MP Added log file reference count support
17-Jan-11 MP Added support for a "Buffered" behaviors which include:
- If Buffering is enabled and Telnet is enabled, a
telnet connection is not required for simulator
operation (instruction execution).
- If Buffering is enabled, all console output is
written to the buffer at all times (deleting the
oldest buffer contents on overflow).
- when a connection is established on the console
telnet port, the whole contents of the Buffer is
presented on the telnet session and connection
will then proceed as if the connection had always
been there.
This concept allows a simulator to run in the background
and when needed a console session to be established.
The "when needed" case usually will be interested in
what already happened before looking to address what
to do, hence the buffer contents being presented.
28-Dec-10 MP Added support for BREAK key on Windows
30-Sep-06 RMS Fixed non-printable characters in KSR mode 30-Sep-06 RMS Fixed non-printable characters in KSR mode
22-Jun-06 RMS Implemented SET/SHOW PCHAR 22-Jun-06 RMS Implemented SET/SHOW PCHAR
31-May-06 JDB Fixed bug if SET CONSOLE DEBUG with no argument 31-May-06 JDB Fixed bug if SET CONSOLE DEBUG with no argument
@ -63,6 +83,12 @@
sim_putchar_s - output character to console, stall if congested sim_putchar_s - output character to console, stall if congested
sim_set_console - set console parameters sim_set_console - set console parameters
sim_show_console - show console parameters sim_show_console - show console parameters
sim_set_cons_buff - set console buffered
sim_set_cons_unbuff -set console unbuffered
sim_set_cons_log - set console log
sim_set_cons_nolog - set console nolog
sim_show_cons_buff - show console buffered
sim_show_cons_log - show console log
sim_tt_inpcvt - convert input character per mode sim_tt_inpcvt - convert input character per mode
sim_tt_outcvt - convert output character per mode sim_tt_outcvt - convert output character per mode
@ -105,8 +131,9 @@ TMLN sim_con_ldsc = { 0 }; /* console line descr */
TMXR sim_con_tmxr = { 1, 0, 0, &sim_con_ldsc }; /* console line mux */ TMXR sim_con_tmxr = { 1, 0, 0, &sim_con_ldsc }; /* console line mux */
extern volatile int32 stop_cpu; extern volatile int32 stop_cpu;
extern int32 sim_quiet, sim_deb_close; extern int32 sim_quiet;
extern FILE *sim_log, *sim_deb; extern FILE *sim_log, *sim_deb;
extern FILEREF *sim_log_ref, *sim_deb_ref;
extern DEVICE *sim_devices[]; extern DEVICE *sim_devices[];
/* Set/show data structures */ /* Set/show data structures */
@ -130,9 +157,19 @@ static SHTAB show_con_tab[] = {
{ "BRK", &sim_show_kmap, KMAP_BRK }, { "BRK", &sim_show_kmap, KMAP_BRK },
{ "DEL", &sim_show_kmap, KMAP_DEL }, { "DEL", &sim_show_kmap, KMAP_DEL },
{ "PCHAR", &sim_show_pchar, 0 }, { "PCHAR", &sim_show_pchar, 0 },
{ "LOG", &sim_show_log, 0 }, { "LOG", &sim_show_cons_log, 0 },
{ "TELNET", &sim_show_telnet, 0 }, { "TELNET", &sim_show_telnet, 0 },
{ "DEBUG", &sim_show_debug, 0 }, { "DEBUG", &sim_show_debug, 0 },
{ "BUFFERED", &sim_show_cons_buff, 0 },
{ NULL, NULL, 0 }
};
static CTAB set_con_telnet_tab[] = {
{ "LOG", &sim_set_cons_log, 0 },
{ "NOLOG", &sim_set_cons_nolog, 0 },
{ "BUFFERED", &sim_set_cons_buff, 0 },
{ "NOBUFFERED", &sim_set_cons_unbuff, 0 },
{ "UNBUFFERED", &sim_set_cons_unbuff, 0 },
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };
@ -262,6 +299,7 @@ return SCPE_OK;
t_stat sim_set_logon (int32 flag, char *cptr) t_stat sim_set_logon (int32 flag, char *cptr)
{ {
char gbuf[CBUFSIZE]; char gbuf[CBUFSIZE];
t_stat r;
if ((cptr == NULL) || (*cptr == 0)) /* need arg */ if ((cptr == NULL) || (*cptr == 0)) /* need arg */
return SCPE_2FARG; return SCPE_2FARG;
@ -269,12 +307,14 @@ cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */
if (*cptr != 0) /* now eol? */ if (*cptr != 0) /* now eol? */
return SCPE_2MARG; return SCPE_2MARG;
sim_set_logoff (0, NULL); /* close cur log */ sim_set_logoff (0, NULL); /* close cur log */
sim_log = sim_fopen (gbuf, "a"); /* open log */ r = sim_open_logfile (gbuf, FALSE, &sim_log, &sim_log_ref); /* open log */
if (sim_log == NULL) /* error? */ if (r != SCPE_OK) /* error? */
return SCPE_OPENERR; return r;
if (!sim_quiet) if (!sim_quiet)
printf ("Logging to file \"%s\"\n", gbuf); printf ("Logging to file \"%s\"\n",
fprintf (sim_log, "Logging to file \"%s\"\n", gbuf); /* start of log */ sim_logfile_name (sim_log, sim_log_ref));
fprintf (sim_log, "Logging to file \"%s\"\n",
sim_logfile_name (sim_log, sim_log_ref)); /* start of log */
return SCPE_OK; return SCPE_OK;
} }
@ -288,8 +328,8 @@ if (sim_log == NULL) /* no log? */
return SCPE_OK; return SCPE_OK;
if (!sim_quiet) if (!sim_quiet)
printf ("Log file closed\n"); printf ("Log file closed\n");
fprintf (sim_log, "Log file closed\n"); /* close log */ fprintf (sim_log, "Log file closed\n");
fclose (sim_log); sim_close_logfile (&sim_log_ref); /* close log */
sim_log = NULL; sim_log = NULL;
return SCPE_OK; return SCPE_OK;
} }
@ -301,8 +341,8 @@ t_stat sim_show_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
if (cptr && (*cptr != 0)) if (cptr && (*cptr != 0))
return SCPE_2MARG; return SCPE_2MARG;
if (sim_log) if (sim_log)
fputs ("Logging enabled\n", st); fprintf (st, "Logging enabled to %s\n", sim_logfile_name (sim_log, sim_log_ref));
else fputs ("Logging disabled\n", st); else fprintf (st, "Logging disabled\n");
return SCPE_OK; return SCPE_OK;
} }
@ -310,34 +350,24 @@ return SCPE_OK;
t_stat sim_set_debon (int32 flag, char *cptr) t_stat sim_set_debon (int32 flag, char *cptr)
{ {
char *tptr, gbuf[CBUFSIZE]; char gbuf[CBUFSIZE];
t_stat r;
if ((cptr == NULL) || (*cptr == 0)) /* too few arguments? */ if ((cptr == NULL) || (*cptr == 0)) /* need arg */
return SCPE_2FARG; return SCPE_2FARG;
tptr = get_glyph (cptr, gbuf, 0); /* get file name */ cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */
if (*tptr != 0) /* now eol? */ if (*cptr != 0) /* now eol? */
return SCPE_2MARG; return SCPE_2MARG;
sim_set_deboff (0, NULL); /* close cur debug */ r = sim_open_logfile (gbuf, FALSE, &sim_deb, &sim_deb_ref);
if (strcmp (gbuf, "LOG") == 0) { /* debug to log? */
if (sim_log == NULL) /* any log? */ if (r != SCPE_OK)
return SCPE_ARG; return r;
sim_deb = sim_log;
}
else if (strcmp (gbuf, "STDOUT") == 0) /* debug to stdout? */
sim_deb = stdout;
else if (strcmp (gbuf, "STDERR") == 0) /* debug to stderr? */
sim_deb = stderr;
else {
cptr = get_glyph_nc (cptr, gbuf, 0); /* reparse */
sim_deb = sim_fopen (gbuf, "a"); /* open debug */
if (sim_deb == NULL) /* error? */
return SCPE_OPENERR;
sim_deb_close = 1; /* need close */
}
if (!sim_quiet) if (!sim_quiet)
printf ("Debug output to \"%s\"\n", gbuf); printf ("Debug output to \"%s\"\n",
sim_logfile_name (sim_deb, sim_deb_ref));
if (sim_log) if (sim_log)
fprintf (sim_log, "Debug output to \"%s\"\n", gbuf); fprintf (sim_log, "Debug output to \"%s\"\n",
sim_logfile_name (sim_deb, sim_deb_ref));
return SCPE_OK; return SCPE_OK;
} }
@ -345,18 +375,18 @@ return SCPE_OK;
t_stat sim_set_deboff (int32 flag, char *cptr) t_stat sim_set_deboff (int32 flag, char *cptr)
{ {
t_stat r;
if (cptr && (*cptr != 0)) /* now eol? */ if (cptr && (*cptr != 0)) /* now eol? */
return SCPE_2MARG; return SCPE_2MARG;
if (sim_deb == NULL) /* no log? */ if (sim_deb == NULL) /* no log? */
return SCPE_OK; return SCPE_OK;
r = sim_close_logfile (&sim_deb_ref);
sim_deb = NULL;
if (!sim_quiet) if (!sim_quiet)
printf ("Debug output disabled\n"); printf ("Debug output disabled\n");
if (sim_log) if (sim_log)
fprintf (sim_log, "Debug output disabled\n"); fprintf (sim_log, "Debug output disabled\n");
if (sim_deb_close) /* close if needed */
fclose (sim_deb);
sim_deb_close = 0;
sim_deb = NULL;
return SCPE_OK; return SCPE_OK;
} }
@ -367,20 +397,41 @@ t_stat sim_show_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cpt
if (cptr && (*cptr != 0)) if (cptr && (*cptr != 0))
return SCPE_2MARG; return SCPE_2MARG;
if (sim_deb) if (sim_deb)
fputs ("Debug output enabled\n", st); fprintf (st, "Debug output enabled\n", sim_logfile_name (sim_deb, sim_deb_ref));
else fputs ("Debug output disabled\n", st); else fprintf (st, "Debug output disabled\n");
return SCPE_OK; return SCPE_OK;
} }
/* Set console to Telnet port */ /* SET CONSOLE command */
t_stat sim_set_telnet (int32 flg, char *cptr) /* Set console to Telnet port (and parameters) */
t_stat sim_set_telnet (int32 flag, char *cptr)
{ {
if ((cptr == NULL) || (*cptr == 0)) /* too few arguments? */ char *cvptr, gbuf[CBUFSIZE];
CTAB *ctptr;
t_stat r;
if ((cptr == NULL) || (*cptr == 0))
return SCPE_2FARG; return SCPE_2FARG;
if (sim_con_tmxr.master) /* already open? */ while (*cptr != 0) { /* do all mods */
return SCPE_ALATT; cptr = get_glyph_nc (cptr, gbuf, ','); /* get modifier */
return tmxr_open_master (&sim_con_tmxr, cptr); /* open master socket */ if (cvptr = strchr (gbuf, '=')) /* = value? */
*cvptr++ = 0;
get_glyph (gbuf, gbuf, 0); /* modifier to UC */
if (isdigit (*gbuf)) {
if (sim_con_tmxr.master) return SCPE_ALATT; /* already open? */
return tmxr_open_master (&sim_con_tmxr, gbuf); /* open master socket */
}
else
if (ctptr = find_ctab (set_con_telnet_tab, gbuf)) { /* match? */
r = ctptr->action (ctptr->arg, cvptr); /* do the rest */
if (r != SCPE_OK)
return r;
}
else return SCPE_NOPARAM;
}
return SCPE_OK;
} }
/* Close console Telnet port */ /* Close console Telnet port */
@ -402,17 +453,167 @@ if (cptr && (*cptr != 0))
return SCPE_2MARG; return SCPE_2MARG;
if (sim_con_tmxr.master == 0) if (sim_con_tmxr.master == 0)
fprintf (st, "Connected to console window\n"); fprintf (st, "Connected to console window\n");
else if (sim_con_ldsc.conn == 0)
fprintf (st, "Listening on port %d\n", sim_con_tmxr.port);
else { else {
fprintf (st, "Listening on port %d, connected to socket %d\n", if (sim_con_ldsc.conn == 0)
sim_con_tmxr.port, sim_con_ldsc.conn); fprintf (st, "Listening on port %d\n", sim_con_tmxr.port);
tmxr_fconns (st, &sim_con_ldsc, -1); else {
fprintf (st, "Listening on port %d, connected to socket %d\n",
sim_con_tmxr.port, sim_con_ldsc.conn);
tmxr_fconns (st, &sim_con_ldsc, -1);
}
tmxr_fstats (st, &sim_con_ldsc, -1); tmxr_fstats (st, &sim_con_ldsc, -1);
} }
return SCPE_OK; return SCPE_OK;
} }
/* Set console to Buffering */
t_stat sim_set_cons_buff (int32 flg, char *cptr)
{
char cmdbuf[CBUFSIZE];
sprintf(cmdbuf, "BUFFERED%c%s", cptr ? '=' : '\0', cptr ? cptr : "");
return tmxr_open_master (&sim_con_tmxr, cmdbuf); /* open master socket */
}
/* Set console to NoBuffering */
t_stat sim_set_cons_unbuff (int32 flg, char *cptr)
{
char cmdbuf[CBUFSIZE];
sprintf(cmdbuf, "UNBUFFERED%c%s", cptr ? '=' : '\0', cptr ? cptr : "");
return tmxr_open_master (&sim_con_tmxr, cmdbuf); /* open master socket */
}
/* Set console to Logging */
t_stat sim_set_cons_log (int32 flg, char *cptr)
{
char cmdbuf[CBUFSIZE];
sprintf(cmdbuf, "LOG%c%s", cptr ? '=' : '\0', cptr ? cptr : "");
return tmxr_open_master (&sim_con_tmxr, cmdbuf); /* open master socket */
}
/* Set console to NoLogging */
t_stat sim_set_cons_nolog (int32 flg, char *cptr)
{
char cmdbuf[CBUFSIZE];
sprintf(cmdbuf, "NOLOG%c%s", cptr ? '=' : '\0', cptr ? cptr : "");
return tmxr_open_master (&sim_con_tmxr, cmdbuf); /* open master socket */
}
t_stat sim_show_cons_log (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, char *cptr)
{
if (cptr && (*cptr != 0))
return SCPE_2MARG;
if (sim_con_tmxr.ldsc->txlog)
fprintf (st, "Log File being written to %s\n", sim_con_tmxr.ldsc->txlogname);
else
fprintf (st, "No Logging\n");
return SCPE_OK;
}
t_stat sim_show_cons_buff (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, char *cptr)
{
if (cptr && (*cptr != 0))
return SCPE_2MARG;
if (!sim_con_tmxr.buffered)
fprintf (st, "Unbuffered\n");
else
fprintf (st, "Buffer Size = %d\n", sim_con_tmxr.buffered);
return SCPE_OK;
}
/* Log File Open/Close/Show Support */
/* Open log file */
t_stat sim_open_logfile (char *filename, t_bool binary, FILE **pf, FILEREF **pref)
{
char *tptr, gbuf[CBUFSIZE];
*pref = NULL;
if ((filename == NULL) || (*filename == 0)) /* too few arguments? */
return SCPE_2FARG;
tptr = get_glyph (filename, gbuf, 0);
if (*tptr != 0) /* now eol? */
return SCPE_2MARG;
sim_close_logfile (pref);
*pf = NULL;
if (strcmp (gbuf, "LOG") == 0) { /* output to log? */
if (sim_log == NULL) /* any log? */
return SCPE_ARG;
*pf = sim_log;
*pref = sim_log_ref;
if (*pref)
++(*pref)->refcount;
}
else if (strcmp (gbuf, "DEBUG") == 0) { /* output to debug? */
if (sim_debug == NULL) /* any debug? */
return SCPE_ARG;
*pf = sim_deb;
*pref = sim_deb_ref;
if (*pref)
++(*pref)->refcount;
}
else if (strcmp (gbuf, "STDOUT") == 0) /* output to stdout? */
*pf = stdout;
else if (strcmp (gbuf, "STDERR") == 0) /* output to stderr? */
*pf = stderr;
else {
*pref = calloc (1, sizeof(**pref));
if (!*pref)
return SCPE_MEM;
get_glyph_nc (filename, gbuf, 0); /* reparse */
strncpy ((*pref)->name, gbuf, sizeof((*pref)->name)-1);
*pf = sim_fopen (gbuf, (binary ? "ab" : "a")); /* open file */
if (*pf == NULL) { /* error? */
free (*pref);
*pref = NULL;
return SCPE_OPENERR;
}
(*pref)->file = *pf;
(*pref)->refcount = 1; /* need close */
}
return SCPE_OK;
}
/* Close log file */
t_stat sim_close_logfile (FILEREF **pref)
{
if (NULL == *pref)
return SCPE_OK;
(*pref)->refcount = (*pref)->refcount - 1;
if ((*pref)->refcount > 0)
return SCPE_OK;
fclose ((*pref)->file);
free (*pref);
*pref = NULL;
return SCPE_OK;
}
/* Show logfile support routine */
const char *sim_logfile_name (FILE *st, FILEREF *ref)
{
if (!st)
return "";
if (st == stdout)
return "STDOUT";
if (st == stderr)
return "STDERR";
if (!ref)
return "";
return ref->name;
}
/* Check connection before executing */ /* Check connection before executing */
t_stat sim_check_console (int32 sec) t_stat sim_check_console (int32 sec)
@ -421,10 +622,15 @@ int32 c, i;
if (sim_con_tmxr.master == 0) /* not Telnet? done */ if (sim_con_tmxr.master == 0) /* not Telnet? done */
return SCPE_OK; return SCPE_OK;
if (sim_con_ldsc.conn) { /* connected? */ if (sim_con_ldsc.conn || sim_con_ldsc.txbfd) { /* connected or buffered ? */
tmxr_poll_rx (&sim_con_tmxr); /* poll (check disconn) */ tmxr_poll_rx (&sim_con_tmxr); /* poll (check disconn) */
if (sim_con_ldsc.conn) /* still connected? */ if (sim_con_ldsc.conn || sim_con_ldsc.txbfd) { /* still connected? */
if (!sim_con_ldsc.conn) {
printf ("Running with Buffered Console\n"); /* print transition */
fflush (stdout);
}
return SCPE_OK; return SCPE_OK;
}
} }
for (i = 0; i < sec; i++) { /* loop */ for (i = 0; i < sec; i++) { /* loop */
if (tmxr_poll_conn (&sim_con_tmxr) >= 0) { /* poll connect */ if (tmxr_poll_conn (&sim_con_tmxr) >= 0) { /* poll connect */
@ -456,8 +662,14 @@ int32 c;
c = sim_os_poll_kbd (); /* get character */ c = sim_os_poll_kbd (); /* get character */
if ((c == SCPE_STOP) || (sim_con_tmxr.master == 0)) /* ^E or not Telnet? */ if ((c == SCPE_STOP) || (sim_con_tmxr.master == 0)) /* ^E or not Telnet? */
return c; /* in-window */ return c; /* in-window */
if (sim_con_ldsc.conn == 0) /* no Telnet conn? */ if (sim_con_ldsc.conn == 0) { /* no Telnet conn? */
return SCPE_LOST; if (!sim_con_ldsc.txbfd) /* unbuffered? */
return SCPE_LOST; /* connection lost */
if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */
sim_con_ldsc.rcve = 1; /* rcv enabled */
else /* fall through to poll reception */
return SCPE_OK; /* unconnected and buffered - nothing to receive */
}
tmxr_poll_rx (&sim_con_tmxr); /* poll for input */ tmxr_poll_rx (&sim_con_tmxr); /* poll for input */
if (c = tmxr_getc_ln (&sim_con_ldsc)) /* any char? */ if (c = tmxr_getc_ln (&sim_con_ldsc)) /* any char? */
return (c & (SCPE_BREAK | 0377)) | SCPE_KFLAG; return (c & (SCPE_BREAK | 0377)) | SCPE_KFLAG;
@ -468,12 +680,19 @@ return SCPE_OK;
t_stat sim_putchar (int32 c) t_stat sim_putchar (int32 c)
{ {
if (sim_log) /* log file? */ if (sim_con_tmxr.master == 0) { /* not Telnet? */
fputc (c, sim_log); if (sim_log) /* log file? */
if (sim_con_tmxr.master == 0) /* not Telnet? */ fputc (c, sim_log);
return sim_os_putchar (c); /* in-window version */ return sim_os_putchar (c); /* in-window version */
if (sim_con_ldsc.conn == 0) /* no Telnet conn? */ }
return SCPE_LOST; if (sim_log && !sim_con_ldsc.txlog) /* log file, but no line log? */
fputc (c, sim_log);
if (sim_con_ldsc.conn == 0) { /* no Telnet conn? */
if (!sim_con_ldsc.txbfd) /* unbuffered? */
return SCPE_LOST; /* connection lost */
if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */
sim_con_ldsc.rcve = 1; /* rcv enabled */
}
tmxr_putc_ln (&sim_con_ldsc, c); /* output char */ tmxr_putc_ln (&sim_con_ldsc, c); /* output char */
tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */
return SCPE_OK; return SCPE_OK;
@ -486,8 +705,12 @@ t_stat r;
if (sim_log) fputc (c, sim_log); /* log file? */ if (sim_log) fputc (c, sim_log); /* log file? */
if (sim_con_tmxr.master == 0) /* not Telnet? */ if (sim_con_tmxr.master == 0) /* not Telnet? */
return sim_os_putchar (c); /* in-window version */ return sim_os_putchar (c); /* in-window version */
if (sim_con_ldsc.conn == 0) /* no Telnet conn? */ if (sim_con_ldsc.conn == 0) { /* no Telnet conn? */
return SCPE_LOST; if (!sim_con_ldsc.txbfd) /* non-buffered Telnet conn? */
return SCPE_LOST; /* lost */
if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */
sim_con_ldsc.rcve = 1; /* rcv enabled */
}
if (sim_con_ldsc.xmte == 0) /* xmt disabled? */ if (sim_con_ldsc.xmte == 0) /* xmt disabled? */
r = SCPE_STALL; r = SCPE_STALL;
else r = tmxr_putc_ln (&sim_con_ldsc, c); /* no, Telnet output */ else r = tmxr_putc_ln (&sim_con_ldsc, c); /* no, Telnet output */

View file

@ -23,6 +23,7 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
17-Jan-11 MP Added buffered line capabilities
22-Jun-06 RMS Implemented SET/SHOW PCHAR 22-Jun-06 RMS Implemented SET/SHOW PCHAR
22-Nov-05 RMS Added central input/output conversion support 22-Nov-05 RMS Added central input/output conversion support
05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy 05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy
@ -57,6 +58,10 @@ t_stat sim_set_notelnet (int32 flag, char *cptr);
t_stat sim_set_logon (int32 flag, char *cptr); t_stat sim_set_logon (int32 flag, char *cptr);
t_stat sim_set_logoff (int32 flag, char *cptr); t_stat sim_set_logoff (int32 flag, char *cptr);
t_stat sim_set_debon (int32 flag, char *cptr); t_stat sim_set_debon (int32 flag, char *cptr);
t_stat sim_set_cons_buff (int32 flg, char *cptr);
t_stat sim_set_cons_unbuff (int32 flg, char *cptr);
t_stat sim_set_cons_log (int32 flg, char *cptr);
t_stat sim_set_cons_nolog (int32 flg, char *cptr);
t_stat sim_set_deboff (int32 flag, char *cptr); t_stat sim_set_deboff (int32 flag, char *cptr);
t_stat sim_set_pchar (int32 flag, char *cptr); t_stat sim_set_pchar (int32 flag, char *cptr);
t_stat sim_show_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); t_stat sim_show_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
@ -65,7 +70,12 @@ t_stat sim_show_telnet (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cp
t_stat sim_show_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); t_stat sim_show_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat sim_show_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); t_stat sim_show_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat sim_show_pchar (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); t_stat sim_show_pchar (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat sim_show_cons_buff (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat sim_show_cons_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat sim_check_console (int32 sec); t_stat sim_check_console (int32 sec);
t_stat sim_open_logfile (char *filename, t_bool binary, FILE **pf, FILEREF **pref);
t_stat sim_close_logfile (FILEREF **pref);
const char *sim_logfile_name (FILE *st, FILEREF *ref);
t_stat sim_poll_kbd (void); t_stat sim_poll_kbd (void);
t_stat sim_putchar (int32 c); t_stat sim_putchar (int32 c);
t_stat sim_putchar_s (int32 c); t_stat sim_putchar_s (int32 c);

View file

@ -23,6 +23,7 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
18-Jan-11 MP Added log file reference count support
21-Jul-08 RMS Removed inlining support 21-Jul-08 RMS Removed inlining support
28-May-08 RMS Added inlining support 28-May-08 RMS Added inlining support
28-Jun-07 RMS Added IA64 VMS support (from Norm Lastovica) 28-Jun-07 RMS Added IA64 VMS support (from Norm Lastovica)
@ -486,6 +487,13 @@ struct sim_debtab {
#define DEBUG_PRI(d,m) (sim_deb && (d.dctrl & (m))) #define DEBUG_PRI(d,m) (sim_deb && (d.dctrl & (m)))
#define DEBUG_PRJ(d,m) (sim_deb && (d->dctrl & (m))) #define DEBUG_PRJ(d,m) (sim_deb && (d->dctrl & (m)))
/* File Reference */
struct sim_fileref {
char name[CBUFSIZE]; /* file name */
FILE *file; /* file handle */
int32 refcount; /* reference count */
};
/* The following macros define structure contents */ /* The following macros define structure contents */
#define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),(cap),0,0 #define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),(cap),0,0
@ -522,6 +530,7 @@ typedef struct sim_mtab MTAB;
typedef struct sim_schtab SCHTAB; typedef struct sim_schtab SCHTAB;
typedef struct sim_brktab BRKTAB; typedef struct sim_brktab BRKTAB;
typedef struct sim_debtab DEBTAB; typedef struct sim_debtab DEBTAB;
typedef struct sim_fileref FILEREF;
/* Function prototypes */ /* Function prototypes */

View file

@ -26,6 +26,7 @@
Based on the original DZ11 simulator by Thord Nilson, as updated by Based on the original DZ11 simulator by Thord Nilson, as updated by
Arthur Krewat. Arthur Krewat.
17-Jan-11 MP Added Buffered line capabilities
16-Jan-11 MP Made option negotiation more reliable 16-Jan-11 MP Made option negotiation more reliable
20-Nov-08 RMS Added three new standardized SHOW routines 20-Nov-08 RMS Added three new standardized SHOW routines
30-Sep-08 JDB Reverted tmxr_find_ldsc to original implementation 30-Sep-08 JDB Reverted tmxr_find_ldsc to original implementation
@ -154,9 +155,12 @@ int32 tmxr_poll_conn (TMXR *mp)
SOCKET newsock; SOCKET newsock;
TMLN *lp; TMLN *lp;
int32 *op; int32 *op;
int32 i, j; int32 i, j, psave;
uint32 ipaddr; uint32 ipaddr;
char cmsg[80];
char dmsg[80] = "";
char lmsg[80] = "";
char msgbuf[256];
static char mantra[] = { static char mantra[] = {
TN_IAC, TN_WILL, TN_LINE, TN_IAC, TN_WILL, TN_LINE,
TN_IAC, TN_WILL, TN_SGA, TN_IAC, TN_WILL, TN_SGA,
@ -189,34 +193,38 @@ if (newsock != INVALID_SOCKET) { /* got a live one? */
lp = mp->ldsc + i; /* get line desc */ lp = mp->ldsc + i; /* get line desc */
lp->conn = newsock; /* record connection */ lp->conn = newsock; /* record connection */
lp->ipad = ipaddr; /* ip address */ lp->ipad = ipaddr; /* ip address */
sim_write_sock (newsock, mantra, sizeof(mantra));
sprintf (cmsg, "\n\r\nConnected to the %s simulator ", sim_name);
if (mp->dptr) { /* device defined? */
sprintf (dmsg, "%s device", /* report device name */
sim_dname (mp->dptr));
if (mp->lines > 1) /* more than one line? */
sprintf (lmsg, ", line %d", i); /* report the line number */
}
sprintf (msgbuf, "%s%s%s\r\n\n", cmsg, dmsg, lmsg);
lp->cnms = sim_os_msec (); /* time of conn */ lp->cnms = sim_os_msec (); /* time of conn */
lp->rxbpr = lp->rxbpi = 0; /* init buf pointers */ if (!mp->buffered) {
lp->txbpr = lp->txbpi = 0; lp->txbpi = 0; /* init buf pointers */
lp->rxcnt = lp->txcnt = 0; /* init counters */ lp->txbpr = lp->txbsz - strlen (msgbuf);
lp->rxcnt = lp->txcnt = lp->txdrp = 0; /* init counters */
}
else
if (lp->txcnt > lp->txbsz)
lp->txbpr = (lp->txbpi + 1) % lp->txbsz;
else
lp->txbpr = lp->txbsz - strlen (msgbuf);
lp->tsta = 0; /* init telnet state */ lp->tsta = 0; /* init telnet state */
lp->xmte = 1; /* enable transmit */ lp->xmte = 1; /* enable transmit */
lp->dstb = 0; /* default bin mode */ lp->dstb = 0; /* default bin mode */
sim_write_sock (newsock, mantra, sizeof (mantra)); psave = lp->txbpi; /* save insertion pointer */
tmxr_linemsg (lp, "\n\r\nConnected to the "); lp->txbpi = lp->txbpr; /* insert connection message */
tmxr_linemsg (lp, sim_name); tmxr_linemsg (lp, msgbuf); /* beginning of buffer */
tmxr_linemsg (lp, " simulator "); lp->txbpi = psave; /* restore insertion pointer */
if (mp->dptr) { /* device defined? */
tmxr_linemsg (lp, sim_dname (mp->dptr)); /* report device name */
tmxr_linemsg (lp, " device");
if (mp->lines > 1) { /* more than one line? */
char line[20];
tmxr_linemsg (lp, ", line "); /* report the line number */
sprintf (line, "%i", i);
tmxr_linemsg (lp, line);
}
}
tmxr_linemsg (lp, "\r\n\n");
tmxr_poll_tx (mp); /* flush output */ tmxr_poll_tx (mp); /* flush output */
lp->txcnt -= strlen (msgbuf); /* adjust statistics */
return i; return i;
} }
} /* end if newsock */ } /* end if newsock */
@ -233,7 +241,8 @@ tmxr_send_buffered_data (lp); /* send buffered data */
sim_close_sock (lp->conn, 0); /* reset conn */ sim_close_sock (lp->conn, 0); /* reset conn */
lp->conn = lp->tsta = 0; /* reset state */ lp->conn = lp->tsta = 0; /* reset state */
lp->rxbpr = lp->rxbpi = 0; lp->rxbpr = lp->rxbpi = 0;
lp->txbpr = lp->txbpi = 0; if (!lp->txbfd)
lp->txbpr = lp->txbpi = 0;
lp->xmte = 1; lp->xmte = 1;
lp->dstb = 0; lp->dstb = 0;
return; return;
@ -419,7 +428,7 @@ return;
int32 tmxr_rqln (TMLN *lp) int32 tmxr_rqln (TMLN *lp)
{ {
return (lp->rxbpi - lp->rxbpr); return (lp->rxbpi - lp->rxbpr + ((lp->rxbpi < lp->rxbpr)? TMXR_MAXBUF: 0));
} }
/* Remove character p (and matching status) from line l input buffer */ /* Remove character p (and matching status) from line l input buffer */
@ -447,24 +456,29 @@ t_stat tmxr_putc_ln (TMLN *lp, int32 chr)
{ {
if (lp->txlog) /* log if available */ if (lp->txlog) /* log if available */
fputc (chr, lp->txlog); fputc (chr, lp->txlog);
if (lp->conn == 0) /* no conn? lost */ if ((lp->conn == 0) && (!lp->txbfd)) /* no conn & not buffered? */
return SCPE_LOST; if (lp->txlog) /* if it was logged, we got it */
if (tmxr_tqln (lp) < (TMXR_MAXBUF - 1)) { /* room for char (+ IAC)? */ return SCPE_OK;
lp->txb[lp->txbpi] = (char) chr; /* buffer char */ else {
lp->txbpi = lp->txbpi + 1; /* adv pointer */ ++lp->txdrp; /* lost */
if (lp->txbpi >= TMXR_MAXBUF) /* wrap? */ return SCPE_LOST;
lp->txbpi = 0;
if ((char) chr == TN_IAC) { /* IAC? */
lp->txb[lp->txbpi] = (char) chr; /* IAC + IAC */
lp->txbpi = lp->txbpi + 1; /* adv pointer */
if (lp->txbpi >= TMXR_MAXBUF) /* wrap? */
lp->txbpi = 0;
} }
if (tmxr_tqln (lp) > (TMXR_MAXBUF - TMXR_GUARD)) /* near full? */ #define TXBUF_AVAIL(lp) (lp->txbsz - tmxr_tqln (lp))
#define TXBUF_CHAR(lp, c) { \
lp->txb[lp->txbpi++] = (char)(c); \
lp->txbpi %= lp->txbsz; \
if (lp->txbpi == lp->txbpr) \
lp->txbpr = (1+lp->txbpr)%lp->txbsz, ++lp->txdrp; \
}
if ((lp->txbfd) || (TXBUF_AVAIL(lp) > 1)) { /* room for char (+ IAC)? */
if (TN_IAC == (char) chr) /* char == IAC ? */
TXBUF_CHAR (lp, TN_IAC); /* stuff extra IAC char */
TXBUF_CHAR (lp, chr); /* buffer char & adv pointer */
if ((!lp->txbfd) && (TXBUF_AVAIL (lp) <= TMXR_GUARD))/* near full? */
lp->xmte = 0; /* disable line */ lp->xmte = 0; /* disable line */
return SCPE_OK; /* char sent */ return SCPE_OK; /* char sent */
} }
lp->xmte = 0; /* no room, dsbl line */ ++lp->txdrp; lp->xmte = 0; /* no room, dsbl line */
return SCPE_STALL; /* char not sent */ return SCPE_STALL; /* char not sent */
} }
@ -510,10 +524,10 @@ if (nbytes) { /* >0? write */
sbytes = sim_write_sock (lp->conn, /* write all data */ sbytes = sim_write_sock (lp->conn, /* write all data */
&(lp->txb[lp->txbpr]), nbytes); &(lp->txb[lp->txbpr]), nbytes);
else sbytes = sim_write_sock (lp->conn, /* write to end buf */ else sbytes = sim_write_sock (lp->conn, /* write to end buf */
&(lp->txb[lp->txbpr]), TMXR_MAXBUF - lp->txbpr); &(lp->txb[lp->txbpr]), lp->txbsz - lp->txbpr);
if (sbytes != SOCKET_ERROR) { /* ok? */ if (sbytes != SOCKET_ERROR) { /* ok? */
lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */ lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */
if (lp->txbpr >= TMXR_MAXBUF) /* wrap? */ if (lp->txbpr >= lp->txbsz) /* wrap? */
lp->txbpr = 0; lp->txbpr = 0;
lp->txcnt = lp->txcnt + sbytes; /* update counts */ lp->txcnt = lp->txcnt + sbytes; /* update counts */
nbytes = nbytes - sbytes; nbytes = nbytes - sbytes;
@ -522,7 +536,7 @@ if (nbytes) { /* >0? write */
sbytes = sim_write_sock (lp->conn, lp->txb, nbytes); sbytes = sim_write_sock (lp->conn, lp->txb, nbytes);
if (sbytes != SOCKET_ERROR) { /* ok */ if (sbytes != SOCKET_ERROR) { /* ok */
lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */ lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */
if (lp->txbpr >= TMXR_MAXBUF) /* wrap? */ if (lp->txbpr >= lp->txbsz) /* wrap? */
lp->txbpr = 0; lp->txbpr = 0;
lp->txcnt = lp->txcnt + sbytes; /* update counts */ lp->txcnt = lp->txcnt + sbytes; /* update counts */
nbytes = nbytes - sbytes; nbytes = nbytes - sbytes;
@ -536,7 +550,7 @@ return nbytes;
int32 tmxr_tqln (TMLN *lp) int32 tmxr_tqln (TMLN *lp)
{ {
return (lp->txbpi - lp->txbpr + ((lp->txbpi < lp->txbpr)? TMXR_MAXBUF: 0)); return (lp->txbpi - lp->txbpr + ((lp->txbpi < lp->txbpr)? lp->txbsz: 0));
} }
/* Open master socket */ /* Open master socket */
@ -548,6 +562,81 @@ SOCKET sock;
TMLN *lp; TMLN *lp;
t_stat r; t_stat r;
if (!isdigit(*cptr)) {
char gbuf[CBUFSIZE];
cptr = get_glyph (cptr, gbuf, '=');
if (0 == MATCH_CMD (gbuf, "LOG")) {
if ((NULL == cptr) || ('\0' == *cptr))
return SCPE_2FARG;
strncpy(mp->logfiletmpl, cptr, sizeof(mp->logfiletmpl)-1);
for (i = 0; i < mp->lines; i++) {
lp = mp->ldsc + i;
sim_close_logfile (&lp->txlogref);
lp->txlog = NULL;
lp->txlogname = realloc(lp->txlogname, CBUFSIZE);
if (mp->lines > 1)
sprintf(lp->txlogname, "%s_%d", mp->logfiletmpl, i);
else
strcpy(lp->txlogname, mp->logfiletmpl);
r = sim_open_logfile (lp->txlogname, TRUE, &lp->txlog, &lp->txlogref);
if (r == SCPE_OK)
setvbuf(lp->txlog, NULL, _IOFBF, 65536);
else {
free (lp->txlogname);
lp->txlogname = NULL;
break;
}
}
return r;
}
if ((0 == MATCH_CMD (gbuf, "NOBUFFERED")) ||
(0 == MATCH_CMD (gbuf, "UNBUFFERED"))) {
if (mp->buffered) {
mp->buffered = 0;
for (i = 0; i < mp->lines; i++) { /* default line buffers */
lp = mp->ldsc + i;
lp->txbsz = TMXR_MAXBUF;
lp->txb = (char *)realloc(lp->txb, lp->txbsz);
lp->txbfd = lp->txbpi = lp->txbpr = 0;
}
}
return SCPE_OK;
}
if (0 == MATCH_CMD (gbuf, "BUFFERED")) {
if ((NULL == cptr) || ('\0' == *cptr))
mp->buffered = 32768;
else {
i = (int32) get_uint (cptr, 10, 1024*1024, &r);
if ((r != SCPE_OK) || (i == 0))
return SCPE_ARG;
mp->buffered = i;
}
for (i = 0; i < mp->lines; i++) { /* initialize line buffers */
lp = mp->ldsc + i;
lp->txbsz = mp->buffered;
lp->txbfd = 1;
lp->txb = (char *)realloc(lp->txb, lp->txbsz);
lp->txbpi = lp->txbpr = 0;
}
return SCPE_OK;
}
if (0 == MATCH_CMD (gbuf, "NOLOG")) {
if ((NULL != cptr) && ('\0' != *cptr))
return SCPE_2MARG;
mp->logfiletmpl[0] = '\0';
for (i = 0; i < mp->lines; i++) { /* close line logs */
lp = mp->ldsc + i;
free(lp->txlogname);
lp->txlogname = NULL;
if (lp->txlog) {
sim_close_logfile (&lp->txlogref);
lp->txlog = NULL;
}
}
return SCPE_OK;
}
return SCPE_ARG;
}
port = (int32) get_uint (cptr, 10, 65535, &r); /* get port */ port = (int32) get_uint (cptr, 10, 65535, &r); /* get port */
if ((r != SCPE_OK) || (port == 0)) if ((r != SCPE_OK) || (port == 0))
return SCPE_ARG; return SCPE_ARG;
@ -564,7 +653,12 @@ for (i = 0; i < mp->lines; i++) { /* initialize lines */
lp->conn = lp->tsta = 0; lp->conn = lp->tsta = 0;
lp->rxbpi = lp->rxbpr = 0; lp->rxbpi = lp->rxbpr = 0;
lp->txbpi = lp->txbpr = 0; lp->txbpi = lp->txbpr = 0;
lp->rxcnt = lp->txcnt = 0; if (!mp->buffered) {
lp->txbfd = lp->txbpi = lp->txbpr = 0;
lp->txbsz = TMXR_MAXBUF;
lp->txb = (char *)realloc(lp->txb, lp->txbsz);
}
lp->rxcnt = lp->txcnt = lp->txdrp = 0;
lp->xmte = 1; lp->xmte = 1;
lp->dstb = 0; lp->dstb = 0;
} }
@ -577,8 +671,11 @@ t_stat tmxr_attach (TMXR *mp, UNIT *uptr, char *cptr)
{ {
char* tptr; char* tptr;
t_stat r; t_stat r;
char pmsg[20], bmsg[32] = "", lmsg[64+PATH_MAX] = "";
tptr = (char *) malloc (strlen (cptr) + 1); /* get string buf */ tptr = (char *) malloc (strlen (cptr) + /* get string buf */
sizeof(pmsg) +
sizeof(bmsg) + sizeof(lmsg));
if (tptr == NULL) /* no more mem? */ if (tptr == NULL) /* no more mem? */
return SCPE_MEM; return SCPE_MEM;
r = tmxr_open_master (mp, cptr); /* open master socket */ r = tmxr_open_master (mp, cptr); /* open master socket */
@ -586,7 +683,12 @@ if (r != SCPE_OK) { /* error? */
free (tptr); /* release buf */ free (tptr); /* release buf */
return SCPE_OPENERR; return SCPE_OPENERR;
} }
strcpy (tptr, cptr); /* copy port */ sprintf (pmsg, "%d", mp->port); /* copy port */
if (mp->buffered)
sprintf (bmsg, ", buffered=%d", mp->buffered); /* buffer info */
if (mp->logfiletmpl[0])
sprintf (lmsg, ", log=%s", mp->logfiletmpl); /* logfile info */
sprintf (tptr, "%s%s%s", pmsg, bmsg, lmsg); /* assemble all */
uptr->filename = tptr; /* save */ uptr->filename = tptr; /* save */
uptr->flags = uptr->flags | UNIT_ATT; /* no more errors */ uptr->flags = uptr->flags | UNIT_ATT; /* no more errors */
@ -696,16 +798,24 @@ static const char *enab = "on";
static const char *dsab = "off"; static const char *dsab = "off";
if (ln >= 0) if (ln >= 0)
fprintf (st, "line %d: ", ln); fprintf (st, "line %d:\b", ln);
if (lp->conn) { if (!lp->conn)
fprintf (st, "input (%s) queued/total = %d/%d, ", fprintf (st, "line disconnected\n");
if (lp->rxcnt)
fprintf (st, " input (%s) queued/total = %d/%d\n",
(lp->rcve? enab: dsab), (lp->rcve? enab: dsab),
lp->rxbpi - lp->rxbpr, lp->rxcnt); tmxr_rqln (lp), lp->rxcnt);
fprintf (st, "output (%s) queued/total = %d/%d\n", if (lp->txcnt || lp->txbpi)
fprintf (st, " output (%s) queued/total = %d/%d\n",
(lp->xmte? enab: dsab), (lp->xmte? enab: dsab),
lp->txbpi - lp->txbpr, lp->txcnt); tmxr_tqln (lp), lp->txcnt);
} if (lp->txbfd)
else fprintf (st, "line disconnected\n"); fprintf (st, " output buffer size = %d\n", lp->txbsz);
if (lp->txcnt || lp->txbpi)
fprintf (st, " bytes in buffer = %d\n",
((lp->txcnt > 0) && (lp->txcnt > lp->txbsz)) ? lp->txbsz : lp->txbpi);
if (lp->txdrp)
fprintf (st, " dropped = %d\n", lp->txdrp);
return; return;
} }
@ -758,7 +868,7 @@ lp->txlogname = (char *) calloc (CBUFSIZE, sizeof (char)); /* alloc namebuf */
if (lp->txlogname == NULL) /* can't? */ if (lp->txlogname == NULL) /* can't? */
return SCPE_MEM; return SCPE_MEM;
strncpy (lp->txlogname, cptr, CBUFSIZE); /* save file name */ strncpy (lp->txlogname, cptr, CBUFSIZE); /* save file name */
lp->txlog = fopen (cptr, "ab"); /* open log */ sim_open_logfile (cptr, TRUE, &lp->txlog, &lp->txlogref);/* open log */
if (lp->txlog == NULL) { /* error? */ if (lp->txlog == NULL) { /* error? */
free (lp->txlogname); /* free buffer */ free (lp->txlogname); /* free buffer */
return SCPE_OPENERR; return SCPE_OPENERR;
@ -779,7 +889,7 @@ lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */
if (lp == NULL) if (lp == NULL)
return SCPE_IERR; return SCPE_IERR;
if (lp->txlog) { /* logging? */ if (lp->txlog) { /* logging? */
fclose (lp->txlog); /* close log */ sim_close_logfile (&lp->txlogref); /* close log */
free (lp->txlogname); /* free namebuf */ free (lp->txlogname); /* free namebuf */
lp->txlog = NULL; lp->txlog = NULL;
lp->txlogname = NULL; lp->txlogname = NULL;

View file

@ -26,6 +26,7 @@
Based on the original DZ11 simulator by Thord Nilson, as updated by Based on the original DZ11 simulator by Thord Nilson, as updated by
Arthur Krewat. Arthur Krewat.
17-Jan-11 MP Added buffered line capabilities
20-Nov-08 RMS Added three new standardized SHOW routines 20-Nov-08 RMS Added three new standardized SHOW routines
27-May-08 JDB Added lnorder to TMXR structure, 27-May-08 JDB Added lnorder to TMXR structure,
added tmxr_set_lnorder and tmxr_set_lnorder added tmxr_set_lnorder and tmxr_set_lnorder
@ -62,11 +63,15 @@ struct tmln {
int32 txbpr; /* xmt buf remove */ int32 txbpr; /* xmt buf remove */
int32 txbpi; /* xmt buf insert */ int32 txbpi; /* xmt buf insert */
int32 txcnt; /* xmt count */ int32 txcnt; /* xmt count */
int32 txdrp; /* xmt drop count */
int32 txbsz; /* xmt buffer size */
int32 txbfd; /* xmt buffered flag */
FILE *txlog; /* xmt log file */ FILE *txlog; /* xmt log file */
FILEREF *txlogref; /* xmt log file reference */
char *txlogname; /* xmt log file name */ char *txlogname; /* xmt log file name */
char rxb[TMXR_MAXBUF]; /* rcv buffer */ char rxb[TMXR_MAXBUF]; /* rcv buffer */
char rbr[TMXR_MAXBUF]; /* rcv break */ char rbr[TMXR_MAXBUF]; /* rcv break */
char txb[TMXR_MAXBUF]; /* xmt buffer */ char *txb; /* xmt buffer */
}; };
typedef struct tmln TMLN; typedef struct tmln TMLN;
@ -78,6 +83,8 @@ struct tmxr {
TMLN *ldsc; /* line descriptors */ TMLN *ldsc; /* line descriptors */
int32 *lnorder; /* line connection order */ int32 *lnorder; /* line connection order */
DEVICE *dptr; /* multiplexer device */ DEVICE *dptr; /* multiplexer device */
char logfiletmpl[FILENAME_MAX]; /* template logfile name */
int32 buffered; /* Buffered Line Behavior and Buffer Size Flag */
}; };
typedef struct tmxr TMXR; typedef struct tmxr TMXR;