diff options
| author | EmulatedSeasons <89668582+EmulatedSeasons@users.noreply.github.com> | 2023-06-15 22:36:39 -0400 |
|---|---|---|
| committer | EmulatedSeasons <89668582+EmulatedSeasons@users.noreply.github.com> | 2023-06-15 22:36:39 -0400 |
| commit | a78033acc941fc4bcf6188f1d48fd8e012673fff (patch) | |
| tree | ac92adae5e40274fd9e0b78352a24840cc88eab4 /kernel/std/printf.c | |
initial commit
Diffstat (limited to 'kernel/std/printf.c')
| -rw-r--r-- | kernel/std/printf.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/kernel/std/printf.c b/kernel/std/printf.c new file mode 100644 index 0000000..c383cad --- /dev/null +++ b/kernel/std/printf.c @@ -0,0 +1,80 @@ +#include <limits.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+static bool print(const char* data, size_t length) {
+ const unsigned char* bytes = (const unsigned char*) data;
+ for (size_t i = 0; i < length; i++)
+ if (putchar(bytes[i]) == EOF)
+ return false;
+ return true;
+}
+
+int printf(const char* restrict format, ...) {
+ va_list parameters;
+ va_start(parameters, format);
+
+ int written = 0;
+
+ while (*format != '\0') {
+ size_t maxrem = INT_MAX - written;
+
+ if (format[0] != '%' || format[1] == '%') {
+ if (format[0] == '%')
+ format++;
+ size_t amount = 1;
+ while (format[amount] && format[amount] != '%')
+ amount++;
+ if (maxrem < amount) {
+ // TODO: Set errno to EOVERFLOW.
+ return -1;
+ }
+ if (!print(format, amount))
+ return -1;
+ format += amount;
+ written += amount;
+ continue;
+ }
+
+ const char* format_begun_at = format++;
+
+ if (*format == 'c') {
+ format++;
+ char c = (char) va_arg(parameters, int /* char promotes to int */);
+ if (!maxrem) {
+ // TODO: Set errno to EOVERFLOW.
+ return -1;
+ }
+ if (!print(&c, sizeof(c)))
+ return -1;
+ written++;
+ } else if (*format == 's') {
+ format++;
+ const char* str = va_arg(parameters, const char*);
+ size_t len = strlen(str);
+ if (maxrem < len) {
+ // TODO: Set errno to EOVERFLOW.
+ return -1;
+ }
+ if (!print(str, len))
+ return -1;
+ written += len;
+ } else {
+ format = format_begun_at;
+ size_t len = strlen(format);
+ if (maxrem < len) {
+ // TODO: Set errno to EOVERFLOW.
+ return -1;
+ }
+ if (!print(format, len))
+ return -1;
+ written += len;
+ format += len;
+ }
+ }
+
+ va_end(parameters);
+ return written;
+}
\ No newline at end of file |
