summaryrefslogtreecommitdiff
path: root/LibC/stdio.cpp
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-03-27 01:40:55 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-03-27 01:40:55 +0100
commitd1e55fb4d95c790155f427bac980a1c24a1360f7 (patch)
tree3e37057c7d5c7136c5207b4f71e9f65725183252 /LibC/stdio.cpp
parent0c2face7b0756ac5d8523551f20a95716d77b9c5 (diff)
downloadserenity-d1e55fb4d95c790155f427bac980a1c24a1360f7.zip
LibC: Add ungetc() and automatically flush streams on fclose().
Diffstat (limited to 'LibC/stdio.cpp')
-rw-r--r--LibC/stdio.cpp20
1 files changed, 18 insertions, 2 deletions
diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp
index 9a976b4bb1..49de4da1c1 100644
--- a/LibC/stdio.cpp
+++ b/LibC/stdio.cpp
@@ -141,9 +141,12 @@ int getchar()
return getc(stdin);
}
-int ungetc(int, FILE*)
+int ungetc(int c, FILE* stream)
{
- ASSERT_NOT_REACHED();
+ ASSERT(stream);
+ stream->have_ungotten = true;
+ stream->ungotten = c;
+ return c;
}
int fputc(int ch, FILE* stream)
@@ -203,6 +206,18 @@ int ferror(FILE* stream)
size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream)
{
assert(stream);
+ if (!size)
+ return 0;
+
+ if (stream->have_ungotten) {
+ // FIXME: Support ungotten character even if size != 1.
+ ASSERT(size == 1);
+ ((char*)ptr)[0] = stream->ungotten;
+ stream->have_ungotten = false;
+ --nmemb;
+ ptr = &((char*)ptr)[1];
+ }
+
ssize_t nread = read(stream->fd, ptr, nmemb * size);
if (nread < 0)
return 0;
@@ -388,6 +403,7 @@ FILE* fdopen(int fd, const char* mode)
int fclose(FILE* stream)
{
+ fflush(stream);
int rc = close(stream->fd);
free(stream);
return rc;