Fixed flushbuf() so that it works with POSIX conformant Unix versions

This commit is contained in:
ceriel 1991-06-10 17:07:18 +00:00
parent e6a017827e
commit 9e9e7db6b4
6 changed files with 124 additions and 45 deletions

View file

@ -27,7 +27,6 @@ fseek.c
fsetpos.c
ftell.c
fwrite.c
gcvt.c
getc.c
getchar.c
gets.c

View file

@ -44,7 +44,6 @@ ferror.c
fileno.c
fltpr.c
ecvt.c
gcvt.c
fillbuf.c
fclose.c
flushbuf.c

View file

@ -111,38 +111,6 @@ o_print(va_list *ap, int flags, char *s, char c, int precision, int is_signed)
return s;
}
#ifndef NOFLOAT
static char *
f_print(va_list *ap, int flags, char *s, char c, int precision)
{
register char *old_s = s;
long double ld_val;
if (flags & FL_LONGDOUBLE) ld_val = va_arg(*ap, long double);
else ld_val = (long double) va_arg(*ap, double);
switch(c) {
case 'f':
s = _pfloat(ld_val, s, precision, flags);
break;
case 'e':
case 'E':
s = _pscien(ld_val, s, precision , flags);
break;
case 'g':
case 'G':
s = _gcvt(ld_val, precision, s, flags);
s += strlen(s);
break;
}
if ( c == 'E' || c == 'G') {
while (*old_s && *old_s != 'e') old_s++;
if (*old_s == 'e') *old_s = 'E';
}
return s;
}
#endif /* NOFLOAT */
int
_doprnt(register const char *fmt, va_list ap, FILE *stream)
{
@ -279,7 +247,7 @@ _doprnt(register const char *fmt, va_list ap, FILE *stream)
precision = sizeof(buf) - 1;
flags |= FL_SIGNEDCONV;
s = f_print(&ap, flags, s, c, precision);
s = _f_print(&ap, flags, s, c, precision);
break;
#endif /* NOFLOAT */
case 'r':

View file

@ -1,12 +1,14 @@
/*
* floatpr.c - print floating point numbers
* fltpr.c - print floating point numbers
*/
/* $Header$ */
#ifndef NOFLOAT
#include <string.h>
#include <stdarg.h>
#include "loc_incl.h"
char *
static char *
_pfloat(long double r, register char *s, int n, int flags)
{
register char *s1;
@ -39,7 +41,7 @@ _pfloat(long double r, register char *s, int n, int flags)
return s;
}
char *
static char *
_pscien(long double r, register char *s, int n, int flags)
{
int sign, dp;
@ -74,4 +76,103 @@ _pscien(long double r, register char *s, int n, int flags)
*s++ = '0' + (dp%10);
return s;
}
#define NDIGINEXP(exp) (((exp) >= 100 || (exp) <= -100) ? 3 : 2)
#define LOW_EXP -4
#define USE_EXP(exp, ndigits) (((exp) < LOW_EXP + 1) || (exp >= ndigits + 1))
static char *
_gcvt(long double value, int ndigit, char *s, int flags)
{
int sign, dp;
register char *s1, *s2;
register int i;
register int nndigit = ndigit;
s1 = _ecvt(value, ndigit, &dp, &sign);
s2 = s;
if (sign) *s2++ = '-';
else if (flags & FL_SIGN)
*s2++ = '+';
else if (flags & FL_SPACE)
*s2++ = ' ';
if (!(flags & FL_ALT))
for (i = nndigit - 1; i > 0 && s1[i] == '0'; i--)
nndigit--;
if (USE_EXP(dp,ndigit)) {
/* Use E format */
dp--;
*s2++ = *s1++;
if ((nndigit > 1) || (flags & FL_ALT)) *s2++ = '.';
while (--nndigit > 0) *s2++ = *s1++;
*s2++ = 'e';
if (dp < 0) {
*s2++ = '-';
dp = -dp;
}
else *s2++ = '+';
s2 += NDIGINEXP(dp);
*s2 = 0;
for (i = NDIGINEXP(dp); i > 0; i--) {
*--s2 = dp % 10 + '0';
dp /= 10;
}
return s;
}
/* Use f format */
if (dp <= 0) {
if (*s1 != '0') {
/* otherwise the whole number is 0 */
*s2++ = '0';
*s2++ = '.';
}
while (dp < 0) {
dp++;
*s2++ = '0';
}
}
for (i = 1; i <= nndigit; i++) {
*s2++ = *s1++;
if (i == dp) *s2++ = '.';
}
if (i <= dp) {
while (i++ <= dp) *s2++ = '0';
*s2++ = '.';
}
if ((s2[-1]=='.') && !(flags & FL_ALT)) s2--;
*s2 = '\0';
return s;
}
char *
_f_print(va_list *ap, int flags, char *s, char c, int precision)
{
register char *old_s = s;
long double ld_val;
if (flags & FL_LONGDOUBLE) ld_val = va_arg(*ap, long double);
else ld_val = (long double) va_arg(*ap, double);
switch(c) {
case 'f':
s = _pfloat(ld_val, s, precision, flags);
break;
case 'e':
case 'E':
s = _pscien(ld_val, s, precision , flags);
break;
case 'g':
case 'G':
s = _gcvt(ld_val, precision, s, flags);
s += strlen(s);
break;
}
if ( c == 'E' || c == 'G') {
while (*old_s && *old_s != 'e') old_s++;
if (*old_s == 'e') *old_s = 'E';
}
return s;
}
#endif /* NOFLOAT */

View file

@ -14,6 +14,21 @@ int _write(int d, const char *buf, int nbytes);
int _isatty(int d);
extern void (*_clean)(void);
static int
do_write(int d, char *buf, int nbytes)
{
int c;
/* POSIX actually allows write() to return a positive value less
than nbytes, so loop ...
*/
while ((c = _write(d, buf, nbytes)) > 0 && c < nbytes) {
nbytes -= c;
buf += c;
}
return c > 0;
}
int
__flushbuf(int c, FILE * stream)
{
@ -75,8 +90,8 @@ __flushbuf(int c, FILE * stream)
return EOF;
}
}
if (_write(fileno(stream), (char *)stream->_buf,
-stream->_count) != -stream->_count) {
if (! do_write(fileno(stream), (char *)stream->_buf,
-stream->_count)) {
stream->_flags |= _IOERR;
return EOF;
} else {
@ -97,8 +112,7 @@ __flushbuf(int c, FILE * stream)
return EOF;
}
}
if (_write(fileno(stream), (char *)stream->_buf, count)
!= count) {
if (! do_write(fileno(stream), (char *)stream->_buf, count)) {
*(stream->_buf) = c;
stream->_flags |= _IOERR;
return EOF;

View file

@ -12,17 +12,15 @@
int _doprnt(const char *format, va_list ap, FILE *stream);
int _doscan(FILE * stream, const char *format, va_list ap);
char *_i_compute(unsigned long val, int base, char *s, int nrdigits);
char *_f_print(va_list *ap, int flags, char *s, char c, int precision);
void __cleanup(void);
FILE *popen(const char *command, const char *type);
FILE *fdopen(int fd, const char *mode);
#ifndef NOFLOAT
char *_pfloat(long double r, register char *s, int n, int flags);
char *_pscien(long double r, register char *s, int n, int flags);
char *_ecvt(long double value, int ndigit, int *decpt, int *sign);
char *_fcvt(long double value, int ndigit, int *decpt, int *sign);
char *_gcvt(long double value, int ndigit, char *s, int flags);
#endif /* NOFLOAT */
#define FL_LJUST 0x0001 /* left-justify field */