mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-09-29 09:56:26 +00:00
greatly reduce stack requirements of vfprintf() and __sbprintf()
This commit is contained in:
parent
a071932b06
commit
c52fcd3475
@ -1,4 +1,3 @@
|
|||||||
#line 1 ":src:gno:lib:libc:stdio:vfprintf.c"
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1990, 1993
|
* Copyright (c) 1990, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
@ -37,14 +36,8 @@
|
|||||||
|
|
||||||
#ifdef __ORCAC__
|
#ifdef __ORCAC__
|
||||||
segment "libc_stdio";
|
segment "libc_stdio";
|
||||||
#pragma debug -1
|
#pragma optimize 78 /* bits 3 and 6, minimum */
|
||||||
#pragma optimize 72
|
#pragma debug 0
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNO__
|
|
||||||
#define STATIC static
|
|
||||||
#else
|
|
||||||
#define STATIC
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
@ -100,42 +93,43 @@ __sprint(FILE *fp, register struct __suio *uio)
|
|||||||
* temporary buffer. We only work on write-only files; this avoids
|
* temporary buffer. We only work on write-only files; this avoids
|
||||||
* worries about ungetc buffers and so forth.
|
* worries about ungetc buffers and so forth.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
__sbprintf(register FILE *fp, const char *fmt, va_list ap)
|
__sbprintf(register FILE *fp, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
FILE fake;
|
#if 1
|
||||||
/* ifdef __GNO__ */
|
FILE *fake;
|
||||||
#if 0
|
unsigned char *buf;
|
||||||
char *buf;
|
if ((fake = malloc(BUFSIZ + sizeof(FILE))) == NULL) {
|
||||||
if (buf = malloc(BUFSIZ)) {
|
/* silent failure; hopefully benign */
|
||||||
/* not much we can do here */
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
buf = (unsigned char *) ((unsigned long)fake + sizeof(FILE));
|
||||||
#else
|
#else
|
||||||
|
FILE fake;
|
||||||
unsigned char buf[BUFSIZ];
|
unsigned char buf[BUFSIZ];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* copy the important variables */
|
/* copy the important variables */
|
||||||
fake._flags = fp->_flags & ~__SNBF;
|
fake->_flags = fp->_flags & ~__SNBF;
|
||||||
fake._file = fp->_file;
|
fake->_file = fp->_file;
|
||||||
fake._cookie = fp->_cookie;
|
fake->_cookie = fp->_cookie;
|
||||||
fake._write = fp->_write;
|
fake->_write = fp->_write;
|
||||||
|
|
||||||
/* set up the buffer */
|
/* set up the buffer */
|
||||||
fake._bf._base = fake._p = buf;
|
fake->_bf._base = fake->_p = buf;
|
||||||
fake._bf._size = fake._w = sizeof(buf);
|
fake->_bf._size = fake->_w = BUFSIZ; /* gdr: previously sizeof(buf) */
|
||||||
fake._lbfsize = 0; /* not actually used, but Just In Case */
|
fake->_lbfsize = 0; /* not actually used, but Just In Case */
|
||||||
|
|
||||||
/* do the work, then copy any error status */
|
/* do the work, then copy any error status */
|
||||||
ret = vfprintf(&fake, fmt, ap);
|
ret = vfprintf(fake, fmt, ap);
|
||||||
if (ret >= 0 && fflush(&fake))
|
if (ret >= 0 && fflush(fake))
|
||||||
ret = EOF;
|
ret = EOF;
|
||||||
if (fake._flags & __SERR)
|
if (fake->_flags & __SERR)
|
||||||
fp->_flags |= __SERR;
|
fp->_flags |= __SERR;
|
||||||
/* ifdef __GNO__ */
|
#if 1
|
||||||
#if 0
|
free(fake);
|
||||||
free(buf);
|
|
||||||
#endif
|
#endif
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
@ -299,9 +293,82 @@ static int exponent __P((char *, int, int));
|
|||||||
#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
|
#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
|
||||||
#define FPT 0x100 /* Floating point number */
|
#define FPT 0x100 /* Floating point number */
|
||||||
|
|
||||||
|
#ifdef __ORCAC__
|
||||||
|
typedef struct vfprintfData_t {
|
||||||
|
char *fmt; /* format string */
|
||||||
|
int ch; /* character from fmt */
|
||||||
|
int n; /* handy integer (short term usage) */
|
||||||
|
char *cp; /* handy char pointer (short term usage) */
|
||||||
|
struct __siov *iovp; /* for PRINT macro */
|
||||||
|
int flags; /* flags as above */
|
||||||
|
int ret; /* return value accumulator */
|
||||||
|
int width; /* width from format (%8d), or 0 */
|
||||||
|
int prec; /* precision from format (%.3d), or -1 */
|
||||||
|
char sign; /* sign prefix (' ', '+', '-', or \0) */
|
||||||
|
#ifdef FLOATING_POINT
|
||||||
|
char softsign; /* temporary negative sign for floats */
|
||||||
|
double_spec_t _double; /* double precision arguments %[eEfgG] */
|
||||||
|
int expt; /* integer value of exponent */
|
||||||
|
int expsize; /* character count for expstr */
|
||||||
|
int ndig; /* actual number of digits returned by cvt */
|
||||||
|
char expstr[7]; /* buffer for exponent string */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
u_long ulval; /* integer arguments %[diouxX] */
|
||||||
|
#ifdef HAS_QUAD_T
|
||||||
|
u_quad_t uqval; /* %q integers */
|
||||||
|
#endif
|
||||||
|
int base; /* base for [diouxX] conversion */
|
||||||
|
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
|
||||||
|
int fieldsz; /* field size expanded by sign, etc */
|
||||||
|
int realsz; /* field size expanded by dprec */
|
||||||
|
int size; /* size of converted field or string */
|
||||||
|
char *xdigs; /* digits for [xX] conversion */
|
||||||
|
#define NIOV 8
|
||||||
|
struct __suio uio; /* output information: summary */
|
||||||
|
struct __siov iov[NIOV];/* ... and individual io vectors */
|
||||||
|
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
|
||||||
|
char ox[2]; /* space for 0x hex-prefix */
|
||||||
|
} vfprintfData_t;
|
||||||
|
|
||||||
|
#define fmt (vdata->fmt)
|
||||||
|
#define ch (vdata->ch)
|
||||||
|
#define n (vdata->n)
|
||||||
|
#define cp (vdata->cp)
|
||||||
|
#define iovp (vdata->iovp)
|
||||||
|
#define flags (vdata->flags)
|
||||||
|
#define ret (vdata->ret)
|
||||||
|
#define width (vdata->width)
|
||||||
|
#define prec (vdata->prec)
|
||||||
|
#define sign (vdata->sign)
|
||||||
|
#define softsign (vdata->softsign)
|
||||||
|
#define _double (vdata->_double)
|
||||||
|
#define expt (vdata->expt)
|
||||||
|
#define expsize (vdata->expsize)
|
||||||
|
#define ndig (vdata->ndig)
|
||||||
|
#define expstr (vdata->expstr)
|
||||||
|
#define ulval (vdata->ulval)
|
||||||
|
#define uqval (vdata->uqval)
|
||||||
|
#define base (vdata->base)
|
||||||
|
#define dprec (vdata->dprec)
|
||||||
|
#define fieldsz (vdata->fieldsz)
|
||||||
|
#define realsz (vdata->realsz)
|
||||||
|
#define size (vdata->size)
|
||||||
|
#define xdigs (vdata->xdigs)
|
||||||
|
#define uio (vdata->uio)
|
||||||
|
#define iov (vdata->iov)
|
||||||
|
#define buf (vdata->buf)
|
||||||
|
#define ox (vdata->ox)
|
||||||
|
|
||||||
|
#endif /* __ORCAC__ */
|
||||||
|
|
||||||
int
|
int
|
||||||
vfprintf(FILE *fp, const char *fmt0, va_list ap)
|
vfprintf(FILE *fp, const char *fmt0, va_list ap)
|
||||||
{
|
{
|
||||||
|
#ifdef __ORCAC__
|
||||||
|
vfprintfData_t *vdata;
|
||||||
|
int retval;
|
||||||
|
#else /* ! __ORCAC__ */
|
||||||
register char *fmt; /* format string */
|
register char *fmt; /* format string */
|
||||||
register int ch; /* character from fmt */
|
register int ch; /* character from fmt */
|
||||||
register int n; /* handy integer (short term usage) */
|
register int n; /* handy integer (short term usage) */
|
||||||
@ -335,6 +402,7 @@ vfprintf(FILE *fp, const char *fmt0, va_list ap)
|
|||||||
struct __siov iov[NIOV];/* ... and individual io vectors */
|
struct __siov iov[NIOV];/* ... and individual io vectors */
|
||||||
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
|
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
|
||||||
char ox[2]; /* space for 0x hex-prefix */
|
char ox[2]; /* space for 0x hex-prefix */
|
||||||
|
#endif /* ! __ORCAC__ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Choose PADSIZE to trade efficiency vs. size. If larger printf
|
* Choose PADSIZE to trade efficiency vs. size. If larger printf
|
||||||
@ -347,6 +415,12 @@ vfprintf(FILE *fp, const char *fmt0, va_list ap)
|
|||||||
static char zeroes[PADSIZE] =
|
static char zeroes[PADSIZE] =
|
||||||
{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
|
{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
|
||||||
|
|
||||||
|
#ifdef __ORCAC__
|
||||||
|
if ((vdata = malloc(sizeof(vfprintfData_t))) == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BEWARE, these `goto error' on error, and PAD uses `n'.
|
* BEWARE, these `goto error' on error, and PAD uses `n'.
|
||||||
*/
|
*/
|
||||||
@ -391,13 +465,24 @@ vfprintf(FILE *fp, const char *fmt0, va_list ap)
|
|||||||
(u_long)va_arg(ap, u_int))
|
(u_long)va_arg(ap, u_int))
|
||||||
|
|
||||||
/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
|
/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
|
||||||
if (cantwrite(fp))
|
if (cantwrite(fp)) {
|
||||||
|
#ifdef __ORCAC__
|
||||||
|
free(vdata);
|
||||||
|
#endif
|
||||||
return (EOF);
|
return (EOF);
|
||||||
|
}
|
||||||
|
|
||||||
/* optimise fprintf(stderr) (and other unbuffered Unix files) */
|
/* optimise fprintf(stderr) (and other unbuffered Unix files) */
|
||||||
if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
|
if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
|
||||||
fp->_file >= 0)
|
fp->_file >= 0) {
|
||||||
|
#ifdef __ORCAC__
|
||||||
|
retval = __sbprintf(fp, fmt0, ap);
|
||||||
|
free(vdata);
|
||||||
|
return retval;
|
||||||
|
#else
|
||||||
return (__sbprintf(fp, fmt0, ap));
|
return (__sbprintf(fp, fmt0, ap));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
fmt = (char *)fmt0;
|
fmt = (char *)fmt0;
|
||||||
uio.uio_iov = iovp = iov;
|
uio.uio_iov = iovp = iov;
|
||||||
@ -834,10 +919,47 @@ number: if ((dprec = prec) >= 0)
|
|||||||
done:
|
done:
|
||||||
FLUSH();
|
FLUSH();
|
||||||
error:
|
error:
|
||||||
|
#ifdef __ORCAC__
|
||||||
|
retval = __sferror(fp) ? EOF : ret;
|
||||||
|
free(vdata);
|
||||||
|
return retval;
|
||||||
|
#else
|
||||||
return (__sferror(fp) ? EOF : ret);
|
return (__sferror(fp) ? EOF : ret);
|
||||||
|
#endif
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __ORCAC__
|
||||||
|
#undef fmt
|
||||||
|
#undef ch
|
||||||
|
#undef n
|
||||||
|
#undef cp
|
||||||
|
#undef iovp
|
||||||
|
#undef flags
|
||||||
|
#undef ret
|
||||||
|
#undef width
|
||||||
|
#undef prec
|
||||||
|
#undef sign
|
||||||
|
#undef softsign
|
||||||
|
#undef _double
|
||||||
|
#undef expt
|
||||||
|
#undef expsize
|
||||||
|
#undef ndig
|
||||||
|
#undef expstr
|
||||||
|
#undef ulval
|
||||||
|
#undef uqval
|
||||||
|
#undef base
|
||||||
|
#undef dprec
|
||||||
|
#undef fieldsz
|
||||||
|
#undef realsz
|
||||||
|
#undef size
|
||||||
|
#undef xdigs
|
||||||
|
#undef uio
|
||||||
|
#undef iov
|
||||||
|
#undef buf
|
||||||
|
#undef ox
|
||||||
|
#endif /* __ORCAC__ */
|
||||||
|
|
||||||
#ifdef FLOATING_POINT
|
#ifdef FLOATING_POINT
|
||||||
|
|
||||||
extern char *__dtoa __P((double, int, int, int *, int *, char **));
|
extern char *__dtoa __P((double, int, int, int *, int *, char **));
|
||||||
@ -888,7 +1010,10 @@ static int
|
|||||||
exponent(char *p0, int exp, int fmtch)
|
exponent(char *p0, int exp, int fmtch)
|
||||||
{
|
{
|
||||||
register char *p, *t;
|
register char *p, *t;
|
||||||
STATIC char expbuf[MAXEXP];
|
#ifdef __ORCAC__
|
||||||
|
static
|
||||||
|
#endif
|
||||||
|
char expbuf[MAXEXP];
|
||||||
|
|
||||||
p = p0;
|
p = p0;
|
||||||
*p++ = fmtch;
|
*p++ = fmtch;
|
||||||
|
Loading…
Reference in New Issue
Block a user