Add printf() and puts(), quite primitive, looks like hex printing isn't there yet...
This commit is contained in:
parent
fc9868819f
commit
34aa953dbc
@ -1,16 +1,10 @@
|
|||||||
#include <luna.h>
|
#include <luna.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
static void print(const char* message)
|
|
||||||
{
|
|
||||||
syscall(SYS_write, message, strlen(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define println(message) print(message "\n")
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
if (gettid() == 0) // why are we the idle task?
|
if (gettid() == 0) // why are we the idle task?
|
||||||
@ -18,29 +12,27 @@ int main()
|
|||||||
__luna_abort("SHENANIGANS! init is tid 0 (which is reserved for the idle task)\n");
|
__luna_abort("SHENANIGANS! init is tid 0 (which is reserved for the idle task)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Welcome to Luna from a C init!");
|
printf("Welcome to Luna!\n");
|
||||||
println("");
|
|
||||||
|
printf("Running as tid %ld\n\n", gettid());
|
||||||
|
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|
||||||
print("Your kernel version is ");
|
|
||||||
|
|
||||||
char version[40];
|
char version[40];
|
||||||
syscall(SYS_getversion, version, sizeof(version));
|
syscall(SYS_getversion, version, sizeof(version));
|
||||||
|
|
||||||
print(version);
|
printf("Your kernel version is %s\n\n", version);
|
||||||
println("\n");
|
|
||||||
|
|
||||||
sleep(2);
|
sleep(2);
|
||||||
|
|
||||||
{
|
{
|
||||||
[[maybe_unused]] volatile int i;
|
|
||||||
char* variable = malloc(200);
|
char* variable = malloc(200);
|
||||||
*variable = 3;
|
*variable = 3;
|
||||||
|
printf("Allocated variable at address %lx\n", (unsigned long int)variable);
|
||||||
free(variable);
|
free(variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Press any key to restart.");
|
printf("Press any key to restart.\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,8 @@ extern "C"
|
|||||||
size_t fwrite(const void*, size_t, size_t, FILE*);
|
size_t fwrite(const void*, size_t, size_t, FILE*);
|
||||||
void setbuf(FILE*, char*);
|
void setbuf(FILE*, char*);
|
||||||
int vfprintf(FILE*, const char*, va_list);
|
int vfprintf(FILE*, const char*, va_list);
|
||||||
|
int printf(const char*, ...);
|
||||||
|
int puts(const char*);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
259
libs/libc/src/printf.cpp
Normal file
259
libs/libc/src/printf.cpp
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
#include <luna.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
typedef long int ssize_t;
|
||||||
|
|
||||||
|
static void __strrev(char* arr, int size)
|
||||||
|
{
|
||||||
|
int left = 0;
|
||||||
|
int right = size - 1;
|
||||||
|
for (int i = left; i < right; i++)
|
||||||
|
{
|
||||||
|
char temp = arr[i];
|
||||||
|
arr[i] = arr[right];
|
||||||
|
arr[right] = temp;
|
||||||
|
right--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename IntegerType> static char* __unsignedtoa(IntegerType number, char* arr, int base)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
IntegerType r = 0;
|
||||||
|
|
||||||
|
if (number == 0)
|
||||||
|
{
|
||||||
|
arr[i] = '0';
|
||||||
|
arr[i + 1] = '\0';
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (number != 0)
|
||||||
|
{
|
||||||
|
r = number % base;
|
||||||
|
arr[i] = (r > 9) ? (r - 10) + 'a' : r + '0';
|
||||||
|
i++;
|
||||||
|
number /= base;
|
||||||
|
}
|
||||||
|
|
||||||
|
__strrev(arr, i - 1);
|
||||||
|
|
||||||
|
arr[i] = '\0';
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename IntegerType, typename UnsignedIntegerType>
|
||||||
|
static char* __signedtoa(IntegerType number, char* arr, int base)
|
||||||
|
{
|
||||||
|
if (number < 0 && base == 10)
|
||||||
|
{
|
||||||
|
return __unsignedtoa<UnsignedIntegerType>((UnsignedIntegerType)(-number), arr, base);
|
||||||
|
}
|
||||||
|
return __unsignedtoa<UnsignedIntegerType>((UnsignedIntegerType)number, arr, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PutString>
|
||||||
|
static int internal_printf(const char* format, PutString put_string_callback, ssize_t max, va_list ap)
|
||||||
|
{
|
||||||
|
char buffer[1025]; // 1024 with null terminator
|
||||||
|
size_t format_size = strlen(format);
|
||||||
|
size_t format_index = 0;
|
||||||
|
size_t buffer_insert_index = 0;
|
||||||
|
ssize_t max_remaining = max;
|
||||||
|
size_t written = 0;
|
||||||
|
|
||||||
|
auto flush_buffer = [&]() {
|
||||||
|
size_t buffer_length = buffer_insert_index;
|
||||||
|
written += buffer_length;
|
||||||
|
buffer_insert_index = 0;
|
||||||
|
if (max_remaining < 0)
|
||||||
|
{
|
||||||
|
buffer[buffer_length] = 0;
|
||||||
|
put_string_callback(buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (max_remaining == 0) { return; }
|
||||||
|
if (buffer_length <= (size_t)max_remaining)
|
||||||
|
{
|
||||||
|
max_remaining -= buffer_length;
|
||||||
|
buffer[buffer_length] = 0;
|
||||||
|
put_string_callback(buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer[max_remaining] = 0;
|
||||||
|
max_remaining = 0;
|
||||||
|
put_string_callback(buffer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool is_long = false;
|
||||||
|
bool is_unsigned_long = false;
|
||||||
|
|
||||||
|
bool preserve_format = false;
|
||||||
|
|
||||||
|
while (format_index < format_size)
|
||||||
|
{
|
||||||
|
char current_char = format[format_index];
|
||||||
|
if (current_char == '%' || preserve_format)
|
||||||
|
{
|
||||||
|
if (!preserve_format && format_index + 1 == format_size) // end of format string
|
||||||
|
{
|
||||||
|
format_index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!preserve_format) format_index++;
|
||||||
|
preserve_format = false;
|
||||||
|
current_char = format[format_index];
|
||||||
|
switch (current_char)
|
||||||
|
{
|
||||||
|
case 'c': {
|
||||||
|
buffer[buffer_insert_index++] = va_arg(ap, int);
|
||||||
|
if (buffer_insert_index == 1024) flush_buffer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '%': {
|
||||||
|
buffer[buffer_insert_index++] = '%';
|
||||||
|
if (buffer_insert_index == 1024) flush_buffer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'z': {
|
||||||
|
is_unsigned_long = true;
|
||||||
|
preserve_format = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'l': {
|
||||||
|
is_long = true;
|
||||||
|
preserve_format = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'd': {
|
||||||
|
if (is_unsigned_long)
|
||||||
|
{
|
||||||
|
char result[25];
|
||||||
|
__unsignedtoa<unsigned long>(va_arg(ap, uint64_t), result, 10);
|
||||||
|
if (buffer_insert_index + strlen(result) > 1024) flush_buffer();
|
||||||
|
memcpy(buffer + buffer_insert_index, result, strlen(result));
|
||||||
|
buffer_insert_index += strlen(result);
|
||||||
|
if (buffer_insert_index == 1024) flush_buffer();
|
||||||
|
is_unsigned_long = is_long = false;
|
||||||
|
}
|
||||||
|
else if (is_long)
|
||||||
|
{
|
||||||
|
char result[25];
|
||||||
|
__signedtoa<long, unsigned long>(va_arg(ap, int64_t), result, 10);
|
||||||
|
if (buffer_insert_index + strlen(result) > 1024) flush_buffer();
|
||||||
|
memcpy(buffer + buffer_insert_index, result, strlen(result));
|
||||||
|
buffer_insert_index += strlen(result);
|
||||||
|
if (buffer_insert_index == 1024) flush_buffer();
|
||||||
|
is_unsigned_long = is_long = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char result[25];
|
||||||
|
__signedtoa<int, unsigned int>(va_arg(ap, int32_t), result, 10);
|
||||||
|
if (buffer_insert_index + strlen(result) > 1024) flush_buffer();
|
||||||
|
memcpy(buffer + buffer_insert_index, result, strlen(result));
|
||||||
|
buffer_insert_index += strlen(result);
|
||||||
|
if (buffer_insert_index == 1024) flush_buffer();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u': {
|
||||||
|
if (is_unsigned_long || is_long)
|
||||||
|
{
|
||||||
|
char result[25];
|
||||||
|
__unsignedtoa<unsigned long>(va_arg(ap, uint64_t), result, 10);
|
||||||
|
if (buffer_insert_index + strlen(result) > 1024) flush_buffer();
|
||||||
|
memcpy(buffer + buffer_insert_index, result, strlen(result));
|
||||||
|
buffer_insert_index += strlen(result);
|
||||||
|
if (buffer_insert_index == 1024) flush_buffer();
|
||||||
|
is_unsigned_long = is_long = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char result[25];
|
||||||
|
__unsignedtoa<unsigned int>(va_arg(ap, uint32_t), result, 10);
|
||||||
|
if (buffer_insert_index + strlen(result) > 1024) flush_buffer();
|
||||||
|
memcpy(buffer + buffer_insert_index, result, strlen(result));
|
||||||
|
buffer_insert_index += strlen(result);
|
||||||
|
if (buffer_insert_index == 1024) flush_buffer();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'x': {
|
||||||
|
if (is_unsigned_long || is_long)
|
||||||
|
{
|
||||||
|
char result[25];
|
||||||
|
__unsignedtoa<unsigned long>(va_arg(ap, uint64_t), result, 16);
|
||||||
|
if (buffer_insert_index + strlen(result) > 1024) flush_buffer();
|
||||||
|
memcpy(buffer + buffer_insert_index, result, strlen(result));
|
||||||
|
buffer_insert_index += strlen(result);
|
||||||
|
if (buffer_insert_index == 1024) flush_buffer();
|
||||||
|
is_unsigned_long = is_long = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char result[25];
|
||||||
|
__unsignedtoa<unsigned int>(va_arg(ap, uint32_t), result, 16);
|
||||||
|
if (buffer_insert_index + strlen(result) > 1024) flush_buffer();
|
||||||
|
memcpy(buffer + buffer_insert_index, result, strlen(result));
|
||||||
|
buffer_insert_index += strlen(result);
|
||||||
|
if (buffer_insert_index == 1024) flush_buffer();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's': {
|
||||||
|
const char* str = va_arg(ap, const char*);
|
||||||
|
while (strlen(str) > 1024)
|
||||||
|
{
|
||||||
|
flush_buffer();
|
||||||
|
memcpy(buffer, str, 1024);
|
||||||
|
str += 1024;
|
||||||
|
buffer_insert_index = 1024;
|
||||||
|
}
|
||||||
|
if (buffer_insert_index + strlen(str) > 1024) flush_buffer();
|
||||||
|
memcpy(buffer + buffer_insert_index, str, strlen(str));
|
||||||
|
buffer_insert_index += strlen(str);
|
||||||
|
if (buffer_insert_index == 1024) flush_buffer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
NOT_IMPLEMENTED("internal_printf: unknown format specifier");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer[buffer_insert_index++] = current_char;
|
||||||
|
if (buffer_insert_index == 1024) flush_buffer();
|
||||||
|
}
|
||||||
|
format_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer_insert_index > 0) flush_buffer();
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
int printf(const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
int written = internal_printf(
|
||||||
|
format, [](const char* s) { syscall(SYS_write, s, strlen(s)); }, -1, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,9 @@
|
|||||||
#include <luna.h>
|
#include <luna.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
@ -43,4 +47,12 @@ extern "C"
|
|||||||
{
|
{
|
||||||
NOT_IMPLEMENTED("vfprintf");
|
NOT_IMPLEMENTED("vfprintf");
|
||||||
}
|
}
|
||||||
|
int puts(const char* s)
|
||||||
|
{
|
||||||
|
size_t len = strlen(s);
|
||||||
|
char* output = (char*)__builtin_alloca(len + 1);
|
||||||
|
memcpy(output, s, len);
|
||||||
|
output[len] = '\n';
|
||||||
|
return syscall(SYS_write, output, len + 1);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user