SCP: Add the ability to Fprintf to memory buffer
This commit is contained in:
parent
5c6dabbccf
commit
8dcc8c0678
2 changed files with 69 additions and 7 deletions
56
scp.c
56
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue