summaryrefslogtreecommitdiff
path: root/src/init
diff options
context:
space:
mode:
Diffstat (limited to 'src/init')
-rw-r--r--src/init/stdlib.c76
1 files changed, 3 insertions, 73 deletions
diff --git a/src/init/stdlib.c b/src/init/stdlib.c
index 82410d6..e928d2c 100644
--- a/src/init/stdlib.c
+++ b/src/init/stdlib.c
@@ -1,6 +1,6 @@
#include <init/stdlib.h>
+#include <shared/printf.h>
#include <shared/syscalls.h>
-#include <stdarg.h>
int __stdin = -1;
int __stdout = -1;
@@ -9,82 +9,12 @@ static void backend_file(void *arg, const char *buf, size_t len) {
_syscall_write(*(handle_t*)arg, buf, len, -1);
}
-static int __printf_internal(const char *fmt, va_list argp,
- void (*back)(void*, const char*, size_t), void *back_arg)
-{
- const char *seg = fmt; // beginning of the current segment
- int total = 0;
-
- for (;;) {
- char c = *fmt++;
- switch (c) {
- case '\0':
- back(back_arg, seg, fmt - seg - 1);
- return total + (fmt - seg - 1);
-
- case '%':
- back(back_arg, seg, fmt - seg - 1);
- total += fmt - seg - 1;
- size_t pad_len = 0;
-
- c = *fmt++;
- while (1) {
- switch (c) {
- case '0':
- pad_len = *fmt++ - '0'; // can skip over the null byte, idc
- break;
- default:
- goto modifier_break;
- }
- c = *fmt++;
- }
-modifier_break:
- switch (c) {
- case 'c':
- char c = va_arg(argp, int);
- back(back_arg, &c, 1);
- total += 1;
- break;
-
- case 's':
- const char *s = va_arg(argp, char*);
- if (s) {
- back(back_arg, s, strlen(s));
- total += strlen(s);
- }
- break;
-
- case 'x':
- unsigned int n = va_arg(argp, int);
- size_t i = 4; // nibbles * 4
- while (n >> i && i < (sizeof(int) * 8))
- i += 4;
-
- if (i < pad_len * 4)
- i = pad_len * 4;
-
- while (i > 0) {
- i -= 4;
- char h = '0' + ((n >> i) & 0xf);
- if (h > '9') h += 'a' - '9' - 1;
- back(back_arg, &h, 1);
- total++;
- }
- break;
- }
- seg = fmt;
- break;
- }
- }
-}
-
int printf(const char *fmt, ...) {
int ret = 0;
va_list argp;
va_start(argp, fmt);
- if (__stdout < 0) goto end;
- __printf_internal(fmt, argp, backend_file, (void*)&__stdout);
-end:
+ if (__stdout >= 0)
+ ret = __printf_internal(fmt, argp, backend_file, (void*)&__stdout);
va_end(argp);
return ret;
}