Files
termOS/userspace/libterm/src/stdio.c
T

185 lines
4.6 KiB
C

// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <stdio.h>
#include <stdarg.h>
#include <types.h>
#include <string.h>
#define EOF (-1)
#define PRINTF_BUFFER_SIZE 1024
extern UInt64 sys_read(UInt64 fd, void* buf, UInt64 len);
extern UInt64 sys_write(UInt64 fd, const void* buf, UInt64 len);
static void putchar(char c) {
sys_write(1, &c, 1);
}
static inline void buf_add(char* str, UInt64 size, UInt64* written, char c) {
if (*written < size - 1 && size > 0) {
str[*written] = c;
}
(*written)++;
}
int vsnprintf(char* str, UInt64 size, const char* fmt, va_list args) {
UInt64 written = 0;
for (UInt32 i = 0; fmt[i] != '\0'; i++) {
if (fmt[i] == '%') {
i++;
if (fmt[i] == '\0') break;
switch (fmt[i]) {
case 's': {
const char* s = va_arg(args, const char*);
if (!s) s = "(null)";
while (*s) buf_add(str, size, &written, *s++);
break;
}
case 'c': {
char c = (char)va_arg(args, int);
buf_add(str, size, &written, c);
break;
}
case 'd': {
Int64 n = va_arg(args, int);
if (n < 0) {
buf_add(str, size, &written, '-');
n = -n;
}
UInt64 u = (UInt64)n;
char tmp[32];
Int32 pos = 0;
if (u == 0) tmp[pos++] = '0';
while (u > 0) {
tmp[pos++] = (u % 10) + '0';
u /= 10;
}
while (pos > 0) buf_add(str, size, &written, tmp[--pos]);
break;
}
case 'x':
case 'X': {
UInt64 u = va_arg(args, unsigned long long);
UInt8 padding = (fmt[i] == 'X') ? 16 : 0;
char tmp[32];
int pos = 0;
const char* hex = "0123456789ABCDEF";
if (u == 0 && padding == 0) tmp[pos++] = '0';
while (u > 0) {
tmp[pos++] = hex[u % 16];
u /= 16;
}
while (pos < padding) tmp[pos++] = '0';
while (pos > 0) buf_add(str, size, &written, tmp[--pos]);
break;
}
case '%': {
buf_add(str, size, &written, '%');
break;
}
default: {
buf_add(str, size, &written, '%');
buf_add(str, size, &written, fmt[i]);
break;
}
}
} else {
buf_add(str, size, &written, fmt[i]);
}
}
if (size > 0) {
if (written < size) str[written] = '\0';
else str[size - 1] = '\0';
}
return (int)written;
}
int snprintf(char* str, usize size, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
int ret = vsnprintf(str, size, fmt, args);
va_end(args);
return ret;
}
int printf(const char *fmt, ...) {
char buf[PRINTF_BUFFER_SIZE];
va_list args;
va_start(args, fmt);
int len = vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
UInt64 write_len = ((UInt64)len < sizeof(buf)) ? len : (sizeof(buf) - 1);
sys_write(1, buf, write_len);
return (int)write_len;
}
int getchar() {
char c;
unsigned long long res = sys_read(0, &c, 1);
if (res <= 0) return EOF;
return (int)(unsigned char)c;
}
char* gets(char* str) {
int i = 0;
int c;
while (1) {
c = getchar();
if (c == EOF || c == '\n' || c == '\r') {
break;
}
str[i++] = (char)c;
char ch = (char)c;
sys_write(1, &ch, 1);
}
str[i] = '\0';
char nl = '\n';
sys_write(1, &nl, 1);
return str;
}
char* gets_s(char* str, UInt64 size) {
if (size == 0) return str;
UInt64 i = 0;
int c;
while (i < size - 1) {
c = getchar();
if (c == EOF || c == '\n' || c == '\r') break;
if (c == '\b') {
if (i > 0) {
i--;
printf("\b \b");
}
continue;
}
str[i++] = (char)c;
putchar(c);
}
str[i] = '\0';
putchar('\n');
return str;
}