summaryrefslogtreecommitdiff
path: root/src/user/lib
diff options
context:
space:
mode:
authordzwdz2022-07-29 21:33:15 +0200
committerdzwdz2022-07-29 21:33:15 +0200
commit99da70deba62de235454ef1852745610a9c9f741 (patch)
treed4d1297bd3f1df579362603d40a0f7c57ff15c3b /src/user/lib
parentdf7e4aeeed27c35994bc12614d5ffcb82ec6497b (diff)
user/libc: properly implement snprintf; the v*printf family
Diffstat (limited to 'src/user/lib')
-rw-r--r--src/user/lib/include/stdio.h10
-rw-r--r--src/user/lib/printf.c59
2 files changed, 49 insertions, 20 deletions
diff --git a/src/user/lib/include/stdio.h b/src/user/lib/include/stdio.h
index bf9e09e..fe754da 100644
--- a/src/user/lib/include/stdio.h
+++ b/src/user/lib/include/stdio.h
@@ -1,5 +1,6 @@
#pragma once
#include <bits/file.h>
+#include <stdarg.h>
#include <stddef.h>
#define EOF (-1)
@@ -8,8 +9,13 @@
#define SEEK_CUR 2
#define SEEK_END 3
-int printf(const char *fmt, ...);
-int snprintf(char *str, size_t len, const char *fmt, ...);
+int printf(const char *restrict fmt, ...);
+int fprintf(FILE *restrict f, const char *restrict fmt, ...);
+int snprintf(char *restrict str, size_t len, const char *restrict fmt, ...);
+
+int vprintf(const char *restrict fmt, va_list ap);
+int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap);
+int vsnprintf(char *restrict str, size_t len, const char *restrict fmt, va_list ap);
int _klogf(const char *fmt, ...); // for kernel debugging only
diff --git a/src/user/lib/printf.c b/src/user/lib/printf.c
index 443c424..53b1140 100644
--- a/src/user/lib/printf.c
+++ b/src/user/lib/printf.c
@@ -5,47 +5,70 @@
static void backend_file(void *arg, const char *buf, size_t len) {
- fwrite(buf, 1, len, (FILE *)arg);
+ fwrite(buf, 1, len, arg);
}
-int printf(const char *fmt, ...) {
- int ret = 0;
- va_list argp;
- va_start(argp, fmt);
- ret = __printf_internal(fmt, argp, backend_file, (void*)stdout);
- va_end(argp);
- return ret;
+int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) {
+ return __printf_internal(fmt, ap, backend_file, f);
}
static void backend_buf(void *arg, const char *buf, size_t len) {
char **ptrs = arg;
size_t space = ptrs[1] - ptrs[0];
if (len > space) len = space;
+
memcpy(ptrs[0], buf, len);
ptrs[0] += len;
+ /* ptrs[1] is the last byte of the buffer, it must be 0.
+ * on overflow:
+ * ptrs[0] + (ptrs[1] - ptrs[0]) = ptrs[1] */
+ *ptrs[0] = '\0';
+}
+
+int vsnprintf(char *restrict str, size_t len, const char *restrict fmt, va_list ap) {
+ char *ptrs[2] = {str, str + len - 1};
+ return __printf_internal(fmt, ap, backend_buf, &ptrs);
+}
+
+
+int printf(const char *restrict fmt, ...) {
+ int ret;
+ va_list argp;
+ va_start(argp, fmt);
+ ret = vprintf(fmt, argp);
+ va_end(argp);
+ return ret;
}
-int snprintf(char *str, size_t len, const char *fmt, ...) {
- int ret = 0;
- char *ptrs[2] = {str, str + len};
+int fprintf(FILE *restrict f, const char *restrict fmt, ...) {
+ int ret;
va_list argp;
va_start(argp, fmt);
- ret = __printf_internal(fmt, argp, backend_buf, &ptrs);
+ ret = vfprintf(f, fmt, argp);
va_end(argp);
- if (ptrs[0] < ptrs[1]) *ptrs[0] = '\0';
return ret;
}
+int snprintf(char *restrict str, size_t len, const char *restrict fmt, ...) {
+ int ret;
+ va_list argp;
+ va_start(argp, fmt);
+ ret = vsnprintf(str, len, fmt, argp);
+ va_end(argp);
+ return ret;
+}
+
+int vprintf(const char *restrict fmt, va_list ap) {
+ return vfprintf(stdout, fmt, ap);
+}
+
int _klogf(const char *fmt, ...) {
- // idiotic. however, this hack won't matter anyways
char buf[256];
- int ret = 0;
- char *ptrs[2] = {buf, buf + sizeof buf};
+ int ret;
va_list argp;
va_start(argp, fmt);
- ret = __printf_internal(fmt, argp, backend_buf, &ptrs);
+ ret = vsnprintf(buf, sizeof buf, fmt, argp);
va_end(argp);
- if (ptrs[0] < ptrs[1]) *ptrs[0] = '\0';
_syscall_debug_klog(buf, ret);
return ret;
}