mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-08-04 01:36:10 -04:00
Update printf
This commit is contained in:
parent
1cb20b40d0
commit
d1e190a0f4
4
cpp.mk
4
cpp.mk
@ -4,7 +4,7 @@ OC=x86_64-elf-objcopy
|
||||
AR=x86_64-elf-ar
|
||||
|
||||
WARNING_FLAGS=-Wall -Wextra -pedantic -Wold-style-cast
|
||||
COMMON_CPP_FLAGS=-masm=intel -I../../tstl/include/ -I../tstl/include/ -I../tlib/include/ -Iinclude/ -nostdlib -g -Os -std=c++11 -fno-stack-protector -fno-exceptions -funsigned-char -fno-rtti -ffreestanding -fomit-frame-pointer -mno-red-zone -mno-3dnow -mno-mmx -fno-asynchronous-unwind-tables
|
||||
COMMON_CPP_FLAGS=-masm=intel -I../../tstl/include/ -I../printf/include/ -I../tstl/include/ -I../tlib/include/ -Iinclude/ -nostdlib -g -Os -std=c++11 -fno-stack-protector -fno-exceptions -funsigned-char -fno-rtti -ffreestanding -fomit-frame-pointer -mno-red-zone -mno-3dnow -mno-mmx -fno-asynchronous-unwind-tables
|
||||
|
||||
DISABLE_SSE_FLAGS=-mno-sse -mno-sse2 -mno-sse3 -mno-sse4 -mno-sse4.1 -mno-sse4.2
|
||||
ENABLE_SSE_FLAGS=-msse -msse2 -msse3 -msse4 -msse4.1 -msse4.2
|
||||
@ -25,5 +25,5 @@ KERNEL_LINK_FLAGS=$(COMMON_LINK_FLAGS) -T linker.ld
|
||||
LIB_FLAGS=$(CPP_FLAGS_64) $(WARNING_FLAGS) -mcmodel=small -fPIC -ffunction-sections -fdata-sections
|
||||
LIB_LINK_FLAGS=$(CPP_FLAGS_64) $(WARNING_FLAGS) -mcmodel=small -fPIC -Wl,-gc-sections
|
||||
|
||||
PROGRAM_FLAGS=$(CPP_FLAGS_64) $(WARNING_FLAGS) -I../../tlib/include/ -static -L../../tlib/ -ltlib -mcmodel=small -fPIC
|
||||
PROGRAM_FLAGS=$(CPP_FLAGS_64) $(WARNING_FLAGS) -I../../tlib/include/ -I../../printf/include/ -static -L../../tlib/ -ltlib -mcmodel=small -fPIC
|
||||
PROGRAM_LINK_FLAGS=$(CPP_FLAGS_64) $(WARNING_FLAGS) $(COMMON_LINK_FLAGS) -static -L../../tlib/ -ltlib -mcmodel=small -fPIC -z max-page-size=0x1000 -T ../linker.ld -Wl,-gc-sections
|
||||
|
@ -8,6 +8,8 @@
|
||||
#ifndef CONSOLE_H
|
||||
#define CONSOLE_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <types.hpp>
|
||||
#include <enable_if.hpp>
|
||||
#include <string.hpp>
|
||||
@ -40,8 +42,6 @@ void k_print(int16_t number);
|
||||
void k_print(int32_t number);
|
||||
void k_print(int64_t number);
|
||||
|
||||
void k_printf(const char* fmt, ...);
|
||||
|
||||
template<typename... Arguments>
|
||||
typename std::enable_if_t<(sizeof...(Arguments) == 0)> k_print_line(const Arguments&... args){
|
||||
k_print('\n');
|
||||
@ -53,4 +53,6 @@ typename std::enable_if_t<(sizeof...(Arguments) > 0)> k_print_line(const Argumen
|
||||
k_print('\n');
|
||||
}
|
||||
|
||||
#include "printf_dec.hpp"
|
||||
|
||||
#endif
|
||||
|
@ -214,177 +214,8 @@ void wipeout(){
|
||||
current_column = 0;
|
||||
}
|
||||
|
||||
void k_printf(const char* fmt, ...){
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
#include "printf_def.hpp"
|
||||
|
||||
char ch;
|
||||
|
||||
while ((ch=*(fmt++))) {
|
||||
if(ch != '%'){
|
||||
k_print(ch);
|
||||
} else {
|
||||
ch = *(fmt++);
|
||||
|
||||
size_t min_width = 0;
|
||||
while(ch >= '0' && ch <= '9'){
|
||||
min_width = 10 * min_width + (ch - '0');
|
||||
ch = *(fmt++);
|
||||
}
|
||||
|
||||
size_t min_digits = 0;
|
||||
if(ch == '.'){
|
||||
ch = *(fmt++);
|
||||
|
||||
while(ch >= '0' && ch <= '9'){
|
||||
min_digits = 10 * min_digits + (ch - '0');
|
||||
ch = *(fmt++);
|
||||
}
|
||||
}
|
||||
|
||||
auto prev = current_column;
|
||||
|
||||
//Signed decimal
|
||||
if(ch == 'd'){
|
||||
auto arg = va_arg(va, int64_t);
|
||||
|
||||
if(min_digits > 0){
|
||||
size_t d = std::digits(arg);
|
||||
if(min_digits > d){
|
||||
min_digits -= d;
|
||||
|
||||
if(arg < 0){
|
||||
arg *= -1;
|
||||
k_print('-');
|
||||
}
|
||||
|
||||
while(min_digits > 0){
|
||||
while(min_digits > 0){
|
||||
k_print('0');
|
||||
--min_digits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
k_print(arg);
|
||||
}
|
||||
//Unsigned Decimal
|
||||
else if(ch == 'u'){
|
||||
auto arg = va_arg(va, uint64_t);
|
||||
|
||||
if(min_digits > 0){
|
||||
size_t d = std::digits(arg);
|
||||
if(min_digits > d){
|
||||
min_digits -= d;
|
||||
while(min_digits > 0){
|
||||
while(min_digits > 0){
|
||||
k_print('0');
|
||||
--min_digits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
k_print(arg);
|
||||
}
|
||||
//Hexadecimal
|
||||
else if(ch == 'h'){
|
||||
k_print("0x");
|
||||
|
||||
uint8_t buffer[20];
|
||||
|
||||
auto arg = va_arg(va, uint64_t);
|
||||
size_t i = 0;
|
||||
|
||||
while(arg / 16 != 0){
|
||||
buffer[i++] = arg % 16;
|
||||
arg /= 16;
|
||||
}
|
||||
|
||||
buffer[i] = arg;
|
||||
|
||||
if(min_digits > 0 && min_digits > i){
|
||||
min_digits -= i + 1;
|
||||
while(min_digits > 0){
|
||||
k_print('0');
|
||||
--min_digits;
|
||||
}
|
||||
}
|
||||
|
||||
while(true){
|
||||
uint8_t digit = buffer[i];
|
||||
|
||||
if(digit < 10){
|
||||
k_print(static_cast<char>('0' + digit));
|
||||
} else {
|
||||
switch(digit){
|
||||
case 10:
|
||||
k_print('A');
|
||||
break;
|
||||
case 11:
|
||||
k_print('B');
|
||||
break;
|
||||
case 12:
|
||||
k_print('C');
|
||||
break;
|
||||
case 13:
|
||||
k_print('D');
|
||||
break;
|
||||
case 14:
|
||||
k_print('E');
|
||||
break;
|
||||
case 15:
|
||||
k_print('F');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i == 0){
|
||||
break;
|
||||
}
|
||||
|
||||
--i;
|
||||
}
|
||||
}
|
||||
//Memory
|
||||
else if(ch == 'm'){
|
||||
auto memory= va_arg(va, uint64_t);
|
||||
|
||||
if(memory >= 1024 * 1024 * 1024){
|
||||
k_print(memory / (1024 * 1024 * 1024));
|
||||
k_print("GiB");
|
||||
} else if(memory >= 1024 * 1024){
|
||||
k_print(memory / (1024 * 1024));
|
||||
k_print("MiB");
|
||||
} else if(memory >= 1024){
|
||||
k_print(memory / 1024);
|
||||
k_print("KiB");
|
||||
} else {
|
||||
k_print(memory);
|
||||
k_print("B");
|
||||
}
|
||||
}
|
||||
//String
|
||||
else if(ch == 's'){
|
||||
auto arg = va_arg(va, const char*);
|
||||
k_print(arg);
|
||||
}
|
||||
|
||||
if(min_width > 0){
|
||||
size_t width = current_column - prev;
|
||||
|
||||
if(min_width > width){
|
||||
min_width -= width;
|
||||
|
||||
while(min_width > 0){
|
||||
k_print(' ');
|
||||
--min_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
va_end(va);
|
||||
void __printf(const std::string& str){
|
||||
k_print(str);
|
||||
}
|
||||
|
@ -224,16 +224,16 @@ const char* exceptions_title[32] {
|
||||
extern "C" {
|
||||
|
||||
void _fault_handler(interrupt::fault_regs regs){
|
||||
k_printf("Exception %u (%s) occured\n", regs.error_no, exceptions_title[regs.error_no]);
|
||||
k_printf("error_code=%u\n", regs.error_code);
|
||||
k_printf("rip=%h\n", regs.rip);
|
||||
k_printf("rflags=%h\n", regs.rflags);
|
||||
k_printf("cs=%h\n", regs.cs);
|
||||
k_printf("rsp=%h\n", regs.rsp);
|
||||
k_printf("ss=%h\n", regs.ss);
|
||||
k_printf("pid=%u\n", scheduler::get_pid());
|
||||
k_printf("cr2=%h\n", get_cr2());
|
||||
k_printf("cr3=%h\n", get_cr3());
|
||||
printf("Exception %u (%s) occured\n", regs.error_no, exceptions_title[regs.error_no]);
|
||||
printf("error_code=%u\n", regs.error_code);
|
||||
printf("rip=%h\n", regs.rip);
|
||||
printf("rflags=%h\n", regs.rflags);
|
||||
printf("cs=%h\n", regs.cs);
|
||||
printf("rsp=%h\n", regs.rsp);
|
||||
printf("ss=%h\n", regs.ss);
|
||||
printf("pid=%u\n", scheduler::get_pid());
|
||||
printf("cr2=%h\n", get_cr2());
|
||||
printf("cr3=%h\n", get_cr3());
|
||||
|
||||
//TODO Improve that with kind of blue screen
|
||||
|
||||
|
@ -151,21 +151,21 @@ void debug_malloc(const char* point = nullptr){
|
||||
|
||||
k_print(" next: ");
|
||||
do {
|
||||
k_printf("%u%h -> ", static_cast<size_t>(it->is_free()), reinterpret_cast<uint64_t>(it));
|
||||
printf("%u%h -> ", static_cast<size_t>(it->is_free()), reinterpret_cast<uint64_t>(it));
|
||||
it = it->next();
|
||||
} while(it != malloc_head);
|
||||
|
||||
k_printf("%h\n", malloc_head);
|
||||
printf("%h\n", malloc_head);
|
||||
|
||||
it = malloc_head;
|
||||
|
||||
k_print("prev: ");
|
||||
do {
|
||||
k_printf("%h <- ", reinterpret_cast<uint64_t>(it));
|
||||
printf("%h <- ", reinterpret_cast<uint64_t>(it));
|
||||
it = it->prev();
|
||||
} while(it != malloc_head);
|
||||
|
||||
k_printf("%h\n", malloc_head);
|
||||
printf("%h\n", malloc_head);
|
||||
}
|
||||
}
|
||||
|
||||
@ -414,7 +414,7 @@ void* kalloc::k_malloc(uint64_t bytes){
|
||||
auto block_start = reinterpret_cast<uintptr_t>(current) + sizeof(malloc_header_chunk);
|
||||
|
||||
if(TRACE_MALLOC){
|
||||
k_printf("m %u(%u) %h ", bytes, current->size(), block_start);
|
||||
printf("m %u(%u) %h ", bytes, current->size(), block_start);
|
||||
}
|
||||
|
||||
return reinterpret_cast<void*>(block_start);
|
||||
@ -429,7 +429,7 @@ void kalloc::k_free(void* block){
|
||||
}
|
||||
|
||||
if(TRACE_MALLOC){
|
||||
k_printf("f %u %h ", free_header->size(), reinterpret_cast<uint64_t>(block));
|
||||
printf("f %u %h ", free_header->size(), reinterpret_cast<uint64_t>(block));
|
||||
}
|
||||
|
||||
//Less memory is used
|
||||
@ -472,7 +472,7 @@ void kalloc::debug(){
|
||||
|
||||
auto it = malloc_head;
|
||||
|
||||
k_printf("malloc overhead: %u\n", META_SIZE);
|
||||
printf("malloc overhead: %u\n", META_SIZE);
|
||||
k_print("Free blocks:");
|
||||
do {
|
||||
if(!it->is_free()){
|
||||
@ -484,14 +484,14 @@ void kalloc::debug(){
|
||||
++inconsistent;
|
||||
}
|
||||
|
||||
k_printf("b(%u) ", it->size());
|
||||
printf("b(%u) ", it->size());
|
||||
memory_free += it->size();
|
||||
|
||||
it = it->next();
|
||||
} while(it != malloc_head);
|
||||
|
||||
k_print_line();
|
||||
k_printf("memory free in malloc chain: %m (%u)\n", memory_free, memory_free);
|
||||
k_printf("There are %u non free blocks in the free list\n", non_free_blocks);
|
||||
k_printf("There are %u inconsistent sized blocks in the free list\n", inconsistent);
|
||||
printf("memory free in malloc chain: %m (%u)\n", memory_free, memory_free);
|
||||
printf("There are %u non free blocks in the free list\n", non_free_blocks);
|
||||
printf("There are %u inconsistent sized blocks in the free list\n", inconsistent);
|
||||
}
|
||||
|
@ -41,5 +41,5 @@ void out_word(uint16_t _port, uint16_t _data){
|
||||
}
|
||||
|
||||
void print_stack(const char* s, size_t check){
|
||||
k_printf("%s stack: %u (16B-a:%u) \n", s, check, static_cast<size_t>(check % 16));
|
||||
printf("%s stack: %u (16B-a:%u) \n", s, check, static_cast<size_t>(check % 16));
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ void gc_task(){
|
||||
auto& desc = process.process;
|
||||
|
||||
if(DEBUG_SCHEDULER){
|
||||
k_printf("Clean process %u\n", desc.pid);
|
||||
printf("Clean process %u\n", desc.pid);
|
||||
}
|
||||
|
||||
//1. Release physical memory of PML4T
|
||||
@ -266,7 +266,7 @@ void switch_to_process(size_t pid){
|
||||
current_pid = pid;
|
||||
|
||||
if(DEBUG_SCHEDULER){
|
||||
k_printf("Switch to %u\n", current_pid);
|
||||
printf("Switch to %u\n", current_pid);
|
||||
}
|
||||
|
||||
auto& process = pcb[current_pid];
|
||||
@ -363,7 +363,7 @@ bool allocate_user_memory(scheduler::process_t& process, size_t address, size_t
|
||||
(physical_memory / paging::PAGE_SIZE + 1) * paging::PAGE_SIZE;
|
||||
|
||||
if(DEBUG_SCHEDULER){
|
||||
k_printf("Map(p%u) virtual:%h into phys: %h\n", process.pid, first_page, aligned_physical_memory);
|
||||
printf("Map(p%u) virtual:%h into phys: %h\n", process.pid, first_page, aligned_physical_memory);
|
||||
}
|
||||
|
||||
|
||||
@ -396,7 +396,7 @@ bool create_paging(char* buffer, scheduler::process_t& process){
|
||||
process.paging_size = paging::PAGE_SIZE;
|
||||
|
||||
if(DEBUG_SCHEDULER){
|
||||
k_printf("Process %u cr3:%h\n", process.pid, process.physical_cr3);
|
||||
printf("Process %u cr3:%h\n", process.pid, process.physical_cr3);
|
||||
}
|
||||
|
||||
clear_physical_memory(process.physical_cr3, 1);
|
||||
@ -442,7 +442,7 @@ bool create_paging(char* buffer, scheduler::process_t& process){
|
||||
physical_pointer phys_ptr(segment.physical, pages);
|
||||
|
||||
if(DEBUG_SCHEDULER){
|
||||
k_printf("Copy to physical:%h\n", segment.physical);
|
||||
printf("Copy to physical:%h\n", segment.physical);
|
||||
}
|
||||
|
||||
auto memory_start = phys_ptr.get() + left_padding;
|
||||
@ -672,7 +672,7 @@ void scheduler::sbrk(size_t inc){
|
||||
auto virtual_start = process.brk_start;
|
||||
|
||||
if(DEBUG_SCHEDULER){
|
||||
k_printf("Map(p%u) virtual:%h into phys: %h\n", process.pid, virtual_start, physical);
|
||||
printf("Map(p%u) virtual:%h into phys: %h\n", process.pid, virtual_start, physical);
|
||||
}
|
||||
|
||||
//Map the memory inside the process memory space
|
||||
@ -710,7 +710,7 @@ void scheduler::await_termination(pid_t pid){
|
||||
|
||||
void scheduler::kill_current_process(){
|
||||
if(DEBUG_SCHEDULER){
|
||||
k_printf("Kill %u\n", current_pid);
|
||||
printf("Kill %u\n", current_pid);
|
||||
}
|
||||
|
||||
//Notify parent if waiting
|
||||
@ -801,7 +801,7 @@ void scheduler::block_process(pid_t pid){
|
||||
thor_assert(pcb[pid].state == process_state::RUNNING, "Can only block RUNNING processes");
|
||||
|
||||
if(DEBUG_SCHEDULER){
|
||||
k_printf("Block process %u\n", pid);
|
||||
printf("Block process %u\n", pid);
|
||||
}
|
||||
|
||||
pcb[pid].state = process_state::BLOCKED;
|
||||
@ -814,7 +814,7 @@ void scheduler::unblock_process(pid_t pid){
|
||||
thor_assert(pcb[pid].state == process_state::BLOCKED || pcb[pid].state == process_state::WAITING, "Can only unblock BLOCKED/WAITING processes");
|
||||
|
||||
if(DEBUG_SCHEDULER){
|
||||
k_printf("Unblock process %u\n", pid);
|
||||
printf("Unblock process %u\n", pid);
|
||||
}
|
||||
|
||||
pcb[pid].state = process_state::READY;
|
||||
@ -825,7 +825,7 @@ void scheduler::sleep_ms(pid_t pid, size_t time){
|
||||
thor_assert(pcb[pid].state == process_state::RUNNING, "Only RUNNING processes can sleep");
|
||||
|
||||
if(DEBUG_SCHEDULER){
|
||||
k_printf("Put %u to sleep\n", pid);
|
||||
printf("Put %u to sleep\n", pid);
|
||||
}
|
||||
|
||||
pcb[pid].state = process_state::SLEEPING;
|
||||
|
20
printf/include/printf_dec.hpp
Normal file
20
printf/include/printf_dec.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
//=======================================================================
|
||||
// Copyright Baptiste Wicht 2013-2014.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
//Is made to be included as is in a header file
|
||||
//
|
||||
//Implement is provided in printf_def.hpp which must be included in
|
||||
//source file
|
||||
|
||||
std::string sprintf(const std::string& format, ...);
|
||||
std::string vsprintf(const std::string& format, va_list va);
|
||||
|
||||
void printf(const std::string& format, ...);
|
||||
void vprintf(const std::string& format, va_list va);
|
||||
|
||||
//Definition of this function must be provided
|
||||
void __printf(const std::string& formatted);
|
205
printf/include/printf_def.hpp
Normal file
205
printf/include/printf_def.hpp
Normal file
@ -0,0 +1,205 @@
|
||||
//=======================================================================
|
||||
// Copyright Baptiste Wicht 2013-2014.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
std::string vsprintf(const std::string& format, va_list va){
|
||||
std::string s(format.size());
|
||||
|
||||
char ch;
|
||||
int fi = 0;
|
||||
|
||||
while ((ch = format[fi++])) {
|
||||
if(ch != '%'){
|
||||
s += ch;
|
||||
} else {
|
||||
ch = format[fi++];
|
||||
|
||||
size_t min_width = 0;
|
||||
while(ch >= '0' && ch <= '9'){
|
||||
min_width = 10 * min_width + (ch - '0');
|
||||
ch = format[fi++];
|
||||
}
|
||||
|
||||
size_t min_digits = 0;
|
||||
if(ch == '.'){
|
||||
ch = format[fi++];
|
||||
|
||||
while(ch >= '0' && ch <= '9'){
|
||||
min_digits = 10 * min_digits + (ch - '0');
|
||||
ch = format[fi++];
|
||||
}
|
||||
}
|
||||
|
||||
auto prev = s.size();
|
||||
|
||||
//Signed decimal
|
||||
if(ch == 'd'){
|
||||
auto arg = va_arg(va, int64_t);
|
||||
|
||||
if(min_digits > 0){
|
||||
size_t d = std::digits(arg);
|
||||
if(min_digits > d){
|
||||
min_digits -= d;
|
||||
|
||||
if(arg < 0){
|
||||
arg *= -1;
|
||||
s += '-';
|
||||
}
|
||||
|
||||
while(min_digits > 0){
|
||||
while(min_digits > 0){
|
||||
arg += '0';
|
||||
--min_digits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s += std::to_string(arg);
|
||||
}
|
||||
//Unsigned Decimal
|
||||
else if(ch == 'u'){
|
||||
auto arg = va_arg(va, uint64_t);
|
||||
|
||||
if(min_digits > 0){
|
||||
size_t d = std::digits(arg);
|
||||
if(min_digits > d){
|
||||
min_digits -= d;
|
||||
while(min_digits > 0){
|
||||
while(min_digits > 0){
|
||||
arg += '0';
|
||||
--min_digits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s += std::to_string(arg);
|
||||
}
|
||||
//Hexadecimal
|
||||
else if(ch == 'h'){
|
||||
s += "0x";
|
||||
|
||||
uint8_t buffer[20];
|
||||
|
||||
auto arg = va_arg(va, uint64_t);
|
||||
size_t i = 0;
|
||||
|
||||
while(arg / 16 != 0){
|
||||
buffer[i++] = arg % 16;
|
||||
arg /= 16;
|
||||
}
|
||||
|
||||
buffer[i] = arg;
|
||||
|
||||
if(min_digits > 0 && min_digits > i){
|
||||
min_digits -= i + 1;
|
||||
while(min_digits > 0){
|
||||
arg += '0';
|
||||
--min_digits;
|
||||
}
|
||||
}
|
||||
|
||||
while(true){
|
||||
uint8_t digit = buffer[i];
|
||||
|
||||
if(digit < 10){
|
||||
s += static_cast<char>('0' + digit);
|
||||
} else {
|
||||
switch(digit){
|
||||
case 10:
|
||||
s += 'A';
|
||||
break;
|
||||
case 11:
|
||||
s += 'B';
|
||||
break;
|
||||
case 12:
|
||||
s += 'C';
|
||||
break;
|
||||
case 13:
|
||||
s += 'D';
|
||||
break;
|
||||
case 14:
|
||||
s += 'E';
|
||||
break;
|
||||
case 15:
|
||||
s += 'F';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i == 0){
|
||||
break;
|
||||
}
|
||||
|
||||
--i;
|
||||
}
|
||||
}
|
||||
//Memory
|
||||
else if(ch == 'm'){
|
||||
auto memory= va_arg(va, uint64_t);
|
||||
|
||||
if(memory >= 1024 * 1024 * 1024){
|
||||
s += std::to_string(memory / (1024 * 1024 * 1024));
|
||||
s += "GiB";
|
||||
} else if(memory >= 1024 * 1024){
|
||||
s += std::to_string(memory / (1024 * 1024));
|
||||
s += "MiB";
|
||||
} else if(memory >= 1024){
|
||||
s += std::to_string(memory / 1024);
|
||||
s += "KiB";
|
||||
} else {
|
||||
s += std::to_string(memory);
|
||||
s += "B";
|
||||
}
|
||||
}
|
||||
//String
|
||||
else if(ch == 's'){
|
||||
auto arg = va_arg(va, const char*);
|
||||
s += arg;
|
||||
}
|
||||
|
||||
if(min_width > 0){
|
||||
size_t width = s.size() - prev;
|
||||
|
||||
if(min_width > width){
|
||||
min_width -= width;
|
||||
|
||||
while(min_width > 0){
|
||||
s += ' ';
|
||||
--min_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(s);
|
||||
}
|
||||
|
||||
std::string sprintf(const std::string& format, ...){
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
|
||||
auto s = vsprintf(format, va);
|
||||
|
||||
va_end(va);
|
||||
|
||||
return std::move(s);
|
||||
}
|
||||
|
||||
void printf(const std::string& format, va_list va){
|
||||
__printf(vsprintf(format, va));
|
||||
}
|
||||
|
||||
void printf(const std::string& format, ...){
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
|
||||
printf(format, va);
|
||||
|
||||
va_end(va);
|
||||
}
|
@ -10,6 +10,8 @@
|
||||
|
||||
//TODO Rename in console
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <types.hpp>
|
||||
#include <string.hpp>
|
||||
|
||||
@ -39,7 +41,6 @@ void clear();
|
||||
size_t get_columns();
|
||||
size_t get_rows();
|
||||
|
||||
std::string sprintf(const std::string& format, ...);
|
||||
void printf(const std::string& format, ...);
|
||||
#include "printf_dec.hpp"
|
||||
|
||||
#endif
|
||||
|
@ -112,197 +112,8 @@ void print_line(const std::string& s){
|
||||
print_line();
|
||||
}
|
||||
|
||||
std::string vsprintf(const std::string& format, va_list va){
|
||||
std::string s(format.size());
|
||||
#include "printf_def.hpp"
|
||||
|
||||
char ch;
|
||||
int fi = 0;
|
||||
|
||||
while ((ch = format[fi++])) {
|
||||
if(ch != '%'){
|
||||
s += ch;
|
||||
} else {
|
||||
ch = format[fi++];
|
||||
|
||||
size_t min_width = 0;
|
||||
while(ch >= '0' && ch <= '9'){
|
||||
min_width = 10 * min_width + (ch - '0');
|
||||
ch = format[fi++];
|
||||
}
|
||||
|
||||
size_t min_digits = 0;
|
||||
if(ch == '.'){
|
||||
ch = format[fi++];
|
||||
|
||||
while(ch >= '0' && ch <= '9'){
|
||||
min_digits = 10 * min_digits + (ch - '0');
|
||||
ch = format[fi++];
|
||||
}
|
||||
}
|
||||
|
||||
auto prev = s.size();
|
||||
|
||||
//Signed decimal
|
||||
if(ch == 'd'){
|
||||
auto arg = va_arg(va, int64_t);
|
||||
|
||||
if(min_digits > 0){
|
||||
size_t d = std::digits(arg);
|
||||
if(min_digits > d){
|
||||
min_digits -= d;
|
||||
|
||||
if(arg < 0){
|
||||
arg *= -1;
|
||||
s += '-';
|
||||
}
|
||||
|
||||
while(min_digits > 0){
|
||||
while(min_digits > 0){
|
||||
arg += '0';
|
||||
--min_digits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s += std::to_string(arg);
|
||||
}
|
||||
//Unsigned Decimal
|
||||
else if(ch == 'u'){
|
||||
auto arg = va_arg(va, uint64_t);
|
||||
|
||||
if(min_digits > 0){
|
||||
size_t d = std::digits(arg);
|
||||
if(min_digits > d){
|
||||
min_digits -= d;
|
||||
while(min_digits > 0){
|
||||
while(min_digits > 0){
|
||||
arg += '0';
|
||||
--min_digits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s += std::to_string(arg);
|
||||
}
|
||||
//Hexadecimal
|
||||
else if(ch == 'h'){
|
||||
s += "0x";
|
||||
|
||||
uint8_t buffer[20];
|
||||
|
||||
auto arg = va_arg(va, uint64_t);
|
||||
size_t i = 0;
|
||||
|
||||
while(arg / 16 != 0){
|
||||
buffer[i++] = arg % 16;
|
||||
arg /= 16;
|
||||
}
|
||||
|
||||
buffer[i] = arg;
|
||||
|
||||
if(min_digits > 0 && min_digits > i){
|
||||
min_digits -= i + 1;
|
||||
while(min_digits > 0){
|
||||
arg += '0';
|
||||
--min_digits;
|
||||
}
|
||||
}
|
||||
|
||||
while(true){
|
||||
uint8_t digit = buffer[i];
|
||||
|
||||
if(digit < 10){
|
||||
s += static_cast<char>('0' + digit);
|
||||
} else {
|
||||
switch(digit){
|
||||
case 10:
|
||||
s += 'A';
|
||||
break;
|
||||
case 11:
|
||||
s += 'B';
|
||||
break;
|
||||
case 12:
|
||||
s += 'C';
|
||||
break;
|
||||
case 13:
|
||||
s += 'D';
|
||||
break;
|
||||
case 14:
|
||||
s += 'E';
|
||||
break;
|
||||
case 15:
|
||||
s += 'F';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i == 0){
|
||||
break;
|
||||
}
|
||||
|
||||
--i;
|
||||
}
|
||||
}
|
||||
//Memory
|
||||
else if(ch == 'm'){
|
||||
auto memory= va_arg(va, uint64_t);
|
||||
|
||||
if(memory >= 1024 * 1024 * 1024){
|
||||
s += std::to_string(memory / (1024 * 1024 * 1024));
|
||||
s += "GiB";
|
||||
} else if(memory >= 1024 * 1024){
|
||||
s += std::to_string(memory / (1024 * 1024));
|
||||
s += "MiB";
|
||||
} else if(memory >= 1024){
|
||||
s += std::to_string(memory / 1024);
|
||||
s += "KiB";
|
||||
} else {
|
||||
s += std::to_string(memory);
|
||||
s += "B";
|
||||
}
|
||||
}
|
||||
//String
|
||||
else if(ch == 's'){
|
||||
auto arg = va_arg(va, const char*);
|
||||
s += arg;
|
||||
}
|
||||
|
||||
if(min_width > 0){
|
||||
size_t width = s.size() - prev;
|
||||
|
||||
if(min_width > width){
|
||||
min_width -= width;
|
||||
|
||||
while(min_width > 0){
|
||||
s += ' ';
|
||||
--min_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(s);
|
||||
}
|
||||
|
||||
std::string sprintf(const std::string& format, ...){
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
|
||||
auto s = vsprintf(format, va);
|
||||
|
||||
va_end(va);
|
||||
|
||||
return std::move(s);
|
||||
}
|
||||
|
||||
void printf(const std::string& format, ...){
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
|
||||
print(vsprintf(format, va));
|
||||
|
||||
va_end(va);
|
||||
void __printf(const std::string& formatted){
|
||||
print(formatted);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user