summaryrefslogtreecommitdiff
path: root/kernel/libc/stdio
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2023-10-30 22:12:14 +0100
committerAnton Kling <anton@kling.gg>2023-10-31 00:18:38 +0100
commit8a9208612eec8ddae4c418485d848ecfa0613699 (patch)
tree2f4b29200c2f0c19ae52f45bdb9b38a41b356e30 /kernel/libc/stdio
parentca76600acc8bf7a02346efa5bd8f17072210ec01 (diff)
Meta: Move kernel and userland to their own folders.
This is to allow both the kernel and the userland to share certain header files and to make the folder structure a bit more clear.
Diffstat (limited to 'kernel/libc/stdio')
-rw-r--r--kernel/libc/stdio/print.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/kernel/libc/stdio/print.c b/kernel/libc/stdio/print.c
new file mode 100644
index 0000000..8174983
--- /dev/null
+++ b/kernel/libc/stdio/print.c
@@ -0,0 +1,97 @@
+#include "../../drivers/serial.h"
+#include "../include/assert.h"
+#include "../include/stdio.h"
+#include <stdarg.h>
+
+#define TAB_SIZE 8
+
+const char HEX_SET[0x10] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+inline void putc(const char c) { write_serial(c); }
+
+int kprint_hex(uint64_t num) {
+ int c = 2;
+
+ if (num == 0) {
+ putc('0');
+ c++;
+ return c;
+ }
+
+ char str[16] = {0};
+ int i = 0;
+ for (; num != 0 && i < 16; i++, num /= 16)
+ str[i] = HEX_SET[(num % 16)];
+
+ c += i;
+ for (i--; i >= 0; i--)
+ putc(str[i]);
+
+ return c;
+}
+
+int kprint_int(int num) {
+ int c = 0;
+ if (0 == num) {
+ putc('0');
+ c++;
+ return c;
+ }
+ char str[10];
+ int i = 0;
+ for (; num != 0 && i < 10; i++, num /= 10)
+ str[i] = (num % 10) + '0';
+
+ c += i;
+ for (i--; i >= 0; i--)
+ putc(str[i]);
+ return c;
+}
+
+int kprintf(const char *format, ...) {
+ int c = 0;
+ va_list list;
+ va_start(list, format);
+
+ const char *s = format;
+ for (; *s; s++) {
+ if ('%' != *s) {
+ putc(*s);
+ c++;
+ continue;
+ }
+
+ char flag = *(s + 1);
+ if ('\0' == flag)
+ break;
+
+ switch (flag) {
+ case 'c':
+ putc((char)va_arg(list, int));
+ c++;
+ break;
+ case 'd':
+ c += kprint_int(va_arg(list, int));
+ break;
+ case 's':
+ for (char *string = va_arg(list, char *); *string; putc(*string++), c++)
+ ;
+ break;
+ case 'x':
+ c += kprint_hex(va_arg(list, const uint32_t));
+ break;
+ case '%':
+ putc('%');
+ c++;
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ break;
+ }
+ s++;
+ }
+ return c;
+}
+
+int puts(char *str) { return kprintf("%s\n", str); }