mirror of
https://git.planet-casio.com/Vhex-Kernel-Core/fxlibc.git
synced 2024-12-28 04:23:38 +01:00
stdio: FILE barebones with buffering model (WIP)
This commit is contained in:
parent
b53078776d
commit
51528170bb
11 changed files with 349 additions and 107 deletions
|
@ -120,6 +120,8 @@ set(SOURCES
|
|||
# stdio
|
||||
src/libc/stdio/asprintf.c
|
||||
src/libc/stdio/dprintf.c
|
||||
src/libc/stdio/fflush.c
|
||||
src/libc/stdio/fileutil.c
|
||||
src/libc/stdio/fprintf.c
|
||||
src/libc/stdio/printf.c
|
||||
src/libc/stdio/printf/format_fixed.c
|
||||
|
@ -129,6 +131,9 @@ set(SOURCES
|
|||
src/libc/stdio/printf/util.c
|
||||
src/libc/stdio/putc.c
|
||||
src/libc/stdio/puts.c
|
||||
src/libc/stdio/remove.c
|
||||
src/libc/stdio/setbuf.c
|
||||
src/libc/stdio/setvbuf.c
|
||||
src/libc/stdio/snprintf.c
|
||||
src/libc/stdio/sprintf.c
|
||||
src/libc/stdio/vasprintf.c
|
||||
|
|
213
STATUS
213
STATUS
|
@ -31,51 +31,49 @@ TODO: Function/symbol/macro is not implemented/defined
|
|||
BDEPS(...): Function/symbol/macro needs ... to build
|
||||
LDEPS(...): Function/symbol/macro needs ... to link
|
||||
TEST: Function/symbol/macro needs to be tested
|
||||
DONE: Function/symbol/macro is defined, builds, links, and is tested
|
||||
-: Function/symbol/macro is defined, builds, links, and is tested
|
||||
|
||||
7.2 <assert.h>
|
||||
! 7.2.1 assert: LDEPS(fprintf,stderr)
|
||||
7.2.1 assert LDEPS(fprintf,stderr)
|
||||
|
||||
7.3 <complex.h> => OpenLibm
|
||||
|
||||
7.4 <ctype.h>
|
||||
7.4.1 is*: DONE
|
||||
7.4.2 to*: DONE
|
||||
7.4.1 is* -
|
||||
7.4.2 to* -
|
||||
|
||||
7.5 <errno.h>
|
||||
7.5.2 EDOM EILSEQ ERANGE: DONE
|
||||
7.5.2 EDOM, EILSEQ, ERANGE -
|
||||
|
||||
7.6 <fenv.h> => OpenLibm
|
||||
|
||||
7.7 <float.h> => GCC
|
||||
|
||||
7.8 <inttypes.h>
|
||||
! 7.8.1 PRI* macros: LDEPS(*printf)
|
||||
! 7.8.1 SCN* macros: LDEPS(*scanf)
|
||||
7.8.2.1 imaxabs: DONE
|
||||
7.8.2.2 imaxdiv: DONE
|
||||
7.8.2.3 strtoimax strtoumax: DONE
|
||||
! 7.8.2.4 wcstoimax wcstoumax: TODO
|
||||
7.8.1 PRI* macros -
|
||||
7.8.1 SCN* macros -
|
||||
7.8.2.1 imaxabs -
|
||||
7.8.2.2 imaxdiv -
|
||||
7.8.2.3 strtoimax, strtoumax -
|
||||
7.8.2.4 wcstoimax, wcstoumax TODO
|
||||
|
||||
7.9 <iso646.h> => GCC
|
||||
|
||||
7.10 <limits.h> => GCC
|
||||
|
||||
7.11 <locale.h>
|
||||
! 7.11.1 setlocale: TEST
|
||||
! 7.11.2 localeconv: TEST
|
||||
7.11.1 setlocale TEST
|
||||
7.11.2 localeconv TEST
|
||||
|
||||
7.12 <math.h> => OpenLibm
|
||||
|
||||
7.13 <setjmp.h>
|
||||
7.13.1 setjmp: DONE
|
||||
7.13.2 longjmp: DONE
|
||||
7.13.1 setjmp -
|
||||
7.13.2 longjmp -
|
||||
|
||||
7.14 <signal.h>
|
||||
7.14 sig_atomic_t SIG_DFL SIG_ERR SIG_IGN: DONE
|
||||
7.14 SIGABRT SIGFPE SIGILL SIGINT SIGSEGV SIGTERM: DONE
|
||||
7.14.1.1 signal: DONE
|
||||
7.14.1.2 raise: DONE
|
||||
7.14.1.1 signal -
|
||||
7.14.1.2 raise -
|
||||
|
||||
7.15 <stdarg.h> => GCC
|
||||
|
||||
|
@ -86,93 +84,114 @@ DONE: Function/symbol/macro is defined, builds, links, and is tested
|
|||
7.18 <stdint.h> => GCC
|
||||
|
||||
7.19 <stdio.h>
|
||||
7.19.1 Introduction: TEST
|
||||
TODO: Handle wide-oriented streams? (see notes)
|
||||
! 7.19.4 Operations on files: TODO
|
||||
! 7.19.5 File access functions: TODO
|
||||
! 7.19.6 Formatted input/output functions: TODO
|
||||
! 7.19.7 Character input/output functions: TODO
|
||||
! 7.19.8 Direct input/output functions: TODO
|
||||
! 7.19.9 File positioning functions: TODO
|
||||
! 7.19.10 Error-handling functions: TODO
|
||||
7.19.1 Introduction TEST
|
||||
No wide-oriented streams (see notes)
|
||||
7.19.4.1 remove TEST
|
||||
7.19.4.2 rename TODO
|
||||
7.19.4.3 tmpfile TODO
|
||||
7.19.4.4 tmpnam TODO
|
||||
7.19.5.1 fclose TODO
|
||||
7.19.5.2 fflush TODO
|
||||
7.19.5.3 fopen TODO
|
||||
7.19.5.4 freopen TODO
|
||||
7.19.5.5 setbuf TODO
|
||||
7.19.5.6 setvbuf TODO
|
||||
7.19.6.1 fprintf LDEPS(fwrite)
|
||||
7.19.6.2 fscanf TODO
|
||||
7.19.6.3 printf LDEPS(fwrite, stdout)
|
||||
7.19.6.4 scanf TODO
|
||||
7.19.6.5 snprintf -
|
||||
7.19.6.6 sprintf -
|
||||
7.19.6.7 sscanf TODO
|
||||
7.19.6.8 vfprintf LDEPS(fwrite)
|
||||
7.19.6.9 vfscanf TODO
|
||||
7.19.6.10 vprintf LDEPS(fwrite, stdout)
|
||||
7.19.6.11 vscanf TODO
|
||||
7.19.6.12 vsnprintf -
|
||||
7.19.6.13 vsprintf -
|
||||
7.19.6.14 vsscanf TODO
|
||||
(EXT) asprintf -
|
||||
(EXT) vasprintf -
|
||||
(EXT) dprintf TEST
|
||||
(EXT) vdprintf TEST
|
||||
7.19.7 Character input/output TODO
|
||||
7.19.8 Direct input/output TODO
|
||||
7.19.9 File positioning TODO
|
||||
7.19.10 Error-handling TODO
|
||||
|
||||
7.20 <stdlib.h>
|
||||
7.20 RAND_MAX: DONE
|
||||
! 7.20 MB_CUR_MAX: TODO
|
||||
7.20.1.1 atof: DONE
|
||||
7.20.1.2 atoi, atol, atoll: DONE
|
||||
7.20.1.3 strtod, strtof, strtold: DONE
|
||||
7.20.1.4 strtol, strtoul, strtoll, strtoull: DONE
|
||||
7.20.2.1 rand: DONE
|
||||
7.20.2.2 srand: DONE
|
||||
7.20.3.1 calloc: DONE
|
||||
7.20.3.2 free: DONE (at least gint)
|
||||
7.20.3.3 malloc: DONE (at least gint)
|
||||
7.20.3.4 realloc: DONE (at least gint)
|
||||
7.20.4.1 abort: DONE
|
||||
! 7.20.4.2 atexit: TODO
|
||||
7.20.4.3 exit: DONE (missing stream flushing/closing/etc)
|
||||
7.20.4.4 _Exit: DONE (gint only)
|
||||
! 7.20.4.5 getenv: TODO
|
||||
! 7.20.4.6 system: TODO
|
||||
! 7.20.5.1 bsearch: TODO
|
||||
! 7.20.5.2 qsort: TEST
|
||||
7.20.6.1 abs, labs, llabs: DONE
|
||||
7.20.6.2 div, ldiv, lldiv: DONE
|
||||
! 7.20.7 Multibyte/wide character conversion functions: TODO
|
||||
! 7.20.8 Multibyte/wide string conversion functions: TODO
|
||||
7.20 MB_CUR_MAX TODO
|
||||
7.20.1.1 atof -
|
||||
7.20.1.2 atoi, atol, atoll -
|
||||
7.20.1.3 strtod, strtof, strtold -
|
||||
7.20.1.4 strtol, strtoul -
|
||||
7.20.1.4 strtoll, strtoull -
|
||||
7.20.2.1 rand -
|
||||
7.20.2.2 srand -
|
||||
7.20.3.1 calloc -
|
||||
7.20.3.2 free - (gint)
|
||||
7.20.3.3 malloc - (gint)
|
||||
7.20.3.4 realloc - (gint)
|
||||
7.20.4.1 abort - (stream flushing/closing/etc?)
|
||||
7.20.4.2 atexit TODO
|
||||
7.20.4.3 exit - (stream flushing/closing/etc?)
|
||||
7.20.4.4 _Exit - (gint)
|
||||
7.20.4.5 getenv TODO
|
||||
7.20.4.6 system TODO
|
||||
7.20.5.1 bsearch TODO
|
||||
7.20.5.2 qsort TEST
|
||||
7.20.6.1 abs, labs, llabs -
|
||||
7.20.6.2 div, ldiv, lldiv -
|
||||
7.20.7 Multibyte/wide char conv TODO
|
||||
7.20.8 Multibyte/wide string conv TODO
|
||||
|
||||
7.21 <string.h>
|
||||
7.21.2.1 memcpy: DONE
|
||||
7.21.2.2 memmove: DONE (Unoptimized: byte-by-byte)
|
||||
7.21.2.3 strcpy: DONE
|
||||
7.21.2.4 strncpy: DONE
|
||||
7.21.3.1 strcat: DONE
|
||||
7.21.3.2 strncat: DONE
|
||||
7.21.4.1 memcmp: DONE
|
||||
7.21.4.2 strcmp: DONE
|
||||
7.21.4.3 strcoll: DONE
|
||||
7.21.4.4 strncmp: DONE
|
||||
7.21.4.5 strxfrm: DONE
|
||||
7.21.5.1 memchr: DONE
|
||||
7.21.5.2 strchr: DONE
|
||||
7.21.5.3 strcspn: DONE
|
||||
7.21.5.4 strpbrk: DONE
|
||||
7.21.5.5 strrchr: DONE
|
||||
7.21.5.6 strspn: DONE
|
||||
7.21.5.7 strstr: DONE
|
||||
7.21.5.8 strtok: DONE
|
||||
7.21.6.1 memset: DONE
|
||||
7.21.6.2 strerror: DONE
|
||||
7.21.6.3 strlen: DONE
|
||||
Extensions:
|
||||
- strnlen: DONE
|
||||
- strchrnul: DONE
|
||||
- strcasestr: DONE
|
||||
- strcasecmp: DONE
|
||||
- strncasecmp: DONE
|
||||
- strdup: DONE
|
||||
- strndup: DONE
|
||||
7.21.2.1 memcpy -
|
||||
7.21.2.2 memmove - (Unoptimized: byte-by-byte)
|
||||
7.21.2.3 strcpy -
|
||||
7.21.2.4 strncpy -
|
||||
7.21.3.1 strcat -
|
||||
7.21.3.2 strncat -
|
||||
7.21.4.1 memcmp -
|
||||
7.21.4.2 strcmp -
|
||||
7.21.4.3 strcoll -
|
||||
7.21.4.4 strncmp -
|
||||
7.21.4.5 strxfrm -
|
||||
7.21.5.1 memchr -
|
||||
7.21.5.2 strchr -
|
||||
7.21.5.3 strcspn -
|
||||
7.21.5.4 strpbrk -
|
||||
7.21.5.5 strrchr -
|
||||
7.21.5.6 strspn -
|
||||
7.21.5.7 strstr -
|
||||
7.21.5.8 strtok -
|
||||
7.21.6.1 memset -
|
||||
7.21.6.2 strerror -
|
||||
7.21.6.3 strlen -
|
||||
(EXT) strnlen -
|
||||
(EXT) strchrnul -
|
||||
(EXT) strcasestr -
|
||||
(EXT) strcasecmp -
|
||||
(EXT) strncasecmp -
|
||||
(EXT) strdup -
|
||||
(EXT) strndup -
|
||||
|
||||
7.22 <tgmath.h> => GCC
|
||||
|
||||
7.23 <time.h>
|
||||
7.23.1 Components of time: DONE
|
||||
7.23.2.1 clock: DONE
|
||||
7.23.2.2 difftime: DONE
|
||||
7.23.2.3 mktime: DONE (DST flag ignored)
|
||||
7.23.2.4 time: DONE
|
||||
7.23.3.1 asctime: DONE
|
||||
7.23.3.2 ctime: DONE
|
||||
7.23.3.3 gmtime: DONE
|
||||
7.23.3.4 localtime: DONE (No timezones; same as gmtime)
|
||||
7.23.3.5 strftime: DONE (No %g/%G/%U/%V/%W; timezones %z/%Z empty)
|
||||
7.23.2.1 clock -
|
||||
7.23.2.2 difftime -
|
||||
7.23.2.3 mktime - (DST flag ignored)
|
||||
7.23.2.4 time -
|
||||
7.23.3.1 asctime -
|
||||
7.23.3.2 ctime -
|
||||
7.23.3.3 gmtime -
|
||||
7.23.3.4 localtime - (No timezones; same as gmtime)
|
||||
7.23.3.5 strftime - (No %g, %G, %U, %V, %W, %z, %Z)
|
||||
|
||||
7.24 <wchar.h>
|
||||
TODO (not a priority)
|
||||
7.24 <wchar.h> TODO (not a priority)
|
||||
|
||||
7.25 <wctype.h>
|
||||
TODO (not a priority)
|
||||
7.25 <wctype.h> TODO (not a priority)
|
||||
|
||||
# Supporting locales
|
||||
|
||||
|
@ -188,7 +207,7 @@ What if we wanted to support more locales?
|
|||
|
||||
# Supporting text and binary files (newline translation)
|
||||
|
||||
Because of 7.19.2%1,223 we don't need to support newline translation.
|
||||
Because of 7.19.2§1.223 we don't need to support newline translation.
|
||||
|
||||
# Support wide-oriented streams
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ extern "C" {
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Hide by default in C++ (7.8.1§1.181) */
|
||||
/* Hide by default in C++ (7.8.1§1.182) */
|
||||
#if !defined __cplusplus || defined __STDC_FORMAT_MACROS
|
||||
|
||||
/* Printing signed fixed-width types, decimal */
|
||||
|
|
|
@ -20,8 +20,7 @@ typedef size_t fpos_t;
|
|||
#define _IONBF 2
|
||||
|
||||
/* Some buffer size for file buffering. */
|
||||
/* TODO: We might want a larger BUFSIZ than 256 on fx-CG 50. */
|
||||
#define BUFSIZ 256
|
||||
#define BUFSIZ 512
|
||||
|
||||
/* End-of-file marker. */
|
||||
#define EOF ((int)(-1))
|
||||
|
@ -55,6 +54,28 @@ extern FILE *stderr;
|
|||
#define stdout stdout
|
||||
#define stderr stderr
|
||||
|
||||
/*
|
||||
** Operations on files.
|
||||
*/
|
||||
|
||||
/* Remove a file from the filesystem.
|
||||
In gint, the file must not be open (open files' names are not tracked). */
|
||||
extern int remove(char const *__filename);
|
||||
|
||||
/*
|
||||
** File access functions.
|
||||
*/
|
||||
|
||||
/* Flush any written data in the FILE's internal buffer. */
|
||||
extern int fflush(FILE *__fp);
|
||||
|
||||
/* Use __buf as a buffer (of size BUFSIZ) for access to __fp. */
|
||||
extern void setbuf(FILE * __restrict__ __fp, char * __restrict__ __buf);
|
||||
|
||||
/* Changer the buffering mode and buffer address for __fp. */
|
||||
extern int setvbuf(FILE * __restrict__ __fp, char * __restrict__ __buf,
|
||||
int __mode, size_t __size);
|
||||
|
||||
/*
|
||||
** Formatted input/output functions.
|
||||
**
|
||||
|
|
|
@ -2,16 +2,77 @@
|
|||
# define __BITS_TYPES_FILE_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define __FILE_BUF_READ 0
|
||||
#define __FILE_BUF_WRITE 1
|
||||
|
||||
/* The FILE structure is mostly a buffer around kernel-level I/O. Most of the
|
||||
work is maintaining that buffer to provide the basic fgetc()/fputc()
|
||||
functions, then everything else is built on top of the abstracted stream.
|
||||
|
||||
The buffer of a FILE can either be in reading or writing mode. When in
|
||||
reading mode, the buffer contains pre-fetched data from a previous read that
|
||||
hasn't yet been requested by the user. When in writing mode, the buffer
|
||||
contains data written by the user which hasn't yet been sent to the kernel.
|
||||
|
||||
The buffer has the following structure:
|
||||
|
||||
0 bufpos bufread bufsize
|
||||
+--------+---------+---------+
|
||||
|xxxxxxxx|rrrrrrrrr|uuuuuuuuu| (When reading)
|
||||
+--------+---------+---------+
|
||||
|wwwwwwww|uuuuuuuuuuuuuuuuuuu| (When writing)
|
||||
+--------+-------------------+
|
||||
|
||||
x: Data read from file descriptor and returned to user
|
||||
r: Data read from file descriptor not yet returned to user
|
||||
w: Data written by user not yet sent to file descriptor
|
||||
u: Undefined
|
||||
|
||||
In reading mode, the region [0..bufread) contains data obtained from the
|
||||
file. bufpos marks how much has been read, in the sense that [0..bufpos) has
|
||||
already been returned to the user while [bufpos..bufread) has not. The offset
|
||||
on the underlying file descriptor sits at bufread, so the position reported
|
||||
by ftell() is fdpos - bufread + bufpos. The rest of the buffer is undefined.
|
||||
|
||||
In writing mode, the region [0..bufpos) contains data received through API
|
||||
but not yet written to the file descriptor. ftell() reports fdpos + bufpos.
|
||||
The rest of the buffer is undefined. */
|
||||
typedef struct {
|
||||
/* BFile handler */
|
||||
/* File descriptor */
|
||||
int fd;
|
||||
/* Current position in file */
|
||||
size_t pos;
|
||||
/* Buffering mode */
|
||||
// TODO
|
||||
/* Opening mode */
|
||||
// TODO
|
||||
/* Current position in file, as tracked by the file descriptor (ie. not
|
||||
accounting for buffer operations) */
|
||||
size_t fdpos;
|
||||
|
||||
/* Pointer to buffer (NULL if _IONBF) */
|
||||
char *buf;
|
||||
/* Current position in buffer, water mark of read data in buffer, and
|
||||
buffer size; see header comment for details */
|
||||
size_t bufpos;
|
||||
size_t bufread;
|
||||
size_t bufsize;
|
||||
/* Buffering mode; one of _IOFBF, _IOLBF, or _IONBF */
|
||||
uint8_t bufmode :2;
|
||||
/* We own the buffer and it needs to be freed */
|
||||
uint8_t bufowned :1;
|
||||
/* __FILE_BUF_READ if the buffer is in reading mode
|
||||
__FILE_BUF_WRITE if it's in writing mode
|
||||
This mode can only be changed when bufpos=0, ie. just after fflush(). */
|
||||
uint8_t bufdir :1;
|
||||
|
||||
/* Opening flags */
|
||||
uint8_t readable :1;
|
||||
uint8_t writable :1;
|
||||
uint8_t append :1;
|
||||
/* Non-zero if text mode, zero if binary mode */
|
||||
uint8_t text :1;
|
||||
/* EOF indicator */
|
||||
uint8_t eof :1;
|
||||
/* Error indicator */
|
||||
uint8_t error :1;
|
||||
} FILE;
|
||||
|
||||
#endif /*__BITS_TYPES_FILE_H__*/
|
||||
|
|
33
src/libc/stdio/fflush.c
Normal file
33
src/libc/stdio/fflush.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "fileutil.h"
|
||||
|
||||
int fflush(FILE *fp)
|
||||
{
|
||||
// TODO: fflush(NULL) should flush "all" files (do we track them?)
|
||||
if(!fp) {
|
||||
errno = EINVAL;
|
||||
return EOF;
|
||||
}
|
||||
if(!fp->buf)
|
||||
return 0;
|
||||
|
||||
int rc = 0;
|
||||
|
||||
/* In reading mode, reset the file offset */
|
||||
if(fp->bufmode == __FILE_BUF_READ && fp->bufpos < fp->bufread) {
|
||||
fp->fdpos = fp->fdpos - fp->bufread + fp->bufpos;
|
||||
lseek(fp->fd, fp->fdpos, SEEK_SET);
|
||||
fp->bufpos = 0;
|
||||
fp->bufread = 0;
|
||||
}
|
||||
|
||||
/* In writing mode, write pending data */
|
||||
else if(fp->bufmode == __FILE_BUF_WRITE && fp->bufpos > 0) {
|
||||
rc = __fp_write(fp, fp->buf, fp->bufpos);
|
||||
fp->bufpos = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
19
src/libc/stdio/fileutil.c
Normal file
19
src/libc/stdio/fileutil.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include "fileutil.h"
|
||||
#include <unistd.h>
|
||||
|
||||
int __fp_write(FILE *fp, void const *data, size_t size)
|
||||
{
|
||||
if(!fp)
|
||||
return EOF;
|
||||
|
||||
ssize_t rc = write(fp->fd, data, size);
|
||||
|
||||
if(rc < 0) {
|
||||
fp->error = 1;
|
||||
return EOF;
|
||||
}
|
||||
else {
|
||||
fp->fdpos += rc;
|
||||
return 0;
|
||||
}
|
||||
}
|
18
src/libc/stdio/fileutil.h
Normal file
18
src/libc/stdio/fileutil.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef __FILEUTIL_H__
|
||||
# define __FILEUTIL_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Write data to a file descriptor; updates the fdpos and sets the error
|
||||
indicator. Returns 0 on success, EOF on error. */
|
||||
int __fp_write(FILE *fp, void const *data, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__FILEUTIL_H__*/
|
19
src/libc/stdio/remove.c
Normal file
19
src/libc/stdio/remove.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int remove(char const *filename)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
int rc = stat(filename, &st);
|
||||
if(rc < 0)
|
||||
return -1;
|
||||
|
||||
if(S_ISDIR(st.st_mode)) {
|
||||
return rmdir(filename);
|
||||
}
|
||||
else {
|
||||
return unlink(filename);
|
||||
}
|
||||
}
|
11
src/libc/stdio/setbuf.c
Normal file
11
src/libc/stdio/setbuf.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <stdio.h>
|
||||
|
||||
void setbuf(FILE * restrict fp, char * restrict buf)
|
||||
{
|
||||
if(buf) {
|
||||
setvbuf(fp, buf, _IOFBF, BUFSIZ);
|
||||
}
|
||||
else {
|
||||
setvbuf(fp, buf, _IONBF, 0);
|
||||
}
|
||||
}
|
36
src/libc/stdio/setvbuf.c
Normal file
36
src/libc/stdio/setvbuf.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
int setvbuf(FILE * restrict fp, char * restrict buf, int mode, size_t size)
|
||||
{
|
||||
if(fp->bufmode != _IONBF) {
|
||||
fflush(fp);
|
||||
if(fp->bufowned)
|
||||
free(fp->buf);
|
||||
}
|
||||
|
||||
fp->buf = NULL;
|
||||
fp->bufowned = false;
|
||||
fp->bufmode = _IONBF;
|
||||
fp->bufsize = 0;
|
||||
|
||||
if(mode == _IONBF)
|
||||
return 0;
|
||||
|
||||
if(buf) {
|
||||
fp->buf = buf;
|
||||
fp->bufsize = size;
|
||||
fp->bufmode = mode;
|
||||
}
|
||||
else {
|
||||
fp->buf = malloc(size);
|
||||
if(!fp->buf)
|
||||
return -1;
|
||||
fp->bufsize = size;
|
||||
fp->bufowned = true;
|
||||
fp->bufmode = mode;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue