From 8dcc8c067860628b39e13a2d04d6afa13f235198 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Mon, 23 Jan 2017 10:25:06 -0800 Subject: [PATCH] SCP: Add the ability to Fprintf to memory buffer --- scp.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++----- sim_defs.h | 8 ++++++- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/scp.c b/scp.c index e3d05199..53da17f2 100644 --- a/scp.c +++ b/scp.c @@ -523,6 +523,7 @@ int32 sim_interval = 0; int32 sim_switches = 0; FILE *sim_ofile = NULL; TMLN *sim_oline = NULL; +MEMFILE *sim_mfile = NULL; SCHTAB *sim_schrptr = FALSE; SCHTAB *sim_schaptr = FALSE; DEVICE *sim_dfdev = NULL; @@ -4704,7 +4705,9 @@ t_stat show_queue (FILE *st, DEVICE *dnotused, UNIT *unotused, int32 flag, CONST DEVICE *dptr; UNIT *uptr; int32 accum; +MEMFILE buf; +memset (&buf, 0, sizeof (buf)); if (cptr && (*cptr != 0)) return SCPE_2MARG; if (sim_clock_queue == QUEUE_LIST_END) @@ -4745,6 +4748,7 @@ else { sim_show_clock_queues (st, dnotused, unotused, flag, cptr); #if defined (SIM_ASYNCH_IO) pthread_mutex_lock (&sim_asynch_lock); +sim_mfile = &buf; fprintf (st, "asynchronous pending event queue\n"); if (sim_asynch_queue == QUEUE_LIST_END) fprintf (st, " Empty\n"); @@ -4762,6 +4766,9 @@ else { fprintf (st, "asynch latency: %d nanoseconds\n", sim_asynch_latency); fprintf (st, "asynch instruction latency: %d instructions\n", sim_asynch_inst_latency); pthread_mutex_unlock (&sim_asynch_lock); +sim_mfile = NULL; +fprintf (st, "%*.*s", (int)buf.pos, (int)buf.pos, buf.buf); +free (buf.buf); #endif /* SIM_ASYNCH_IO */ return SCPE_OK; } @@ -10931,12 +10938,61 @@ int Fprintf (FILE *f, const char* fmt, ...) int ret = 0; va_list args; -va_start (args, fmt); -if (sim_oline) - tmxr_linemsgvf (sim_oline, fmt, args); -else - ret = vfprintf (f, fmt, args); -va_end (args); +if (sim_mfile) { + char stackbuf[STACKBUFSIZE]; + int32 bufsize = sizeof(stackbuf); + char *buf = stackbuf; + va_list arglist; + int32 len; + + buf[bufsize-1] = '\0'; + + while (1) { /* format passed string, args */ + va_start (arglist, fmt); +#if defined(NO_vsnprintf) + len = vsprintf (buf, fmt, arglist); +#else /* !defined(NO_vsnprintf) */ + len = vsnprintf (buf, bufsize-1, fmt, arglist); +#endif /* NO_vsnprintf */ + va_end (arglist); + +/* If the formatted result didn't fit into the buffer, then grow the buffer and try again */ + + if ((len < 0) || (len >= bufsize-1)) { + if (buf != stackbuf) + free (buf); + bufsize = bufsize * 2; + if (bufsize < len + 2) + bufsize = len + 2; + buf = (char *) malloc (bufsize); + if (buf == NULL) /* out of memory */ + return -1; + buf[bufsize-1] = '\0'; + continue; + } + break; + } + +/* Store the formatted data */ + + if (sim_mfile->pos + len > sim_mfile->size) { + sim_mfile->size = sim_mfile->pos + 2 * MAX(bufsize, 512); + sim_mfile->buf = (char *)realloc (sim_mfile->buf, sim_mfile->size); + } + memcpy (sim_mfile->buf + sim_mfile->pos, buf, len); + sim_mfile->pos += len; + + if (buf != stackbuf) + free (buf); + } +else { + va_start (args, fmt); + if (sim_oline) + tmxr_linemsgvf (sim_oline, fmt, args); + else + ret = vfprintf (f, fmt, args); + va_end (args); + } return ret; } diff --git a/sim_defs.h b/sim_defs.h index ed6c29d3..2ad7a71f 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -428,6 +428,7 @@ typedef struct EXPECT EXPECT; typedef struct SEND SEND; typedef struct DEBTAB DEBTAB; typedef struct FILEREF FILEREF; +typedef struct MEMFILE MEMFILE; typedef struct BITFIELD BITFIELD; typedef t_stat (*ACTIVATE_API)(UNIT *unit, int32 interval); @@ -806,13 +807,18 @@ struct DEBTAB { #define SIM_DBG_ACTIVATE 0x20000 #define SIM_DBG_AIO_QUEUE 0x40000 -/* File Reference */ +/* Open File Reference */ struct FILEREF { char name[CBUFSIZE]; /* file name */ FILE *file; /* file handle */ int32 refcount; /* reference count */ }; +struct MEMFILE { + char *buf; /* buffered data */ + size_t size; /* size */ + size_t pos; /* data used */ + }; /* The following macros exist to help populate structure contents