chore(libterm/stdio): printf reworked, vsnprintf() and snprintf()
This commit is contained in:
+8
-4
@@ -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).
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
@@ -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;
|
||||||
}
|
|
||||||
|
|
||||||
static void print_dec(long long n) {
|
|
||||||
if (n < 0) {
|
|
||||||
putchar('-');
|
|
||||||
n = -n;
|
|
||||||
}
|
}
|
||||||
unsigned long long u = (unsigned long long)n;
|
(*written)++;
|
||||||
char buffer[32];
|
|
||||||
int i = 0;
|
|
||||||
do {
|
|
||||||
buffer[i++] = (u % 10) + '0';
|
|
||||||
u /= 10;
|
|
||||||
} while (u > 0);
|
|
||||||
while (--i >= 0) putchar(buffer[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_hex(unsigned long long u, int padding) {
|
int vsnprintf(char* str, u64 size, const char* fmt, va_list args) {
|
||||||
char buffer[16];
|
u64 written = 0;
|
||||||
int i = 0;
|
for (u32 i = 0; fmt[i] != '\0'; i++) {
|
||||||
const char* hex_chars = "0123456789ABCDEF";
|
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) {
|
||||||
|
buf_add(str, size, &written, '-');
|
||||||
|
n = -n;
|
||||||
|
}
|
||||||
|
u64 u = (u64)n;
|
||||||
|
char tmp[32];
|
||||||
|
i32 pos = 0;
|
||||||
|
if (u == 0) tmp[pos++] = '0';
|
||||||
|
while (u > 0) {
|
||||||
|
tmp[pos++] = (u % 10) + '0';
|
||||||
|
u /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
while (pos > 0) buf_add(str, size, &written, tmp[--pos]);
|
||||||
buffer[i++] = hex_chars[u % 16];
|
break;
|
||||||
u /= 16;
|
}
|
||||||
} while (u > 0);
|
case 'x':
|
||||||
|
case 'X': {
|
||||||
|
u64 u = va_arg(args, unsigned long long);
|
||||||
|
u8 padding = (fmt[i] == 'X') ? 16 : 0;
|
||||||
|
|
||||||
while (i < padding) buffer[i++] = '0';
|
char tmp[32];
|
||||||
|
int pos = 0;
|
||||||
|
const char* hex = "0123456789ABCDEF";
|
||||||
|
|
||||||
print_str("0x");
|
if (u == 0 && padding == 0) tmp[pos++] = '0';
|
||||||
while (--i >= 0) putchar(buffer[i]);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user