chore(libterm/stdio): printf reworked, vsnprintf() and snprintf()

This commit is contained in:
Karina
2026-01-30 20:22:45 +04:00
parent 52d0bfeaae
commit e323e91dac
5 changed files with 115 additions and 57 deletions
+8 -4
View File
@@ -23,12 +23,11 @@
### v0.5.4 (The Shell Update) ### v0.5.4 (The Shell Update)
*Focus: Interactive Userspace* *Focus: Interactive Userspace*
- [ ] **Userspace Shell (`termosh`)** - [x] **Userspace Shell (`termosh`)**
- Porting `ksh` logic into a standalone `.hot` binary. - Porting `ksh` logic into a standalone `.hot` binary.
- Standard I/O abstraction (stdin/stdout) to pass keyboard input to active process. - Standard I/O abstraction (stdin/stdout) to pass keyboard input to active process.
- [ ] **Basic Utils** - [ ] ~~**Basic Utils** (`ls`, `cat`, `echo`)~~ *(Moved to v0.6.1 — awaiting Apple-style API)*
- `ls`, `cat`, `echo`, `ver` as standalone programs.
- Remove built-in commands from the kernel.
--- ---
@@ -36,6 +35,11 @@
*Goal: Total independence from external libraries and architectural hygiene.* *Goal: Total independence from external libraries and architectural hygiene.*
### v0.6.0 (Architecture Overhaul) ### v0.6.0 (Architecture Overhaul)
- [ ] **System-wide Naming & API Refactoring (Apple-style)**
- Replace generic types with PascalCase branding (`u64` -> `UInt64`, `i32` -> `Int32`).
- Standardize system prefixes: `VM` for Virtual Memory, `OS` for Core, `CPU` for HAL.
- Transition from `snake_case` to `PascalCase` for all kernel functions and structures.
- Implement `OSReturn` status codes for unified error handling.
- [ ] **Bootloader Independence** - [ ] **Bootloader Independence**
- Remove `posix-uefi` library. - Remove `posix-uefi` library.
- Write custom UEFI entry point (pure PE). - Write custom UEFI entry point (pure PE).
+6 -4
View File
@@ -2,11 +2,13 @@
// Copyright (c) 2026 0xKarinyash // Copyright (c) 2026 0xKarinyash
#include <process.h> #include <process.h>
#include <stdio.h>
#include <malloc.h> #include <malloc.h>
// TODO: read .cfg and spawn what stated there
int main() { int main() {
wait(spawn("/bin/termosh")); // TODO: read .cfg and spawn what stated there while (1) {
printf("\nbaiii"); i32 pid = spawn("/bin/termosh");
return 0; if (pid < 0) return pid;
wait(pid);
}
} }
+2 -1
View File
@@ -4,7 +4,8 @@
#pragma once #pragma once
#include <types.h> #include <types.h>
void printf(const char *fmt, ...); int printf(const char *fmt, ...);
int snprintf(char* str, u64 size, const char* fmt, ...);
int getchar(); int getchar();
char* gets(char* str); char* gets(char* str);
char* gets_s(char* str, u64 size); char* gets_s(char* str, u64 size);
+89 -42
View File
@@ -7,6 +7,7 @@
#include <string.h> #include <string.h>
#define EOF (-1) #define EOF (-1)
#define PRINTF_BUFFER_SIZE 1024
extern u64 sys_read(u64 fd, void* buf, u64 len); extern u64 sys_read(u64 fd, void* buf, u64 len);
extern u64 sys_write(u64 fd, const void* buf, u64 len); extern u64 sys_write(u64 fd, const void* buf, u64 len);
@@ -15,65 +16,111 @@ static void putchar(char c) {
sys_write(1, &c, 1); sys_write(1, &c, 1);
} }
static void print_str(const char* str) { static inline void buf_add(char* str, u64 size, u64* written, char c) {
if (!str) str = "(null)"; if (*written < size - 1 && size > 0) {
sys_write(1, str, strlen(str)); str[*written] = c;
}
(*written)++;
} }
static void print_dec(long long n) { int vsnprintf(char* str, u64 size, const char* fmt, va_list args) {
u64 written = 0;
for (u32 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': {
i64 n = va_arg(args, int);
if (n < 0) { if (n < 0) {
putchar('-'); buf_add(str, size, &written, '-');
n = -n; n = -n;
} }
unsigned long long u = (unsigned long long)n; u64 u = (u64)n;
char buffer[32]; char tmp[32];
int i = 0; i32 pos = 0;
do { if (u == 0) tmp[pos++] = '0';
buffer[i++] = (u % 10) + '0'; while (u > 0) {
tmp[pos++] = (u % 10) + '0';
u /= 10; u /= 10;
} while (u > 0); }
while (--i >= 0) putchar(buffer[i]);
}
static void print_hex(unsigned long long u, int padding) { while (pos > 0) buf_add(str, size, &written, tmp[--pos]);
char buffer[16]; break;
int i = 0; }
const char* hex_chars = "0123456789ABCDEF"; case 'x':
case 'X': {
u64 u = va_arg(args, unsigned long long);
u8 padding = (fmt[i] == 'X') ? 16 : 0;
do { char tmp[32];
buffer[i++] = hex_chars[u % 16]; 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; u /= 16;
} while (u > 0); }
while (i < padding) buffer[i++] = '0'; 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]);
}
}
print_str("0x"); if (size > 0) {
while (--i >= 0) putchar(buffer[i]); if (written < size) str[written] = '\0';
else str[size - 1] = '\0';
}
return (int)written;
} }
void printf(const char *fmt, ...) { 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_list args;
va_start(args, fmt); va_start(args, fmt);
for (int i = 0; fmt[i] != '\0'; i++) { int len = vsnprintf(buf, sizeof(buf), fmt, args);
if (fmt[i] == '%') {
i++;
switch (fmt[i]) {
case 's': print_str(va_arg(args, const char*)); break;
case 'c': putchar((char)va_arg(args, int)); break;
case 'd': print_dec(va_arg(args, int)); break;
case 'x': print_hex(va_arg(args, unsigned long long), 0); break;
case 'X': print_hex(va_arg(args, unsigned long long), 16); break;
case '%': putchar('%'); break;
default: putchar(fmt[i]); break;
}
}
else {
putchar(fmt[i]);
}
}
va_end(args); va_end(args);
u64 write_len = ((u64)len < sizeof(buf)) ? len : (sizeof(buf) - 1);
sys_write(1, buf, write_len);
return (int)write_len;
} }
int getchar() { int getchar() {
+5 -1
View File
@@ -23,7 +23,11 @@ int main() {
case TOKEN_CLEAR: not_implemented_yet(); break; case TOKEN_CLEAR: not_implemented_yet(); break;
case TOKEN_HELP: not_implemented_yet(); break; case TOKEN_HELP: not_implemented_yet(); break;
case TOKEN_SPAWN: if (tokens_count >= 2) cmd_spawn(tokens[1]); break; case TOKEN_SPAWN: if (tokens_count >= 2) cmd_spawn(tokens[1]); break;
default: printf("Unknown command\n"); break; default: {
char buff[256];
snprintf(buff, sizeof(buff), "/bin/%s", tokens[0]);
cmd_spawn(buff);
}
} }
} }
} }