SCP: Add the ability to Fprintf to memory buffer

This commit is contained in:
Mark Pizzolato 2017-01-23 10:25:06 -08:00
parent 5c6dabbccf
commit 8dcc8c0678
2 changed files with 69 additions and 7 deletions

68
scp.c
View file

@ -523,6 +523,7 @@ int32 sim_interval = 0;
int32 sim_switches = 0; int32 sim_switches = 0;
FILE *sim_ofile = NULL; FILE *sim_ofile = NULL;
TMLN *sim_oline = NULL; TMLN *sim_oline = NULL;
MEMFILE *sim_mfile = NULL;
SCHTAB *sim_schrptr = FALSE; SCHTAB *sim_schrptr = FALSE;
SCHTAB *sim_schaptr = FALSE; SCHTAB *sim_schaptr = FALSE;
DEVICE *sim_dfdev = NULL; DEVICE *sim_dfdev = NULL;
@ -4704,7 +4705,9 @@ t_stat show_queue (FILE *st, DEVICE *dnotused, UNIT *unotused, int32 flag, CONST
DEVICE *dptr; DEVICE *dptr;
UNIT *uptr; UNIT *uptr;
int32 accum; int32 accum;
MEMFILE buf;
memset (&buf, 0, sizeof (buf));
if (cptr && (*cptr != 0)) if (cptr && (*cptr != 0))
return SCPE_2MARG; return SCPE_2MARG;
if (sim_clock_queue == QUEUE_LIST_END) if (sim_clock_queue == QUEUE_LIST_END)
@ -4745,6 +4748,7 @@ else {
sim_show_clock_queues (st, dnotused, unotused, flag, cptr); sim_show_clock_queues (st, dnotused, unotused, flag, cptr);
#if defined (SIM_ASYNCH_IO) #if defined (SIM_ASYNCH_IO)
pthread_mutex_lock (&sim_asynch_lock); pthread_mutex_lock (&sim_asynch_lock);
sim_mfile = &buf;
fprintf (st, "asynchronous pending event queue\n"); fprintf (st, "asynchronous pending event queue\n");
if (sim_asynch_queue == QUEUE_LIST_END) if (sim_asynch_queue == QUEUE_LIST_END)
fprintf (st, " Empty\n"); fprintf (st, " Empty\n");
@ -4762,6 +4766,9 @@ else {
fprintf (st, "asynch latency: %d nanoseconds\n", sim_asynch_latency); fprintf (st, "asynch latency: %d nanoseconds\n", sim_asynch_latency);
fprintf (st, "asynch instruction latency: %d instructions\n", sim_asynch_inst_latency); fprintf (st, "asynch instruction latency: %d instructions\n", sim_asynch_inst_latency);
pthread_mutex_unlock (&sim_asynch_lock); 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 */ #endif /* SIM_ASYNCH_IO */
return SCPE_OK; return SCPE_OK;
} }
@ -10931,12 +10938,61 @@ int Fprintf (FILE *f, const char* fmt, ...)
int ret = 0; int ret = 0;
va_list args; va_list args;
va_start (args, fmt); if (sim_mfile) {
if (sim_oline) char stackbuf[STACKBUFSIZE];
tmxr_linemsgvf (sim_oline, fmt, args); int32 bufsize = sizeof(stackbuf);
else char *buf = stackbuf;
ret = vfprintf (f, fmt, args); va_list arglist;
va_end (args); 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; return ret;
} }

View file

@ -428,6 +428,7 @@ typedef struct EXPECT EXPECT;
typedef struct SEND SEND; typedef struct SEND SEND;
typedef struct DEBTAB DEBTAB; typedef struct DEBTAB DEBTAB;
typedef struct FILEREF FILEREF; typedef struct FILEREF FILEREF;
typedef struct MEMFILE MEMFILE;
typedef struct BITFIELD BITFIELD; typedef struct BITFIELD BITFIELD;
typedef t_stat (*ACTIVATE_API)(UNIT *unit, int32 interval); typedef t_stat (*ACTIVATE_API)(UNIT *unit, int32 interval);
@ -806,13 +807,18 @@ struct DEBTAB {
#define SIM_DBG_ACTIVATE 0x20000 #define SIM_DBG_ACTIVATE 0x20000
#define SIM_DBG_AIO_QUEUE 0x40000 #define SIM_DBG_AIO_QUEUE 0x40000
/* File Reference */ /* Open File Reference */
struct FILEREF { struct FILEREF {
char name[CBUFSIZE]; /* file name */ char name[CBUFSIZE]; /* file name */
FILE *file; /* file handle */ FILE *file; /* file handle */
int32 refcount; /* reference count */ 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 The following macros exist to help populate structure contents