Ver Fonte

feat(gblibc): clearerr, ferror, feof

greatbridf há 2 anos atrás
pai
commit
92f2e82f02
3 ficheiros alterados com 61 adições e 7 exclusões
  1. 4 0
      gblibc/include/stdio.h
  2. 2 0
      gblibc/private-include/priv-vars.h
  3. 55 7
      gblibc/src/stdio.c

+ 4 - 0
gblibc/include/stdio.h

@@ -56,6 +56,10 @@ int fputs(const char* s, FILE* stream);
 int fgetc(FILE* stream);
 int fputc(int character, FILE* stream);
 
+int ferror(FILE* stream);
+int feof(FILE* stream);
+void clearerr(FILE* stream);
+
 extern FILE* stdout;
 extern FILE* stdin;
 extern FILE* stderr;

+ 2 - 0
gblibc/private-include/priv-vars.h

@@ -9,6 +9,8 @@ extern "C" {
 
 #define FILE_READ (1 << 0)
 #define FILE_WRITE (1 << 1)
+#define FILE_ERROR (1 << 2)
+#define FILE_EOF (1 << 3)
 
 void** __start_brk_location(void);
 void** __curr_brk_location(void);

+ 55 - 7
gblibc/src/stdio.c

@@ -10,6 +10,11 @@
 #include <unistd.h>
 #include <priv-vars.h>
 
+static inline int __feof_or_error(FILE* stream)
+{
+    return !!(stream->flags & (FILE_ERROR | FILE_EOF));
+}
+
 // where n is in the range of [0, 9]
 static inline char d_to_c(int32_t n)
 {
@@ -649,9 +654,19 @@ open_fail:
 
 int fflush(FILE* stream)
 {
+    if (__feof_or_error(stream))
+        return EOF;
+
     if (stream->wbuf && stream->wpos) {
-        if (write(stream->fd, stream->wbuf, stream->wpos) < 0)
+        int ret = write(stream->fd, stream->wbuf, stream->wpos);
+        if (ret < 0) {
+            stream->flags |= FILE_ERROR;
+            return EOF;
+        }
+        if (ret == 0) {
+            stream->flags |= FILE_EOF;
             return EOF;
+        }
         stream->wpos = 0;
     }
 
@@ -707,9 +722,13 @@ int fputs(const char* s, FILE* stream)
 
 static inline int __fillbuf(FILE* stream)
 {
-    // TODO: set EOF flag
     if ((stream->rcnt = read(stream->fd, stream->rbuf, stream->rbsz)) >= 2147483648U) {
         stream->rcnt = 0;
+        stream->flags |= FILE_ERROR;
+        return EOF;
+    }
+    if (stream->rcnt == 0) {
+        stream->flags |= FILE_EOF;
         return EOF;
     }
     stream->rpos = 0;
@@ -718,6 +737,9 @@ static inline int __fillbuf(FILE* stream)
 
 int getc_unlocked(FILE* stream)
 {
+    if (__feof_or_error(stream))
+        return EOF;
+
     if (stream->rbuf) {
         if (stream->rpos == stream->rcnt) {
             if (__fillbuf(stream) < 0)
@@ -726,23 +748,34 @@ int getc_unlocked(FILE* stream)
         return stream->rbuf[stream->rpos++];
     } else {
         int c;
-        // TODO: set EOF on error
-        if (read(stream->fd, &c, 1) < 0)
+        int ret = read(stream->fd, &c, 1);
+        if (ret < 0) {
+            stream->flags |= FILE_ERROR;
+            return EOF;
+        }
+        if (ret == 0) {
+            stream->flags |= FILE_EOF;
             return EOF;
+        }
         return c;
     }
 }
 
 int putc_unlocked(int c, FILE* stream)
 {
+    if (__feof_or_error(stream))
+        return EOF;
+
     if (stream->wbuf) {
         stream->wbuf[stream->wpos++] = c;
         if (stream->wpos == stream->wbsz || c == '\n')
-            fflush(stream);
+            if (fflush(stream) == EOF)
+                return EOF;
     } else {
-        // TODO: set EOF on error
-        if (write(stream->fd, &c, 1) < 0)
+        if (write(stream->fd, &c, 1) < 0) {
+            stream->flags |= FILE_ERROR;
             return EOF;
+        }
     }
 
     return c;
@@ -757,3 +790,18 @@ int fgetc(FILE* stream)
 {
     return getc_unlocked(stream);
 }
+
+int ferror(FILE* stream)
+{
+    return stream->flags & FILE_ERROR;
+}
+
+int feof(FILE* stream)
+{
+    return stream->flags & FILE_EOF;
+}
+
+void clearerr(FILE* stream)
+{
+    stream->flags &= ~FILE_ERROR;
+}