summaryrefslogtreecommitdiff
path: root/lib/libc/stdio
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/stdio')
-rw-r--r--lib/libc/stdio/Kbuild20
-rw-r--r--lib/libc/stdio/clearerr.c15
-rw-r--r--lib/libc/stdio/clearerr_unlocked.c8
-rw-r--r--lib/libc/stdio/fclose.c2
-rw-r--r--lib/libc/stdio/fdopen.c25
-rw-r--r--lib/libc/stdio/feof.c15
-rw-r--r--lib/libc/stdio/feof_unlocked.c7
-rw-r--r--lib/libc/stdio/ferror.c14
-rw-r--r--lib/libc/stdio/ferror_unlocked.c7
-rw-r--r--lib/libc/stdio/fflush.c73
-rw-r--r--lib/libc/stdio/fflush_unlocked.c64
-rw-r--r--lib/libc/stdio/fgetc.c11
-rw-r--r--lib/libc/stdio/fgetc_unlocked.c11
-rw-r--r--lib/libc/stdio/fgets.c15
-rw-r--r--lib/libc/stdio/fgets_unlocked.c6
-rw-r--r--lib/libc/stdio/fileno.c20
-rw-r--r--lib/libc/stdio/fileno_unlocked.c13
-rw-r--r--lib/libc/stdio/flockfile.c8
-rw-r--r--lib/libc/stdio/fmemopen.c10
-rw-r--r--lib/libc/stdio/fopen.c18
-rw-r--r--lib/libc/stdio/fputc.c25
-rw-r--r--lib/libc/stdio/fputc_unlocked.c6
-rw-r--r--lib/libc/stdio/fputs.c11
-rw-r--r--lib/libc/stdio/fputs_unlocked.c9
-rw-r--r--lib/libc/stdio/fread.c56
-rw-r--r--lib/libc/stdio/fread_unlocked.c47
-rw-r--r--lib/libc/stdio/fseek.c19
-rw-r--r--lib/libc/stdio/ftrylockfile.c11
-rw-r--r--lib/libc/stdio/funlockfile.c8
-rw-r--r--lib/libc/stdio/fwrite.c136
-rw-r--r--lib/libc/stdio/fwrite_unlocked.c106
-rw-r--r--lib/libc/stdio/getc.c13
-rw-r--r--lib/libc/stdio/getc_unlocked.c6
-rw-r--r--lib/libc/stdio/getchar.c13
-rw-r--r--lib/libc/stdio/getchar_unlocked.c6
-rw-r--r--lib/libc/stdio/pclose.c2
-rw-r--r--lib/libc/stdio/popen.c2
-rw-r--r--lib/libc/stdio/putchar.c13
-rw-r--r--lib/libc/stdio/putchar_unlocked.c6
-rw-r--r--lib/libc/stdio/setvbuf.c10
-rw-r--r--lib/libc/stdio/stderr.c23
-rw-r--r--lib/libc/stdio/stdin.c19
-rw-r--r--lib/libc/stdio/stdout.c37
-rw-r--r--lib/libc/stdio/vfprintf.c245
44 files changed, 568 insertions, 623 deletions
diff --git a/lib/libc/stdio/Kbuild b/lib/libc/stdio/Kbuild
index 36339313..0d1df566 100644
--- a/lib/libc/stdio/Kbuild
+++ b/lib/libc/stdio/Kbuild
@@ -1,33 +1,50 @@
obj-y += asprintf.o
obj-y += clearerr.o
+obj-y += clearerr_unlocked.o
obj-y += dprintf.o
obj-y += dtoa.o
obj-y += fclose.o
obj-y += fdopen.o
obj-y += feof.o
+obj-y += feof_unlocked.o
obj-y += ferror.o
+obj-y += ferror_unlocked.o
obj-y += fflush.o
+obj-y += fflush_unlocked.o
obj-y += fgetc.o
+obj-y += fgetc_unlocked.o
obj-y += fgets.o
+obj-y += fgets_unlocked.o
obj-y += fileno.o
+obj-y += fileno_unlocked.o
+obj-y += flockfile.o
obj-y += fmemopen.o
obj-y += fopen.o
obj-y += fprintf.o
obj-y += fputc.o
+obj-y += fputc_unlocked.o
obj-y += fputs.o
+obj-y += fputs_unlocked.o
obj-y += fread.o
+obj-y += fread_unlocked.o
obj-y += fseek.o
obj-y += ftell.o
obj-y += ftello.o
+obj-y += ftrylockfile.o
+obj-y += funlockfile.o
obj-y += fwrite.o
+obj-y += fwrite_unlocked.o
obj-y += getc.o
+obj-y += getc_unlocked.o
obj-y += getchar.o
+obj-y += getchar_unlocked.o
obj-y += pclose.o
obj-y += perror.o
obj-y += popen.o
obj-y += printf.o
obj-y += putc.o
obj-y += putchar.o
+obj-y += putchar_unlocked.o
obj-y += puts.o
obj-y += remove.o
obj-y += rename.o
@@ -37,9 +54,6 @@ obj-y += setbuf.o
obj-y += setvbuf.o
obj-y += snprintf.o
obj-y += sprintf.o
-obj-y += stderr.o
-obj-y += stdin.o
-obj-y += stdout.o
obj-y += vasprintf.o
obj-y += vdprintf.o
obj-y += vfprintf.o
diff --git a/lib/libc/stdio/clearerr.c b/lib/libc/stdio/clearerr.c
index 02244466..8389a085 100644
--- a/lib/libc/stdio/clearerr.c
+++ b/lib/libc/stdio/clearerr.c
@@ -1,14 +1,9 @@
-#include "__stdio.h" // for __FILE, _IO_EOF, _IO_ERR
-#include "stddef.h" // for NULL
-
-#include <stdio.h> // for FILE, clearerr
+#include <__stdio.h>
+#include <stdio.h>
void clearerr(FILE *stream)
{
- struct __FILE *stream_impl = __FILE(stream);
-
- if (stream == NULL)
- return;
-
- stream_impl->flags &= ~(_IO_ERR | _IO_EOF);
+ flockfile(stream);
+ clearerr_unlocked(stream);
+ funlockfile(stream);
}
diff --git a/lib/libc/stdio/clearerr_unlocked.c b/lib/libc/stdio/clearerr_unlocked.c
new file mode 100644
index 00000000..da4ea106
--- /dev/null
+++ b/lib/libc/stdio/clearerr_unlocked.c
@@ -0,0 +1,8 @@
+#include <__stdio.h>
+#include <stdio.h>
+
+void clearerr_unlocked(FILE *stream)
+{
+ if (stream != NULL)
+ stream->flags &= ~(_IO_ERR | _IO_EOF);
+}
diff --git a/lib/libc/stdio/fclose.c b/lib/libc/stdio/fclose.c
index 4534715b..4fdf6495 100644
--- a/lib/libc/stdio/fclose.c
+++ b/lib/libc/stdio/fclose.c
@@ -8,7 +8,7 @@ int fclose(FILE *stream)
return -1;
if (stream != stdin && stream != stdout && stream != stderr) {
- if (close((__FILE(stream))->fd) == -1)
+ if (close(fileno(stream)) == -1)
return -1;
}
diff --git a/lib/libc/stdio/fdopen.c b/lib/libc/stdio/fdopen.c
index bded5f27..dc9da567 100644
--- a/lib/libc/stdio/fdopen.c
+++ b/lib/libc/stdio/fdopen.c
@@ -4,33 +4,30 @@
#include <sys/cdefs.h>
#include <unistd.h> // for lseek, off_t
-__weak void __stdio_cleanup(void)
-{
-}
-
FILE *fdopen(int fildes, const char *mode)
{
- FILE *stream;
+ struct __FILE *stream;
if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a')) {
return NULL;
}
- stream = calloc(1, sizeof(FILE));
+ stream = calloc(1, sizeof(struct __FILE));
if (stream == NULL)
return NULL;
- __FILE(stream)->fd = fildes;
- atomic_flag_clear(&__FILE(stream)->lock);
+ stream->fd = fildes;
+ atomic_flag_clear(&stream->lock);
+
if (mode[0] == 'r') {
- __FILE(stream)->type = _IONBF;
+ stream->type = _IONBF;
} else if (mode[0] == 'w') {
- __FILE(stream)->type = _IOLBF;
+ stream->type = _IOLBF;
} else if (mode[0] == 'a') {
- __FILE(stream)->type = _IONBF;
-
- off_t offset = lseek(fildes, 0, SEEK_END);
- if (offset == (off_t)-1) {
+ off_t off;
+ stream->type = _IONBF;
+ off = lseek(fildes, 0, SEEK_END);
+ if (off == (off_t)-1) {
free(stream);
return NULL;
}
diff --git a/lib/libc/stdio/feof.c b/lib/libc/stdio/feof.c
index f9245d06..6a36172b 100644
--- a/lib/libc/stdio/feof.c
+++ b/lib/libc/stdio/feof.c
@@ -1,12 +1,13 @@
-#include "stddef.h" // for NULL
-
-#include <__stdio.h> // for __FILE
-#include <stdio.h> // for FILE, feof
+#include <__stdio.h>
+#include <stdio.h>
int feof(FILE *stream)
{
- if (stream == NULL)
- return 0;
+ int r;
+
+ flockfile(stream);
+ r = feof_unlocked(stream);
+ funlockfile(stream);
- return (__FILE(stream))->eof;
+ return r;
}
diff --git a/lib/libc/stdio/feof_unlocked.c b/lib/libc/stdio/feof_unlocked.c
new file mode 100644
index 00000000..4d7d9d53
--- /dev/null
+++ b/lib/libc/stdio/feof_unlocked.c
@@ -0,0 +1,7 @@
+#include <__stdio.h>
+#include <stdio.h>
+
+int feof_unlocked(FILE *stream)
+{
+ return (stream) ? stream->eof : 0;
+}
diff --git a/lib/libc/stdio/ferror.c b/lib/libc/stdio/ferror.c
index 5e4b8dc4..9391a44a 100644
--- a/lib/libc/stdio/ferror.c
+++ b/lib/libc/stdio/ferror.c
@@ -1,12 +1,12 @@
-#include "__stdio.h" // for __FILE, _IO_ERR
-#include "stddef.h" // for NULL
-
-#include <stdio.h> // for FILE, ferror
+#include <stdio.h>
int ferror(FILE *stream)
{
- if (stream == NULL)
- return 0;
+ int r;
+
+ flockfile(stream);
+ r = ferror_unlocked(stream);
+ funlockfile(stream);
- return (__FILE(stream)->flags & _IO_ERR) != 0;
+ return r;
}
diff --git a/lib/libc/stdio/ferror_unlocked.c b/lib/libc/stdio/ferror_unlocked.c
new file mode 100644
index 00000000..3c622dd9
--- /dev/null
+++ b/lib/libc/stdio/ferror_unlocked.c
@@ -0,0 +1,7 @@
+#include <__stdio.h>
+#include <stdio.h>
+
+int ferror_unlocked(FILE *stream)
+{
+ return (stream) ? (stream->flags & _IO_ERR) != 0 : 0;
+}
diff --git a/lib/libc/stdio/fflush.c b/lib/libc/stdio/fflush.c
index 1cf4b7bd..b3fca8bd 100644
--- a/lib/libc/stdio/fflush.c
+++ b/lib/libc/stdio/fflush.c
@@ -3,74 +3,15 @@
#include <atomic.h> // for LIBC_UNLOCK, LIBC_LOCK
#include <errno.h> // for errno, EBADF, EIO
-#include <fcntl.h> // for O_ACCMODE, O_RDONLY
-#include <stdio.h> // for EOF, FILE, fflush
-#include <string.h> // for memmove
-#include <unistd.h> // for size_t, write, ssize_t
+#include <stdio.h>
-int fflush(FILE *stream)
+int fflush(struct __FILE *stream)
{
- if (stream == NULL) {
- // TODO: Implement flushing all open streams
- // For now, just return success
- return 0;
- }
+ int r;
- if (__FILE(stream)->buf_len == 0) {
- return 0;
- }
+ flockfile(stream);
+ r = fflush_unlocked(stream);
+ funlockfile(stream);
- if (__FILE(stream)->fd == -1) {
- __FILE(stream)->buf_len = 0;
- return 0;
- }
-
- if (__FILE(stream)->flags & _IO_ERR) {
- errno = EIO;
- return EOF;
- }
-
- if ((__FILE(stream)->flags & O_ACCMODE) == O_RDONLY) {
- errno = EBADF;
- return EOF;
- }
-
- LIBC_LOCK(__FILE(stream)->lock);
-
- size_t bytes_to_write = __FILE(stream)->buf_len;
- size_t total_written = 0;
- char *buf_ptr = __FILE(stream)->buf;
-
- while (total_written < bytes_to_write) {
- ssize_t result = write(__FILE(stream)->fd,
- buf_ptr + total_written,
- bytes_to_write - total_written);
-
- if (result < 0) {
- __FILE(stream)->flags |= _IO_ERR;
- LIBC_UNLOCK(__FILE(stream)->lock);
- return EOF;
- }
-
- if (result == 0) {
- break;
- }
-
- total_written += result;
- }
-
- if (total_written == bytes_to_write) {
- __FILE(stream)->buf_len = 0;
- __FILE(stream)->buf_pos = 0;
- } else {
- size_t remaining = bytes_to_write - total_written;
- memmove(__FILE(stream)->buf,
- __FILE(stream)->buf + total_written, remaining);
- __FILE(stream)->buf_len = remaining;
- __FILE(stream)->buf_pos = 0;
- }
-
- LIBC_UNLOCK(__FILE(stream)->lock);
-
- return (total_written == bytes_to_write) ? 0 : EOF;
+ return r;
}
diff --git a/lib/libc/stdio/fflush_unlocked.c b/lib/libc/stdio/fflush_unlocked.c
new file mode 100644
index 00000000..b4ee3e43
--- /dev/null
+++ b/lib/libc/stdio/fflush_unlocked.c
@@ -0,0 +1,64 @@
+#include <__stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/cdefs.h>
+#include <unistd.h>
+
+int fflush_unlocked(struct __FILE *stream)
+{
+ if (stream == NULL) {
+ // TODO: flush all streams
+ return 0;
+ }
+
+ if (__predict_false(stream->fd) == -1) {
+ stream->buf_len = 0;
+ return 0;
+ }
+
+ if (__predict_false(stream->buf == 0)) {
+ return 0;
+ }
+
+ if (stream->flags & _IO_ERR) {
+ errno = EIO;
+ return EOF;
+ }
+
+ if ((stream->flags & O_ACCMODE) == O_RDONLY) {
+ errno = EBADF;
+ return EOF;
+ }
+
+ size_t bytes_to_write = stream->buf_len;
+ size_t total_written = 0;
+ char *buf_ptr = stream->buf;
+
+ while (total_written < bytes_to_write) {
+ ssize_t result = write(stream->fd, buf_ptr + total_written, bytes_to_write - total_written);
+
+ if (result < 0) {
+ stream->flags |= _IO_ERR;
+ return EOF;
+ }
+
+ if (result == 0) {
+ break;
+ }
+
+ total_written += result;
+ }
+
+ if (total_written == bytes_to_write) {
+ stream->buf_len = 0;
+ stream->buf_pos = 0;
+ } else {
+ size_t remaining = bytes_to_write - total_written;
+ memmove(stream->buf, stream->buf + total_written, remaining);
+ stream->buf_len = remaining;
+ stream->buf_pos = 0;
+ }
+
+ return (total_written == bytes_to_write) ? 0 : EOF;
+}
diff --git a/lib/libc/stdio/fgetc.c b/lib/libc/stdio/fgetc.c
index a7612f42..f0642c30 100644
--- a/lib/libc/stdio/fgetc.c
+++ b/lib/libc/stdio/fgetc.c
@@ -1,11 +1,12 @@
-#include <stdio.h> // for fread, FILE, fgetc
+#include <stdio.h>
int fgetc(FILE *stream)
{
- int c;
+ int r;
- if (fread(&c, 1, 1, stream) < 0)
- return -1;
+ flockfile(stream);
+ r = fgetc_unlocked(stream);
+ funlockfile(stream);
- return c;
+ return r;
}
diff --git a/lib/libc/stdio/fgetc_unlocked.c b/lib/libc/stdio/fgetc_unlocked.c
new file mode 100644
index 00000000..5cccfd87
--- /dev/null
+++ b/lib/libc/stdio/fgetc_unlocked.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+int fgetc_unlocked(FILE *stream)
+{
+ int c;
+
+ if (fread_unlocked(&c, 1, 1, stream) < 0)
+ return -1;
+
+ return c;
+}
diff --git a/lib/libc/stdio/fgets.c b/lib/libc/stdio/fgets.c
index adeae1b4..d0f7d2d9 100644
--- a/lib/libc/stdio/fgets.c
+++ b/lib/libc/stdio/fgets.c
@@ -1,11 +1,12 @@
-#include "stddef.h" // for NULL
-
-#include <libc.h> // for weak_reference
-#include <stdio.h> // for fread, FILE, fgets
+#include <stdio.h>
char *fgets(char *restrict s, int n, FILE *restrict stream)
{
- return fread(s, 1, n, stream) ? s : NULL;
-}
+ char *r;
-weak_reference(fgets, fgets_unlocked);
+ flockfile(stream);
+ r = fgets_unlocked(s, n, stream);
+ funlockfile(stream);
+
+ return r;
+}
diff --git a/lib/libc/stdio/fgets_unlocked.c b/lib/libc/stdio/fgets_unlocked.c
new file mode 100644
index 00000000..9e2dca60
--- /dev/null
+++ b/lib/libc/stdio/fgets_unlocked.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+char *fgets_unlocked(char *s, int n, FILE *stream)
+{
+ return fread_unlocked(s, 1, n, stream) ? s : NULL;
+}
diff --git a/lib/libc/stdio/fileno.c b/lib/libc/stdio/fileno.c
index e27b56de..4fa47eb4 100644
--- a/lib/libc/stdio/fileno.c
+++ b/lib/libc/stdio/fileno.c
@@ -1,20 +1,12 @@
-#include <__stdio.h> // for __FILE
-#include <atomic.h> // for LIBC_LOCK, LIBC_UNLOCK
-#include <errno.h> // for EBADF, errno
-#include <stdio.h> // for FILE, fileno
+#include <stdio.h>
int fileno(FILE *stream)
{
- int fd;
+ int r;
- LIBC_LOCK(__FILE(stream)->lock);
- fd = __FILE(stream)->fd;
- LIBC_UNLOCK(__FILE(stream)->lock);
+ flockfile(stream);
+ r = fileno_unlocked(stream);
+ funlockfile(stream);
- if (fd < 0) {
- errno = EBADF;
- return -1;
- }
-
- return fd;
+ return r;
}
diff --git a/lib/libc/stdio/fileno_unlocked.c b/lib/libc/stdio/fileno_unlocked.c
new file mode 100644
index 00000000..a3490686
--- /dev/null
+++ b/lib/libc/stdio/fileno_unlocked.c
@@ -0,0 +1,13 @@
+#include <__stdio.h>
+#include <errno.h>
+#include <stdio.h>
+
+int fileno_unlocked(FILE *stream)
+{
+ if (stream->fd < 0) {
+ errno = EBADF;
+ return -1;
+ }
+
+ return stream->fd;
+}
diff --git a/lib/libc/stdio/flockfile.c b/lib/libc/stdio/flockfile.c
new file mode 100644
index 00000000..788750b0
--- /dev/null
+++ b/lib/libc/stdio/flockfile.c
@@ -0,0 +1,8 @@
+#include <__stdio.h>
+#include <atomic.h>
+#include <stdio.h>
+
+void flockfile(FILE *file)
+{
+ LIBC_LOCK(file->lock);
+}
diff --git a/lib/libc/stdio/fmemopen.c b/lib/libc/stdio/fmemopen.c
index e1b2ccff..1e90b5ea 100644
--- a/lib/libc/stdio/fmemopen.c
+++ b/lib/libc/stdio/fmemopen.c
@@ -21,10 +21,10 @@ FILE *fmemopen(void *restrict buf, size_t max_size, const char *restrict mode)
if (stream == NULL)
return stream;
- __FILE(stream)->fd = -1;
- __FILE(stream)->buf = buf;
- __FILE(stream)->buf_size = max_size;
- __FILE(stream)->type = _IOFBF;
+ stream->fd = -1;
+ stream->buf = buf;
+ stream->buf_size = max_size;
+ stream->type = _IOFBF;
if (mode[0] == 'r') {
flags = O_RDONLY;
@@ -42,7 +42,7 @@ FILE *fmemopen(void *restrict buf, size_t max_size, const char *restrict mode)
flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
}
- __FILE(stream)->flags = flags;
+ stream->flags = flags;
__libc_fadd(stream);
diff --git a/lib/libc/stdio/fopen.c b/lib/libc/stdio/fopen.c
index 5415e711..0265694a 100644
--- a/lib/libc/stdio/fopen.c
+++ b/lib/libc/stdio/fopen.c
@@ -8,10 +8,6 @@
#include <sys/cdefs.h>
#include <unistd.h> // for close
-__weak void __stdio_cleanup(void)
-{
-}
-
FILE *fopen(const char *restrict pathname, const char *restrict mode)
{
int fd, flags, _mode;
@@ -42,15 +38,15 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode)
if (stream == NULL)
return NULL;
- __FILE(stream)->fd = fd;
- __FILE(stream)->buf_size = BUFSIZ;
- __FILE(stream)->flags = flags;
- __FILE(stream)->type = _IOLBF;
- atomic_flag_clear(&__FILE(stream)->lock);
+ stream->fd = fd;
+ stream->buf_size = BUFSIZ;
+ stream->flags = flags;
+ stream->type = _IOLBF;
+ atomic_flag_clear(&stream->lock);
- __FILE(stream)->buf = malloc(BUFSIZ);
+ stream->buf = malloc(BUFSIZ);
- if (__FILE(stream)->buf == NULL) {
+ if (stream->buf == NULL) {
close(fd);
free(stream);
return NULL;
diff --git a/lib/libc/stdio/fputc.c b/lib/libc/stdio/fputc.c
index 922011f2..365fbb96 100644
--- a/lib/libc/stdio/fputc.c
+++ b/lib/libc/stdio/fputc.c
@@ -1,25 +1,12 @@
-#include "stddef.h" // for NULL
-
-#include <__stdio.h> // for __FILE
-#include <errno.h> // for EINVAL, errno
-#include <stdio.h> // for EOF, fwrite, FILE, fputc
+#include <stdio.h>
int fputc(int c, FILE *stream)
{
- if (stream == NULL) {
- errno = EINVAL;
- return EOF;
- }
-
- if ((__FILE(stream))->fd == -1 && (__FILE(stream))->buf != NULL) {
- if ((__FILE(stream))->buf_len >=
- (__FILE(stream))->buf_size - 1) {
- return EOF;
- }
+ int r;
- (__FILE(stream))->buf[(__FILE(stream))->buf_len++] = (char)c;
- return (unsigned char)c;
- }
+ flockfile(stream);
+ r = fputc_unlocked(c, stream);
+ funlockfile(stream);
- return fwrite(&c, 1, 1, stream) ? c : EOF;
+ return r;
}
diff --git a/lib/libc/stdio/fputc_unlocked.c b/lib/libc/stdio/fputc_unlocked.c
new file mode 100644
index 00000000..966721e7
--- /dev/null
+++ b/lib/libc/stdio/fputc_unlocked.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int fputc_unlocked(int c, FILE *stream)
+{
+ return fwrite_unlocked(&c, 1, 1, stream) ? c : EOF;
+}
diff --git a/lib/libc/stdio/fputs.c b/lib/libc/stdio/fputs.c
index 2ba0d4d1..ac5261e7 100644
--- a/lib/libc/stdio/fputs.c
+++ b/lib/libc/stdio/fputs.c
@@ -1,7 +1,12 @@
-#include <stdio.h> // for fwrite, EOF, FILE, fputs
-#include <string.h> // for strlen
+#include <stdio.h>
int fputs(const char *restrict s, FILE *restrict stream)
{
- return fwrite(s, 1, strlen(s), stream) == strlen(s) ? 0 : EOF;
+ int r;
+
+ flockfile(stream);
+ r = fputs_unlocked(s, stream);
+ funlockfile(stream);
+
+ return r;
}
diff --git a/lib/libc/stdio/fputs_unlocked.c b/lib/libc/stdio/fputs_unlocked.c
new file mode 100644
index 00000000..aeab8d32
--- /dev/null
+++ b/lib/libc/stdio/fputs_unlocked.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+#include <string.h>
+
+int fputs_unlocked(const char *s, FILE *stream)
+{
+ size_t len = strlen(s);
+
+ return fwrite_unlocked(s, 1, len, stream) == len ? 0 : EOF;
+}
diff --git a/lib/libc/stdio/fread.c b/lib/libc/stdio/fread.c
index 443b4874..bcadbbdc 100644
--- a/lib/libc/stdio/fread.c
+++ b/lib/libc/stdio/fread.c
@@ -1,54 +1,12 @@
-#include "__stdio.h" // for __FILE, _IO_EOF, _IO_ERR
+#include <stdio.h>
-#include <atomic.h> // for LIBC_LOCK, LIBC_UNLOCK
-#include <stdio.h> // for fread, BUFSIZ, FILE
-#include <string.h> // for memcpy
-#include <unistd.h> // for size_t, read, ssize_t
-
-char __stdin_buffer[BUFSIZ];
-
-size_t fread(void *restrict ptr, size_t size, size_t nitems,
- FILE *restrict stream)
+size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream)
{
- if (size == 0 || nitems == 0)
- return 0;
-
- size_t total = size * nitems;
- size_t bytes_read = 0;
- char *p = ptr;
-
- LIBC_LOCK(__FILE(stream)->lock);
-
- while (total > 0) {
- if (__FILE(stream)->buf_pos < __FILE(stream)->buf_len) {
- size_t available = __FILE(stream)->buf_len -
- __FILE(stream)->buf_pos;
- size_t to_copy = total < available ? total : available;
-
- memcpy(p, __FILE(stream)->buf + __FILE(stream)->buf_pos,
- to_copy);
- __FILE(stream)->buf_pos += to_copy;
- p += to_copy;
- bytes_read += to_copy;
- total -= to_copy;
- continue;
- }
-
- ssize_t ret = read(__FILE(stream)->fd, __FILE(stream)->buf,
- __FILE(stream)->buf_size);
- if (ret <= 0) {
- if (ret < 0)
- __FILE(stream)->flags |= _IO_ERR;
- else
- __FILE(stream)->flags |= _IO_EOF;
- break;
- }
-
- __FILE(stream)->buf_len = ret;
- __FILE(stream)->buf_pos = 0;
- }
+ size_t r;
- LIBC_UNLOCK(__FILE(stream)->lock);
+ flockfile(stream);
+ r = fread_unlocked(ptr, size, nitems, stream);
+ funlockfile(stream);
- return bytes_read / size;
+ return r;
}
diff --git a/lib/libc/stdio/fread_unlocked.c b/lib/libc/stdio/fread_unlocked.c
new file mode 100644
index 00000000..4251a7ed
--- /dev/null
+++ b/lib/libc/stdio/fread_unlocked.c
@@ -0,0 +1,47 @@
+#include "__stdio.h" // for __FILE, _IO_EOF, _IO_ERR
+
+#include <atomic.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+extern void __libc_init_io(void);
+void *__libc_force_io_init = (void *)__libc_init_io;
+
+size_t fread_unlocked(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream)
+{
+ if (size == 0 || nitems == 0)
+ return 0;
+
+ size_t total = size * nitems;
+ size_t bytes_read = 0;
+ char *p = ptr;
+
+ while (total > 0) {
+ if (stream->buf_pos < stream->buf_len) {
+ size_t available = stream->buf_len - stream->buf_pos;
+ size_t to_copy = total < available ? total : available;
+
+ memcpy(p, stream->buf + stream->buf_pos, to_copy);
+ stream->buf_pos += to_copy;
+ p += to_copy;
+ bytes_read += to_copy;
+ total -= to_copy;
+ continue;
+ }
+
+ ssize_t ret = read(stream->fd, stream->buf, stream->buf_size);
+ if (ret <= 0) {
+ if (ret < 0)
+ stream->flags |= _IO_ERR;
+ else
+ stream->flags |= _IO_EOF;
+ break;
+ }
+
+ stream->buf_len = ret;
+ stream->buf_pos = 0;
+ }
+
+ return bytes_read / size;
+}
diff --git a/lib/libc/stdio/fseek.c b/lib/libc/stdio/fseek.c
index 7a6754f7..19459e7f 100644
--- a/lib/libc/stdio/fseek.c
+++ b/lib/libc/stdio/fseek.c
@@ -7,24 +7,21 @@
int fseek(FILE *stream, long offset, int whence)
{
- if (stream == NULL || __FILE(stream)->fd < 0)
+ if (stream == NULL || stream->fd < 0)
return -1;
- LIBC_LOCK(__FILE(stream)->lock);
+ stream->buf_pos = 0;
+ stream->buf_len = 0;
+ stream->flags &= ~_IO_EOF;
- __FILE(stream)->buf_pos = 0;
- __FILE(stream)->buf_len = 0;
- __FILE(stream)->flags &= ~_IO_EOF;
-
- off_t result = lseek(__FILE(stream)->fd, offset, whence);
-
- LIBC_UNLOCK(__FILE(stream)->lock);
+ off_t result = lseek(stream->fd, offset, whence);
if (result == (off_t)-1) {
- __FILE(stream)->flags |= _IO_ERR;
+ stream->flags |= _IO_ERR;
return -1;
}
- __FILE(stream)->offset = result;
+ stream->offset = result;
+
return 0;
}
diff --git a/lib/libc/stdio/ftrylockfile.c b/lib/libc/stdio/ftrylockfile.c
new file mode 100644
index 00000000..b8f89e4b
--- /dev/null
+++ b/lib/libc/stdio/ftrylockfile.c
@@ -0,0 +1,11 @@
+#include <__stdio.h>
+#include <atomic.h>
+#include <stdio.h>
+
+int ftrylockfile(FILE *file)
+{
+ if (file == NULL)
+ return -1;
+
+ return atomic_flag_test_and_set_explicit(&file->lock, memory_order_acquire) ? 1 : 0;
+}
diff --git a/lib/libc/stdio/funlockfile.c b/lib/libc/stdio/funlockfile.c
new file mode 100644
index 00000000..9d4154c7
--- /dev/null
+++ b/lib/libc/stdio/funlockfile.c
@@ -0,0 +1,8 @@
+#include <__stdio.h>
+#include <atomic.h>
+#include <stdio.h>
+
+void funlockfile(FILE *file)
+{
+ LIBC_UNLOCK(file->lock);
+}
diff --git a/lib/libc/stdio/fwrite.c b/lib/libc/stdio/fwrite.c
index c21054da..8d81c7ac 100644
--- a/lib/libc/stdio/fwrite.c
+++ b/lib/libc/stdio/fwrite.c
@@ -1,134 +1,12 @@
-#include "__stdio.h" // for __FILE, _IO_ERR
-#include "stddef.h" // for NULL
+#include <stdio.h>
-#include <atomic.h> // for LIBC_UNLOCK, LIBC_LOCK
-#include <errno.h> // for errno, EOVERFLOW, EBADF, EINVAL, EIO
-#include <fcntl.h> // for O_ACCMODE, O_RDONLY
-#include <stdio.h> // for fflush, fwrite, BUFSIZ, FILE, _IOFBF, _IOLBF
-#include <string.h> // for memcpy, memchr
-#include <unistd.h> // for size_t, ssize_t, write
-
-char __stdout_buffer[BUFSIZ];
-void (*__stdio_cleanup)(void);
-
-size_t fwrite(const void *restrict ptr, size_t size, size_t nitems,
- FILE *restrict stream)
+size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream)
{
- size_t total_bytes;
- size_t written = 0;
- const char *data = (const char *)ptr;
-
- if (ptr == NULL || stream == NULL || size == 0) {
- if (size == 0) {
- return nitems;
- }
- errno = EINVAL;
- return 0;
- }
-
- if (__FILE(stream)->fd == -1 && __FILE(stream)->buf != NULL) {
- if (__builtin_mul_overflow(size, nitems, &total_bytes)) {
- errno = EOVERFLOW;
- return 0;
- }
-
- size_t space_left =
- __FILE(stream)->buf_size > __FILE(stream)->buf_len ?
- __FILE(stream)->buf_size -
- __FILE(stream)->buf_len - 1 :
- 0;
-
- if (space_left == 0) {
- return 0;
- }
-
- size_t to_copy = total_bytes < space_left ? total_bytes :
- space_left;
-
- if (to_copy > 0) {
- memcpy(__FILE(stream)->buf + __FILE(stream)->buf_len,
- data, to_copy);
- __FILE(stream)->buf_len += to_copy;
- }
-
- return to_copy == total_bytes ? nitems : to_copy / size;
- }
-
- if (__builtin_mul_overflow(size, nitems, &total_bytes)) {
- errno = EOVERFLOW;
- return 0;
- }
-
- if ((__FILE(stream)->flags & O_ACCMODE) == O_RDONLY) {
- errno = EBADF;
- return 0;
- }
-
- if (__FILE(stream)->flags & _IO_ERR) {
- errno = EIO;
- return 0;
- }
-
- LIBC_LOCK(__FILE(stream)->lock);
-
- if (__FILE(stream)->type == _IONBF) {
- ssize_t result = write(__FILE(stream)->fd, data, total_bytes);
- LIBC_UNLOCK(__FILE(stream)->lock);
-
- if (result < 0) {
- __FILE(stream)->flags |= _IO_ERR;
- return 0;
- }
-
- return result == (ssize_t)total_bytes ? nitems : result / size;
- }
-
- size_t remaining = total_bytes;
-
- while (remaining > 0) {
- size_t space_available =
- __FILE(stream)->buf_size - __FILE(stream)->buf_len;
-
- if (space_available == 0) {
- LIBC_UNLOCK(__FILE(stream)->lock);
- if (fflush(stream) != 0) {
- return written / size;
- }
- space_available = __FILE(stream)->buf_size;
- }
-
- size_t to_copy = remaining < space_available ? remaining :
- space_available;
-
- memcpy(__FILE(stream)->buf + __FILE(stream)->buf_len,
- data + written, to_copy);
- __FILE(stream)->buf_len += to_copy;
- written += to_copy;
- remaining -= to_copy;
-
- if (__FILE(stream)->type == _IOLBF) {
- char *newline_pos = memchr(
- __FILE(stream)->buf + __FILE(stream)->buf_len -
- to_copy,
- '\n', to_copy);
- if (newline_pos != NULL) {
- LIBC_UNLOCK(__FILE(stream)->lock);
- if (fflush(stream) != 0) {
- return written / size;
- }
- }
- }
-
- else if (__FILE(stream)->type == _IOFBF &&
- __FILE(stream)->buf_len == __FILE(stream)->buf_size) {
- LIBC_UNLOCK(__FILE(stream)->lock);
- if (fflush(stream) != 0) {
- return written / size;
- }
- }
- }
+ size_t r;
- LIBC_UNLOCK(__FILE(stream)->lock);
+ flockfile(stream);
+ r = fwrite_unlocked(ptr, size, nitems, stream);
+ funlockfile(stream);
- return written == total_bytes ? nitems : written / size;
+ return r;
}
diff --git a/lib/libc/stdio/fwrite_unlocked.c b/lib/libc/stdio/fwrite_unlocked.c
new file mode 100644
index 00000000..dd5f4c0b
--- /dev/null
+++ b/lib/libc/stdio/fwrite_unlocked.c
@@ -0,0 +1,106 @@
+#include "__stdio.h"
+#include <atomic.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+extern void __libc_init_io(void);
+void *__libc_force_io_init = (void *)__libc_init_io;
+
+size_t fwrite_unlocked(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream)
+{
+ size_t total_bytes;
+ size_t written = 0;
+ const char *data = (const char *)ptr;
+
+ if (ptr == NULL || stream == NULL || size == 0) {
+ if (size == 0) {
+ return nitems;
+ }
+ errno = EINVAL;
+ return 0;
+ }
+
+ if (__builtin_mul_overflow(size, nitems, &total_bytes)) {
+ errno = EOVERFLOW;
+ return 0;
+ }
+
+ if ((stream->flags & O_ACCMODE) == O_RDONLY) {
+ errno = EBADF;
+ return 0;
+ }
+
+ if (stream->flags & _IO_ERR) {
+ errno = EIO;
+ return 0;
+ }
+
+ /* Handle in-memory buffer case (e.g., string streams) */
+ if (stream->fd == -1 && stream->buf != NULL) {
+ size_t space_left = (stream->buf_size > stream->buf_len) ?
+ stream->buf_size - stream->buf_len - 1 /* Reserve for '\0' */
+ :
+ 0;
+ if (space_left == 0) {
+ return 0;
+ }
+ size_t to_copy = (total_bytes < space_left) ? total_bytes : space_left;
+ if (to_copy > 0) {
+ memcpy(stream->buf + stream->buf_len, data, to_copy);
+ stream->buf_len += to_copy;
+ }
+ return (to_copy == total_bytes) ? nitems : to_copy / size;
+ }
+
+ if (stream->type != _IONBF && stream->buf == NULL) {
+ errno = EIO;
+ return 0;
+ }
+
+ /* Unbuffered mode: direct write */
+ if (stream->type == _IONBF) {
+ ssize_t result = write(stream->fd, data, total_bytes);
+ if (result < 0) {
+ stream->flags |= _IO_ERR;
+ return 0;
+ }
+ return (result == (ssize_t)total_bytes) ? nitems : result / size;
+ }
+
+ size_t remaining = total_bytes;
+ while (remaining > 0) {
+ size_t space_available = stream->buf_size - stream->buf_len;
+ if (space_available == 0) {
+ if (fflush_unlocked(stream) != 0) {
+ return written / size;
+ }
+ space_available = stream->buf_size;
+ }
+ size_t to_copy = (remaining < space_available) ? remaining : space_available;
+ memcpy(stream->buf + stream->buf_len, data + written, to_copy);
+ stream->buf_len += to_copy;
+ written += to_copy;
+ remaining -= to_copy;
+
+ /* Line-buffered: flush on newline in the copied chunk */
+ if (stream->type == _IOLBF) {
+ char *newline_pos = memchr(stream->buf + stream->buf_len - to_copy, '\n', to_copy);
+ if (newline_pos != NULL) {
+ if (fflush_unlocked(stream) != 0) {
+ return written / size;
+ }
+ }
+ } else if (stream->type == _IOFBF && stream->buf_len == stream->buf_size) {
+ /* Full-buffered: flush when buffer is full */
+ if (fflush_unlocked(stream) != 0) {
+ return written / size;
+ }
+ }
+ }
+
+ return (written == total_bytes) ? nitems : written / size;
+}
diff --git a/lib/libc/stdio/getc.c b/lib/libc/stdio/getc.c
index 242c8396..2f59ba5c 100644
--- a/lib/libc/stdio/getc.c
+++ b/lib/libc/stdio/getc.c
@@ -1,9 +1,12 @@
-#include <libc.h> // for weak_reference
-#include <stdio.h> // for fgetc, FILE, getc, getc_unlocked
+#include <stdio.h>
int getc(FILE *stream)
{
- return fgetc(stream);
-}
+ int r;
+
+ flockfile(stream);
+ r = getc_unlocked(stream);
+ funlockfile(stream);
-weak_reference(getc, getc_unlocked);
+ return r;
+}
diff --git a/lib/libc/stdio/getc_unlocked.c b/lib/libc/stdio/getc_unlocked.c
new file mode 100644
index 00000000..1fc46d0a
--- /dev/null
+++ b/lib/libc/stdio/getc_unlocked.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int getc_unlocked(FILE *stream)
+{
+ return fgetc_unlocked(stream);
+}
diff --git a/lib/libc/stdio/getchar.c b/lib/libc/stdio/getchar.c
index d26c3c6b..d5e08cd1 100644
--- a/lib/libc/stdio/getchar.c
+++ b/lib/libc/stdio/getchar.c
@@ -1,9 +1,12 @@
-#include <libc.h> // for weak_reference
-#include <stdio.h> // for fgetc, getchar, getchar_unlocked, stdin
+#include <stdio.h>
int getchar(void)
{
- return fgetc(stdin);
-}
+ int r;
+
+ flockfile(stdin);
+ r = getchar_unlocked();
+ funlockfile(stdin);
-weak_reference(getchar, getchar_unlocked);
+ return r;
+}
diff --git a/lib/libc/stdio/getchar_unlocked.c b/lib/libc/stdio/getchar_unlocked.c
new file mode 100644
index 00000000..e7b2fed2
--- /dev/null
+++ b/lib/libc/stdio/getchar_unlocked.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int getchar_unlocked(void)
+{
+ return fgetc_unlocked(stdin);
+}
diff --git a/lib/libc/stdio/pclose.c b/lib/libc/stdio/pclose.c
index a515981c..1967b2c8 100644
--- a/lib/libc/stdio/pclose.c
+++ b/lib/libc/stdio/pclose.c
@@ -6,5 +6,5 @@ int pclose(FILE *stream)
{
int stat;
fclose(stream);
- return (waitpid(__FILE(stream)->pid, &stat, 0) < 0) ? -1 : stat;
+ return (waitpid(stream->pid, &stat, 0) < 0) ? -1 : stat;
}
diff --git a/lib/libc/stdio/popen.c b/lib/libc/stdio/popen.c
index 1fd5f991..5720fba3 100644
--- a/lib/libc/stdio/popen.c
+++ b/lib/libc/stdio/popen.c
@@ -62,7 +62,7 @@ FILE *popen(const char *command, const char *mode)
close(pipefd[0]);
}
- __FILE(stream)->pid = pid;
+ stream->pid = pid;
return stream;
}
diff --git a/lib/libc/stdio/putchar.c b/lib/libc/stdio/putchar.c
index c9e3ba08..c0673473 100644
--- a/lib/libc/stdio/putchar.c
+++ b/lib/libc/stdio/putchar.c
@@ -1,9 +1,12 @@
-#include <libc.h> // for weak_reference
-#include <stdio.h> // for putc, putchar, putchar_unlocked, stdout
+#include <stdio.h>
int putchar(int c)
{
- return putc(c, stdout);
-}
+ int r;
+
+ flockfile(stdout);
+ r = putchar_unlocked(c);
+ funlockfile(stdout);
-weak_reference(putchar, putchar_unlocked);
+ return r;
+}
diff --git a/lib/libc/stdio/putchar_unlocked.c b/lib/libc/stdio/putchar_unlocked.c
new file mode 100644
index 00000000..a8a5fc47
--- /dev/null
+++ b/lib/libc/stdio/putchar_unlocked.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int putchar_unlocked(int c)
+{
+ return fputc_unlocked(c, stdout);
+}
diff --git a/lib/libc/stdio/setvbuf.c b/lib/libc/stdio/setvbuf.c
index 686640f4..d6b41d31 100644
--- a/lib/libc/stdio/setvbuf.c
+++ b/lib/libc/stdio/setvbuf.c
@@ -10,13 +10,13 @@ int setvbuf(FILE *restrict stream, char *restrict buf, int type, size_t size)
if (type != _IONBF && (buf == NULL || size == 0))
return -1;
- if (__FILE(stream)->fd < 0)
+ if (stream->fd < 0)
return -1;
- __FILE(stream)->buf = buf;
- __FILE(stream)->buf_size = size;
- __FILE(stream)->buf_pos = 0;
- __FILE(stream)->type = type;
+ stream->buf = buf;
+ stream->buf_size = size;
+ stream->buf_pos = 0;
+ stream->type = type;
return 0;
}
diff --git a/lib/libc/stdio/stderr.c b/lib/libc/stdio/stderr.c
deleted file mode 100644
index ec115fd0..00000000
--- a/lib/libc/stdio/stderr.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "__stdio.h" // for __FILE
-#include "stdatomic.h" // for ATOMIC_FLAG_INIT
-
-#include <fcntl.h> // for O_WRONLY
-#include <stdio.h> // for FILE, stderr
-#include <unistd.h> // for STDERR_FILENO
-
-#define BUFSIZ 4096
-
-struct __FILE __stderr = { .fd = STDERR_FILENO,
- .flags = O_WRONLY,
- .type = 0,
- .buf = 0,
- .buf_len = 0,
- .buf_size = 0,
- .buf_pos = 0,
- .eof = 0,
- .unget_cnt = 0,
- .next = 0,
- .offset = 0,
- .lock = ATOMIC_FLAG_INIT };
-
-FILE *const stderr = (FILE *)&__stderr;
diff --git a/lib/libc/stdio/stdin.c b/lib/libc/stdio/stdin.c
deleted file mode 100644
index 0d127efa..00000000
--- a/lib/libc/stdio/stdin.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "__stdio.h" // for __FILE
-
-#include <fcntl.h> // for O_RDONLY
-#include <stdio.h> // for FILE, stdin
-#include <sys/cdefs.h>
-#include <unistd.h> // for STDOUT_FILENO
-
-#define BUFSIZ 4096
-
-__weak char __stdin_buffer[0];
-struct __FILE __stdin = { .fd = STDOUT_FILENO,
- .flags = O_RDONLY,
- .buf = __stdin_buffer,
- .type = 0x0,
- .buf_size = BUFSIZ,
- .buf_pos = 0,
- .offset = 0 };
-
-FILE *const stdin = (FILE *)&__stdin;
diff --git a/lib/libc/stdio/stdout.c b/lib/libc/stdio/stdout.c
deleted file mode 100644
index 471a54b9..00000000
--- a/lib/libc/stdio/stdout.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include "__stdio.h" // for __FILE, __libc_fadd
-
-#include <atomic.h> // for LIBC_LOCK, LIBC_UNLOCK
-#include <fcntl.h> // for O_WRONLY
-#include <stddef.h> // for NULL
-#include <stdio.h> // for stdout
-#include <sys/cdefs.h>
-#include <unistd.h> // for STDOUT_FILENO
-
-#define BUFSIZ 4096
-
-__weak char __stdout_buffer[0];
-static atomic_flag __stdio_lock = ATOMIC_FLAG_INIT;
-struct __FILE __stdout = { .fd = STDOUT_FILENO,
- .flags = O_WRONLY,
- .type = 1,
- .buf = __stdout_buffer,
- .buf_len = 0,
- .buf_size = BUFSIZ,
- .buf_pos = 0,
- .eof = 0,
- .unget_cnt = 0,
- .offset = 0,
- .next = NULL,
- .lock = ATOMIC_FLAG_INIT };
-
-struct __FILE *const stdout = (struct __FILE *)&__stdout;
-
-void __libc_fadd(struct __FILE *f)
-{
- LIBC_LOCK(__stdio_lock);
- struct __FILE *cur = &__stdout;
- while (cur->next)
- cur = cur->next;
- cur->next = f;
- LIBC_UNLOCK(__stdio_lock);
-}
diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c
index 06609046..4dc1a4d2 100644
--- a/lib/libc/stdio/vfprintf.c
+++ b/lib/libc/stdio/vfprintf.c
@@ -1,13 +1,13 @@
-#include <ctype.h> // for isdigit
-#include <errno.h> // for EINVAL, errno
-#include <math.h> // for isinf, isnan
-#include <stdarg.h> // for va_arg
-#include <stddef.h> // for NULL, ptrdiff_t
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stddef.h>
#include <stdint.h>
-#include <stdint.h> // for uintptr_t, intmax_t, uintmax_t
-#include <stdio.h> // for fwrite, fputc, vfprintf, FILE, va_list
-#include <string.h> // for memmove, strlcpy, strlen
-#include <sys/types.h> // for size_t, ssize_t
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
static double __frexp(double x, int *e)
{
@@ -35,8 +35,7 @@ static double __frexp(double x, int *e)
return y.d;
}
-extern char *dtoa(double, int mode, int ndigits, int *decpt, int *sign,
- char **rve);
+extern char *dtoa(double, int mode, int ndigits, int *decpt, int *sign, char **rve);
extern void freedtoa(char *s);
static int utoa_base(unsigned long long v, char *s, int b, int p, int u)
@@ -65,12 +64,14 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
const char *ptr;
int total_printed;
+ flockfile(stream);
+
ptr = format;
total_printed = 0;
while (*ptr != '\0') {
if (*ptr != '%') {
- fputc(*ptr, stream);
+ fputc_unlocked(*ptr, stream);
total_printed++;
ptr++;
} else {
@@ -104,8 +105,7 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
LENGTH_CAPL
} length = LENGTH_NONE;
- while (*ptr == '-' || *ptr == '+' || *ptr == ' ' ||
- *ptr == '0' || *ptr == '#') {
+ while (*ptr == '-' || *ptr == '+' || *ptr == ' ' || *ptr == '0' || *ptr == '#') {
if (*ptr == '-')
flags |= FLAG_MINUS;
else if (*ptr == '+')
@@ -143,8 +143,7 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
} else {
precision = 0;
while (isdigit(*ptr)) {
- precision = precision * 10 +
- (*ptr - '0');
+ precision = precision * 10 + (*ptr - '0');
ptr++;
}
}
@@ -196,7 +195,7 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
val = va_arg(ap, int);
break;
case LENGTH_HH:
- val = (signed char)va_arg(ap, int);
+ val = (unsigned char)va_arg(ap, int);
break;
case LENGTH_H:
val = (short)va_arg(ap, int);
@@ -218,6 +217,7 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
break;
case LENGTH_CAPL:
errno = EINVAL;
+ funlockfile(stream);
return -1;
}
@@ -261,12 +261,10 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
val = va_arg(ap, unsigned int);
break;
case LENGTH_HH:
- val = (unsigned char)va_arg(
- ap, unsigned int);
+ val = (unsigned char)va_arg(ap, unsigned int);
break;
case LENGTH_H:
- val = (unsigned short)va_arg(
- ap, unsigned int);
+ val = (unsigned short)va_arg(ap, unsigned int);
break;
case LENGTH_L:
val = va_arg(ap, unsigned long);
@@ -285,24 +283,20 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
break;
case LENGTH_CAPL:
errno = EINVAL;
+ funlockfile(stream);
return -1;
}
if (fmt_char == 'o') {
- l = utoa_base(val, buf, 8, precision,
- 0);
+ l = utoa_base(val, buf, 8, precision, 0);
} else if (fmt_char == 'u') {
- l = utoa_base(val, buf, 10, precision,
- 0);
+ l = utoa_base(val, buf, 10, precision, 0);
} else if (fmt_char == 'x') {
- l = utoa_base(val, buf, 16, precision,
- 0);
+ l = utoa_base(val, buf, 16, precision, 0);
} else if (fmt_char == 'X') {
- l = utoa_base(val, buf, 16, precision,
- 1);
+ l = utoa_base(val, buf, 16, precision, 1);
} else {
- l = utoa_base(val, buf, 10, precision,
- 0);
+ l = utoa_base(val, buf, 10, precision, 0);
}
s = buf;
@@ -350,11 +344,7 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
int pos = 0;
if (isnan(val)) {
- strlcpy(buf,
- (*ptr == 'F' || *ptr == 'E' ||
- *ptr == 'G') ?
- "NAN" :
- "nan",
+ strlcpy(buf, (*ptr == 'F' || *ptr == 'E' || *ptr == 'G') ? "NAN" : "nan",
sizeof(buf));
l = 3;
break;
@@ -367,11 +357,7 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
} else if (flags & FLAG_SPACE) {
buf[pos++] = ' ';
}
- strlcpy(buf + pos,
- (*ptr == 'F' || *ptr == 'E' ||
- *ptr == 'G') ?
- "INF" :
- "inf",
+ strlcpy(buf + pos, (*ptr == 'F' || *ptr == 'E' || *ptr == 'G') ? "INF" : "inf",
sizeof(buf) - pos);
l = pos + 3;
break;
@@ -391,58 +377,40 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
case 'F': {
int decpt, sign;
char *rve;
- char *digits = dtoa(val, 3, precision,
- &decpt, &sign,
- &rve);
+ char *digits = dtoa(val, 3, precision, &decpt, &sign, &rve);
if (sign && val != 0.0) {
buf[pos++] = '-';
}
- if (decpt <= 1 && digits[0] == '0' &&
- digits[1] == '\0') {
+ if (decpt <= 1 && digits[0] == '0' && digits[1] == '\0') {
buf[pos++] = '0';
if (precision > 0) {
buf[pos++] = '.';
- for (int i = 0;
- i < precision;
- i++) {
- buf[pos++] =
- '0';
+ for (int i = 0; i < precision; i++) {
+ buf[pos++] = '0';
}
}
} else if (decpt <= 0) {
buf[pos++] = '0';
if (precision > 0) {
buf[pos++] = '.';
- for (int i = 0;
- i < -decpt &&
- i < precision;
- i++) {
- buf[pos++] =
- '0';
+ for (int i = 0; i < -decpt && i < precision; i++) {
+ buf[pos++] = '0';
}
- int remaining =
- precision +
- decpt;
+ int remaining = precision + decpt;
char *d = digits;
- while (*d &&
- remaining-- >
- 0) {
- buf[pos++] =
- *d++;
+ while (*d && remaining-- > 0) {
+ buf[pos++] = *d++;
}
- while (remaining-- >
- 0) {
- buf[pos++] =
- '0';
+ while (remaining-- > 0) {
+ buf[pos++] = '0';
}
}
} else {
char *d = digits;
int digits_used = 0;
- for (int i = 0; i < decpt && *d;
- i++) {
+ for (int i = 0; i < decpt && *d; i++) {
buf[pos++] = *d++;
digits_used++;
}
@@ -452,15 +420,11 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
}
if (precision > 0) {
buf[pos++] = '.';
- for (int i = 0;
- i < precision;
- i++) {
+ for (int i = 0; i < precision; i++) {
if (*d) {
- buf[pos++] =
- *d++;
+ buf[pos++] = *d++;
} else {
- buf[pos++] =
- '0';
+ buf[pos++] = '0';
}
}
}
@@ -475,9 +439,7 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
case 'E': {
int decpt, sign;
char *rve;
- char *digits =
- dtoa(val, 2, precision + 1,
- &decpt, &sign, &rve);
+ char *digits = dtoa(val, 2, precision + 1, &decpt, &sign, &rve);
if (sign && val != 0.0) {
buf[pos++] = '-';
@@ -491,14 +453,11 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
if (precision > 0) {
buf[pos++] = '.';
- for (int i = 0; i < precision;
- i++) {
+ for (int i = 0; i < precision; i++) {
if (*digits) {
- buf[pos++] =
- *digits++;
+ buf[pos++] = *digits++;
} else {
- buf[pos++] =
- '0';
+ buf[pos++] = '0';
}
}
}
@@ -510,8 +469,7 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
exp = -exp;
if (exp < 10)
buf[pos++] = '0';
- pos += utoa_base(exp, buf + pos, 10, 0,
- 0);
+ pos += utoa_base(exp, buf + pos, 10, 0, 0);
buf[pos] = '\0';
l = pos;
@@ -522,9 +480,7 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
case 'G': {
int decpt, sign;
char *rve;
- char *digits = dtoa(val, 2, precision,
- &decpt, &sign,
- &rve);
+ char *digits = dtoa(val, 2, precision, &decpt, &sign, &rve);
if (sign && val != 0.0) {
buf[pos++] = '-';
@@ -538,63 +494,44 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
if (*digits) {
buf[pos++] = '.';
while (*digits) {
- buf[pos++] =
- *digits++;
+ buf[pos++] = *digits++;
}
}
- buf[pos++] = (*ptr == 'G') ?
- 'E' :
- 'e';
- buf[pos++] = (exp >= 0) ? '+' :
- '-';
+ buf[pos++] = (*ptr == 'G') ? 'E' : 'e';
+ buf[pos++] = (exp >= 0) ? '+' : '-';
if (exp < 0)
exp = -exp;
if (exp < 10)
buf[pos++] = '0';
- pos += utoa_base(exp, buf + pos,
- 10, 0, 0);
+ pos += utoa_base(exp, buf + pos, 10, 0, 0);
} else {
if (decpt <= 0) {
buf[pos++] = '0';
- if (*digits &&
- *digits != '0') {
- buf[pos++] =
- '.';
- for (int i = 0;
- i < -decpt;
- i++) {
- buf[pos++] =
- '0';
+ if (*digits && *digits != '0') {
+ buf[pos++] = '.';
+ for (int i = 0; i < -decpt; i++) {
+ buf[pos++] = '0';
}
- char *d =
- digits;
- while (*d &&
- *d != '0') {
- buf[pos++] =
- *d++;
+ char *d = digits;
+ while (*d && *d != '0') {
+ buf[pos++] = *d++;
}
}
} else {
char *d = digits;
- for (int i = 0;
- i < decpt && *d;
- i++) {
- buf[pos++] =
- *d++;
+ for (int i = 0; i < decpt && *d; i++) {
+ buf[pos++] = *d++;
}
if (*d) {
- buf[pos++] =
- '.';
+ buf[pos++] = '.';
while (*d) {
- buf[pos++] =
- *d++;
+ buf[pos++] = *d++;
}
}
}
}
- while (pos > 1 && buf[pos - 1] == '0' &&
- pos > 2 && buf[pos - 2] != 'e' &&
+ while (pos > 1 && buf[pos - 1] == '0' && pos > 2 && buf[pos - 2] != 'e' &&
buf[pos - 2] != 'E') {
pos--;
}
@@ -634,9 +571,7 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
}
if (val == 0.0) {
- strlcpy(buf + pos,
- upper ? "0X0P+0" : "0x0p+0",
- sizeof(buf) - pos);
+ strlcpy(buf + pos, upper ? "0X0P+0" : "0x0p+0", sizeof(buf) - pos);
l = pos + 6;
break;
}
@@ -662,15 +597,9 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
int digit = (int)mant;
if (digit > 15)
digit = 15;
- buf[pos++] =
- (digit < 10) ?
- ('0' + digit) :
- (upper ? ('A' +
- digit -
- 10) :
- ('a' +
- digit -
- 10));
+ buf[pos++] = (digit < 10) ?
+ ('0' + digit) :
+ (upper ? ('A' + digit - 10) : ('a' + digit - 10));
mant -= digit;
}
@@ -728,9 +657,7 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
case 'p': {
void *ptr_val = va_arg(ap, void *);
uintptr_t uptr = (uintptr_t)ptr_val;
- int len = utoa_base((unsigned long long)uptr,
- buf + 2, 16,
- sizeof(void *) * 2, 0);
+ int len = utoa_base((unsigned long long)uptr, buf + 2, 16, sizeof(void *) * 2, 0);
buf[0] = '0';
buf[1] = 'x';
buf[len + 2] = '\0';
@@ -755,6 +682,7 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
}
default:
errno = EINVAL;
+ funlockfile(stream);
return -1;
}
@@ -767,46 +695,39 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
char format_char = *(ptr - 1);
char pad_char = ' ';
if ((flags & FLAG_ZERO) && !(flags & FLAG_MINUS) &&
- (format_char == 'd' || format_char == 'i' ||
- format_char == 'u' || format_char == 'o' ||
- format_char == 'x' || format_char == 'X' ||
- format_char == 'f' || format_char == 'F' ||
- format_char == 'e' || format_char == 'E' ||
- format_char == 'g' || format_char == 'G') &&
+ (format_char == 'd' || format_char == 'i' || format_char == 'u' || format_char == 'o' ||
+ format_char == 'x' || format_char == 'X' || format_char == 'f' || format_char == 'F' ||
+ format_char == 'e' || format_char == 'E' || format_char == 'g' || format_char == 'G') &&
precision < 0) {
pad_char = '0';
}
if ((flags & FLAG_MINUS) == 0) {
if (pad_char == '0' && s != NULL) {
- if (s[0] == '-' || s[0] == '+' ||
- s[0] == ' ') {
- fwrite(s, 1, 1, stream);
+ if (s[0] == '-' || s[0] == '+' || s[0] == ' ') {
+ fwrite_unlocked(s, 1, 1, stream);
total_printed++;
s++;
l--;
}
- if (l >= 2 && s[0] == '0' &&
- (s[1] == 'x' || s[1] == 'X')) {
- fwrite(s, 1, 2, stream);
+ if (l >= 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
+ fwrite_unlocked(s, 1, 2, stream);
total_printed += 2;
s += 2;
l -= 2;
}
for (int i = 0; i < padding; i++) {
- fwrite("0", 1, 1, stream);
+ fwrite_unlocked("0", 1, 1, stream);
total_printed++;
}
} else {
for (int i = 0; i < padding; i++) {
if (pad_char == '0') {
- fwrite("0", 1, 1,
- stream);
+ fwrite_unlocked("0", 1, 1, stream);
} else {
- fwrite(" ", 1, 1,
- stream);
+ fwrite_unlocked(" ", 1, 1, stream);
}
total_printed++;
}
@@ -815,18 +736,20 @@ int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap)
if (l > 0) {
if (s != NULL)
- fwrite(s, 1, l, stream);
+ fwrite_unlocked(s, 1, l, stream);
total_printed += l;
}
if (flags & FLAG_MINUS) {
for (int i = 0; i < padding; i++) {
- fwrite(" ", 1, 1, stream);
+ fwrite_unlocked(" ", 1, 1, stream);
total_printed++;
}
}
}
}
+ funlockfile(stream);
+
return total_printed;
}