9os

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 0507169ee281ff85788004c7fd01de9e03541ce1
parent 4fcd2f187ce6d417de018324bd6463dd264cfb0c
Author: Roberto Vargas <roberto.vargas@arm.com>
Date:   Wed,  7 Nov 2018 16:15:02 +0000

[libc] Fix line buffering mode in FILEs

Change-Id: Ie31ea523301c4fca584aff08737e53e8bd638175

Diffstat:
Minclude/stdio.h | 4++--
Msrc/libc/libc.h | 5++++-
Msrc/libc/stdio/Makefile | 3++-
Msrc/libc/stdio/__getc.c | 13+++----------
Rsrc/libc/stdio/stdio.c -> src/libc/stdio/__iob.c | 0
Msrc/libc/stdio/__putc.c | 18++++++------------
Asrc/libc/stdio/_allocbuf.c | 21+++++++++++++++++++++
Msrc/libc/stdio/_flsbuf.c | 12+++++++-----
Msrc/libc/stdio/fclose.c | 2--
Msrc/libc/stdio/fseek.c | 2--
Msrc/libc/stdio/setvbuf.c | 22++++++++++++++--------
Msrc/libc/stdio/vprintf.c | 2+-
12 files changed, 60 insertions(+), 44 deletions(-)

diff --git a/include/stdio.h b/include/stdio.h @@ -110,8 +110,8 @@ extern void perror(const char *s); extern int __getc(FILE *fp); extern int __putc(int, FILE *fp); -#define getc(fp) ((fp)->rp >= (fp)->wp ? __getc(fp) : *(fp)->rp++) -#define putc(c, fp) ((fp)->wp >= (fp)->rp ? __putc(c,fp) : (*(fp)->wp++ = c)) +#define getc(fp) ((fp)->rp >= (fp)->wp ? __getc(fp) : *(fp)->rp++) +#define putc(c, fp) ((fp)->wp >= (fp)->rp ? __putc(c,fp) : (*(fp)->wp++ = c)) #define ferror(fp) ((fp)->flags & _IOERR) #define feof(fp) ((fp)->flags & _IOEOF) diff --git a/src/libc/libc.h b/src/libc/libc.h @@ -33,7 +33,10 @@ struct tm; extern struct tzone *_tzone(struct tm *tm); extern int _daysyear(int year); extern int _newyear(int year); - extern void *_getheap(void); +#ifdef FILE +extern int _flsbuf(FILE *fp); +extern void _allocbuf(FILE *fp); +#endif extern int _daysmon[12]; diff --git a/src/libc/stdio/Makefile b/src/libc/stdio/Makefile @@ -36,11 +36,12 @@ OBJS = __getc.o\ setvbuf.o\ snprintf.o\ sprintf.o\ - stdio.o\ + __iob.o\ tmpnam.o\ vfprintf.o\ vsnprintf.o\ vsprintf.o\ vprintf.o\ + _allocbuf.o\ all: $(OBJS) diff --git a/src/libc/stdio/__getc.c b/src/libc/stdio/__getc.c @@ -1,8 +1,8 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include "../libc.h" #include "../syscall.h" -#undef getc int __getc(FILE *fp) @@ -23,15 +23,8 @@ __getc(FILE *fp) return EOF; } - if (fp->buf == NULL) { - if ((fp->buf = malloc(BUFSIZ)) == NULL) { - errno = ENOMEM; - return EOF; - } - fp->len = BUFSIZ; - fp->flags |= _IOALLOC; - fp->lp = fp->rp = fp->wp = fp->buf; - } + if (fp->buf == NULL && _allocbuf(fp)) + return EOF; if ((cnt = _read(fp->fd, fp->buf, fp->len)) <= 0) { fp->flags |= (cnt == 0) ? _IOEOF : _IOERR; diff --git a/src/libc/stdio/stdio.c b/src/libc/stdio/__iob.c diff --git a/src/libc/stdio/__putc.c b/src/libc/stdio/__putc.c @@ -1,8 +1,7 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> - -extern int _flsbuf(FILE *fp); +#include "../libc.h" int fflush(FILE *fp) @@ -45,14 +44,8 @@ __putc(int ch, FILE *fp) return EOF; } - if (fp->buf == NULL) { - if ((fp->buf = malloc(BUFSIZ)) == NULL) { - errno = ENOMEM; + if (fp->buf == NULL && _allocbuf(fp)) return EOF; - } - fp->flags |= _IOALLOC; - fp->rp = fp->wp = fp->lp = fp->buf; - } if (first) { if (atexit(cleanup)) { @@ -64,15 +57,16 @@ __putc(int ch, FILE *fp) } if (fp->flags & _IOLBF) { - if (fp->lp == fp->rp && _flsbuf(fp)) + if (fp->wp == fp->lp && _flsbuf(fp)) return EOF; - *fp->lp++ = ch; + *fp->wp++ = ch; if (ch == '\n' && _flsbuf(fp)) return EOF; } else if (fp->flags & _IOFBF) { - if (fp->wp == fp->rp && _flsbuf(fp)) + if (_flsbuf(fp)) return EOF; *fp->wp++ = ch; + fp->rp = fp->buf + fp->len; } else { *fp->wp++ = ch; if (_flsbuf(fp)) diff --git a/src/libc/stdio/_allocbuf.c b/src/libc/stdio/_allocbuf.c @@ -0,0 +1,21 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include "../libc.h" + +int +_allocbuf(FILE *fp) +{ + char *bp; + + if ((bp = malloc(BUFSIZ)) == NULL) { + fp->flags |= _IOERR; + errno = ENOMEM; + return EOF; + } + fp->len = BUFSIZ; + fp->rp = fp->wp = fp->buf = bp; + fp->lp = bp + BUFSIZ; + + return 0; +} diff --git a/src/libc/stdio/_flsbuf.c b/src/libc/stdio/_flsbuf.c @@ -1,21 +1,23 @@ #include <errno.h> #include <stdio.h> + +#include "../libc.h" #include "../syscall.h" int _flsbuf(FILE *fp) { - unsigned char *p; size_t cnt; - p = (fp->flags & _IOLBF) ? fp->lp : fp->wp; - cnt = p - fp->buf; + if (fp->flags&_IOREAD) + return 0; - if (_write(fp->fd, fp->buf, cnt) != cnt) { + cnt = fp->wp - fp->buf; + if (cnt > 0 && _write(fp->fd, fp->buf, cnt) != cnt) { fp->flags |= _IOERR; return EOF; } - fp->lp = fp->rp = fp->wp = fp->buf; + fp->wp = fp->buf; return 0; } diff --git a/src/libc/stdio/fclose.c b/src/libc/stdio/fclose.c @@ -3,8 +3,6 @@ #include "../syscall.h" #undef fclose -extern int _flsbuf(FILE *fp); - int fclose(FILE *fp) { diff --git a/src/libc/stdio/fseek.c b/src/libc/stdio/fseek.c @@ -2,8 +2,6 @@ #include "../syscall.h" #undef fseek -extern int _flsbuf(FILE *fp); - int fseek(FILE *fp, long off, int whence) { diff --git a/src/libc/stdio/setvbuf.c b/src/libc/stdio/setvbuf.c @@ -3,23 +3,29 @@ #include <stdlib.h> #undef setvbuf -extern int _flsbuf(FILE *fp); - int setvbuf(FILE * restrict fp, char * restrict buf, int mode, size_t size) { int flags; + char *p; + size_t l; if (_flsbuf(fp) == EOF) return EOF; + if (buf) + p = buf, l = size; + else + p = fp->buf, l = fp->len; + switch (mode) { case _IONBF: - size = sizeof(fp->unbuf); - buf = fp->unbuf; - break; + l = sizeof(fp->unbuf); + p = fp->unbuf; case _IOLBF: case _IOFBF: + fp->rp = fp->wp = p; + fp->lp = p + l; break; default: errno = EINVAL; @@ -27,13 +33,13 @@ setvbuf(FILE * restrict fp, char * restrict buf, int mode, size_t size) } flags = fp->flags; - if (buf && (flags & _IOALLOC)) { + if (flags&_IOALLOC && (buf || mode == _IONBF)) { free(fp->buf); - fp->buf = buf; - fp->len = size; flags &= ~_IOALLOC; } + fp->buf = p; + fp->len = l; flags &= ~(_IONBF | _IOLBF | _IOFBF); flags |= mode; fp->flags = flags; diff --git a/src/libc/stdio/vprintf.c b/src/libc/stdio/vprintf.c @@ -7,5 +7,5 @@ vprintf(const char *fmt, va_list ap) va_list ap2; va_copy(ap2, ap); - return vfprintf(stdin, fmt, ap2); + return vfprintf(stdout, fmt, ap2); }