summaryrefslogtreecommitdiff
path: root/LibC/stdio.cpp
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-11-11 10:11:09 +0100
committerAndreas Kling <awesomekling@gmail.com>2018-11-11 10:11:09 +0100
commite48182d91b352525d31105989be3b0e5f77f772a (patch)
treec4e50b54b55e9828ec6f8cb14b721641d670511c /LibC/stdio.cpp
parent7cc4caee4f879efd12a079a206b00a689a254609 (diff)
downloadserenity-e48182d91b352525d31105989be3b0e5f77f772a.zip
Add setvbuf(), setlinebuf(), setbuf().
Diffstat (limited to 'LibC/stdio.cpp')
-rw-r--r--LibC/stdio.cpp83
1 files changed, 69 insertions, 14 deletions
diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp
index 5c1409591f..d4df7762a8 100644
--- a/LibC/stdio.cpp
+++ b/LibC/stdio.cpp
@@ -6,11 +6,70 @@
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
+#include <unistd.h>
#include <Kernel/Syscall.h>
#include <AK/printf.cpp>
extern "C" {
+static FILE __default_streams[3];
+FILE* stdin;
+FILE* stdout;
+FILE* stderr;
+
+void init_FILE(FILE& fp, int fd, int mode)
+{
+ fp.fd = fd;
+ fp.buffer = fp.default_buffer;
+ fp.buffer_size = BUFSIZ;
+ fp.mode = mode;
+}
+
+static FILE* make_FILE(int fd)
+{
+ auto* fp = (FILE*)malloc(sizeof(FILE));
+ memset(fp, 0, sizeof(FILE));
+ init_FILE(*fp, fd, isatty(fd));
+ return fp;
+}
+
+void __stdio_init()
+{
+ stdin = &__default_streams[0];
+ stdout = &__default_streams[1];
+ stderr = &__default_streams[2];
+ init_FILE(*stdin, 0, isatty(0) ? _IOLBF : _IOFBF);
+ init_FILE(*stdout, 1, isatty(1) ? _IOLBF : _IOFBF);
+ init_FILE(*stderr, 2, _IONBF);
+}
+
+int setvbuf(FILE* stream, char* buf, int mode, size_t size)
+{
+ if (mode != _IONBF && mode != _IOLBF && mode != _IOFBF) {
+ errno = EINVAL;
+ return -1;
+ }
+ stream->mode = mode;
+ if (buf) {
+ stream->buffer = buf;
+ stream->buffer_size = size;
+ } else {
+ stream->buffer = stream->default_buffer;
+ stream->buffer_size = BUFSIZ;
+ }
+ return 0;
+}
+
+void setbuf(FILE* stream, char* buf)
+{
+ setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
+}
+
+void setlinebuf(FILE* stream, char* buf)
+{
+ setvbuf(stream, buf, buf ? _IOLBF : _IONBF, BUFSIZ);
+}
+
int fileno(FILE* stream)
{
assert(stream);
@@ -28,10 +87,10 @@ int fflush(FILE* stream)
// FIXME: Implement buffered streams, duh.
if (!stream)
return -EBADF;
- if (!stream->write_buffer_index)
+ if (!stream->buffer_index)
return 0;
- int rc = write(stream->fd, stream->write_buffer, stream->write_buffer_index);
- stream->write_buffer_index = 0;
+ int rc = write(stream->fd, stream->buffer, stream->buffer_index);
+ stream->buffer_index = 0;
return rc;
}
@@ -75,9 +134,11 @@ int getchar()
int fputc(int ch, FILE* stream)
{
assert(stream);
- assert(stream->write_buffer_index < __STDIO_FILE_BUFFER_SIZE);
- stream->write_buffer[stream->write_buffer_index++] = ch;
- if (ch == '\n' || stream->write_buffer_index >= __STDIO_FILE_BUFFER_SIZE)
+ assert(stream->buffer_index < stream->buffer_size);
+ stream->buffer[stream->buffer_index++] = ch;
+ if (stream->buffer_index >= stream->buffer_size)
+ fflush(stream);
+ else if (stream->mode == _IOLBF && ch == '\n')
fflush(stream);
if (stream->eof)
return EOF;
@@ -218,10 +279,7 @@ FILE* fopen(const char* pathname, const char* mode)
int fd = open(pathname, O_RDONLY);
if (fd < 0)
return nullptr;
- auto* fp = (FILE*)malloc(sizeof(FILE));
- memset(fp, 0, sizeof(FILE));
- fp->fd = fd;
- return fp;
+ return make_FILE(fd);
}
FILE* fdopen(int fd, const char* mode)
@@ -229,10 +287,7 @@ FILE* fdopen(int fd, const char* mode)
assert(!strcmp(mode, "r") || !strcmp(mode, "rb"));
if (fd < 0)
return nullptr;
- auto* fp = (FILE*)malloc(sizeof(FILE));
- memset(fp, 0, sizeof(FILE));
- fp->fd = fd;
- return fp;
+ return make_FILE(fd);
}
int fclose(FILE* stream)