ref(libterm): now apple-styled too
This commit is contained in:
@@ -22,12 +22,12 @@ set(USER_C_FLAGS
|
||||
set(CMAKE_ASM_NASM_FLAGS "-f elf64")
|
||||
|
||||
set(LIBTERM_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls.asm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/stdio.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/malloc.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/string.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ctype.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/process.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/OSServices.asm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Console.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Memory.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/String.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Character.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Process.c
|
||||
)
|
||||
|
||||
add_library(term STATIC ${LIBTERM_SOURCES})
|
||||
@@ -36,13 +36,13 @@ target_compile_options(term PRIVATE $<$<COMPILE_LANGUAGE:C>:${USER_C_FLAGS}>)
|
||||
|
||||
target_include_directories(term PUBLIC inc)
|
||||
|
||||
add_library(crt0_obj OBJECT src/crt0.asm)
|
||||
target_compile_options(crt0_obj PRIVATE $<$<COMPILE_LANGUAGE:C>:${USER_C_FLAGS}>)
|
||||
add_library(RuntimeEntryObject OBJECT src/RuntimeEntry.asm)
|
||||
target_compile_options(RuntimeEntryObject PRIVATE $<$<COMPILE_LANGUAGE:C>:${USER_C_FLAGS}>)
|
||||
|
||||
function(add_termos_executable NAME SOURCES)
|
||||
add_executable(${NAME} ${SOURCES})
|
||||
|
||||
target_sources(${NAME} PRIVATE $<TARGET_OBJECTS:crt0_obj>)
|
||||
target_sources(${NAME} PRIVATE $<TARGET_OBJECTS:RuntimeEntryObject>)
|
||||
|
||||
target_compile_options(${NAME} PRIVATE $<$<COMPILE_LANGUAGE:C>:${USER_C_FLAGS}>)
|
||||
target_link_libraries(${NAME} PRIVATE term)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <Types.h>
|
||||
|
||||
enum {
|
||||
kConsoleEOF = -1,
|
||||
kConsoleDefaultBufferSize = 1024
|
||||
};
|
||||
|
||||
Int32 ConsolePrint(const char* format, ...);
|
||||
Int32 StringFormat(char* destination, UInt64 size, const char* format, ...);
|
||||
Int32 ConsoleGetCharacter();
|
||||
char* ConsoleReadLine(char* string, UInt64 size);
|
||||
@@ -0,0 +1,23 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <Types.h>
|
||||
|
||||
enum {
|
||||
kMemoryBlockMagic = 0x1CE1CE,
|
||||
kMemoryAlignment = 16,
|
||||
kMemoryPageSize = 4096
|
||||
};
|
||||
|
||||
typedef struct MemoryBlockHeader {
|
||||
UInt64 magic;
|
||||
struct MemoryBlockHeader* next;
|
||||
struct MemoryBlockHeader* previous;
|
||||
UInt64 size;
|
||||
bool isFree;
|
||||
} MemoryBlockHeader;
|
||||
|
||||
void* MemoryAllocate(UInt64 size);
|
||||
void MemoryFree(void* pointer);
|
||||
void* MemoryReallocate(void* pointer, UInt64 newSize);
|
||||
@@ -2,7 +2,7 @@
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
#include <Types.h>
|
||||
|
||||
Int32 spawn(const char* path);
|
||||
Int32 wait(UInt64 pid);
|
||||
Int32 ProcessSpawn(const char* path);
|
||||
Int32 ProcessWait(UInt64 pid);
|
||||
@@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <Types.h>
|
||||
|
||||
void* MemorySet(void* destination, UInt8 value, UInt64 count);
|
||||
void* MemoryCopy(void* destination, const void* source, UInt64 count);
|
||||
Int32 StringCompare(const char* firstString, const char* secondString);
|
||||
Int32 StringCompareWithLimit(const char* firstString, const char* secondString, UInt64 limit);
|
||||
char* StringCopy(char* destination, const char* source);
|
||||
char* StringCopyWithLimit(char* destination, const char* source, UInt64 limit);
|
||||
UInt64 StringGetLength(const char* string);
|
||||
UInt64 StringGetInitialSpan(const char* string, const char* characterSet);
|
||||
char* StringFindFirstCharacterFromSet(const char* string, const char* accept);
|
||||
char* StringTokenize(char *s, const char* delim);
|
||||
@@ -1,19 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
#define HEADER_MAGIC 0x1CE1CE
|
||||
|
||||
typedef struct block_header {
|
||||
UInt64 magic;
|
||||
struct block_header* next;
|
||||
struct block_header* prev;
|
||||
UInt64 size;
|
||||
bool is_free;
|
||||
} block_header;
|
||||
|
||||
void* malloc(UInt64 size);
|
||||
void free(void* ptr);
|
||||
void* realloc(void* ptr, UInt64 new_size);
|
||||
@@ -1,11 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
int printf(const char *fmt, ...);
|
||||
int snprintf(char* str, UInt64 size, const char* fmt, ...);
|
||||
int getchar();
|
||||
char* gets(char* str);
|
||||
char* gets_s(char* str, UInt64 size);
|
||||
@@ -1,16 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
void *memset(void *ptr, int value, usize num);
|
||||
void* memcpy(void* dest, const void* src, UInt64 n);
|
||||
Int32 strcmp(const char *s1, const char *s2);
|
||||
Int32 strncmp(const char* s1, const char* s2, UInt64 n);
|
||||
char* strcpy(char* dest, const char* src);
|
||||
char* strncpy(char* dest, const char* src, UInt64 n);
|
||||
UInt64 strlen(const char* str);
|
||||
UInt64 strspn(const char* s, const char* accept);
|
||||
char* strpbrk(const char* s, const char* accept);
|
||||
char* strtok(char *s, const char* delim);
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <Console.h>
|
||||
#include <Memory.h>
|
||||
#include <Process.h>
|
||||
#include <String.h>
|
||||
#include <Varargs.h>
|
||||
#include <Types.h>
|
||||
@@ -0,0 +1,156 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <Console.h>
|
||||
#include <Varargs.h>
|
||||
#include <String.h>
|
||||
|
||||
extern UInt64 OSServiceIORead(UInt64 fileDescriptor, void* buffer, UInt64 length);
|
||||
extern UInt64 OSServiceIOWrite(UInt64 fileDescriptor, const void* buffer, UInt64 length);
|
||||
|
||||
static void sConsoleWriteCharacter(char character) {
|
||||
OSServiceIOWrite(1, &character, 1);
|
||||
}
|
||||
|
||||
static inline void sConsoleBufferAdd(char* string, UInt64 size, UInt64* written, char character) {
|
||||
if (*written < size - 1 && size > 0) {
|
||||
string[*written] = character;
|
||||
}
|
||||
(*written)++;
|
||||
}
|
||||
|
||||
static Int32 sStringFormatVariadic(char* string, UInt64 size, const char* format, va_list args) {
|
||||
UInt64 written = 0;
|
||||
for (UInt32 i = 0; format[i] != '\0'; i++) {
|
||||
if (format[i] == '%') {
|
||||
i++;
|
||||
if (format[i] == '\0') break;
|
||||
switch (format[i]) {
|
||||
case 's': {
|
||||
const char* vaArgString = va_arg(args, const char*);
|
||||
if (!vaArgString) vaArgString = "(null)";
|
||||
while (*vaArgString) sConsoleBufferAdd(string, size, &written, *vaArgString++);
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
char character = (char)va_arg(args, int);
|
||||
sConsoleBufferAdd(string, size, &written, character);
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
Int64 number = va_arg(args, int);
|
||||
if (number < 0) {
|
||||
sConsoleBufferAdd(string, size, &written, '-');
|
||||
number = -number;
|
||||
}
|
||||
UInt64 unsignedNumber = (UInt64)number;
|
||||
char tempBuffer[32];
|
||||
Int32 position = 0;
|
||||
if (unsignedNumber == 0) tempBuffer[position++] = '0';
|
||||
while (unsignedNumber > 0) {
|
||||
tempBuffer[position++] = (unsignedNumber % 10) + '0';
|
||||
unsignedNumber /= 10;
|
||||
}
|
||||
|
||||
while (position > 0) sConsoleBufferAdd(string, size, &written, tempBuffer[--position]);
|
||||
break;
|
||||
}
|
||||
case 'x':
|
||||
case 'X': {
|
||||
UInt64 unsignedNumber = va_arg(args, unsigned long long);
|
||||
UInt8 padding = (format[i] == 'X') ? 16 : 0;
|
||||
|
||||
char tempBuffer[32];
|
||||
int position = 0;
|
||||
const char* hex = "0123456789ABCDEF";
|
||||
|
||||
if (unsignedNumber == 0 && padding == 0) tempBuffer[position++] = '0';
|
||||
while (unsignedNumber > 0) {
|
||||
tempBuffer[position++] = hex[unsignedNumber % 16];
|
||||
unsignedNumber /= 16;
|
||||
}
|
||||
|
||||
while (position < padding) tempBuffer[position++] = '0';
|
||||
while (position > 0) sConsoleBufferAdd(string, size, &written, tempBuffer[--position]);
|
||||
break;
|
||||
}
|
||||
case '%': {
|
||||
sConsoleBufferAdd(string, size, &written, '%');
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sConsoleBufferAdd(string, size, &written, '%');
|
||||
sConsoleBufferAdd(string, size, &written, format[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sConsoleBufferAdd(string, size, &written, format[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
if (written < size) string[written] = '\0';
|
||||
else string[size - 1] = '\0';
|
||||
}
|
||||
|
||||
return (int)written;
|
||||
}
|
||||
|
||||
Int32 StringFormat(char* destination, usize size, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int returnValue = sStringFormatVariadic(destination, size, format, args);
|
||||
va_end(args);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
Int32 ConsolePrint(const char *format, ...) {
|
||||
char buffer[kConsoleDefaultBufferSize];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
int length = sStringFormatVariadic(buffer, sizeof(buffer), format, args);
|
||||
va_end(args);
|
||||
|
||||
UInt64 writeLength = ((UInt64)length < sizeof(buffer)) ? length : (sizeof(buffer) - 1);
|
||||
OSServiceIOWrite(1, buffer, writeLength);
|
||||
|
||||
return (int)writeLength;
|
||||
}
|
||||
|
||||
Int32 ConsoleGetCharacter() {
|
||||
char character;
|
||||
UInt64 serviceCallResult = OSServiceIORead(0, &character, 1);
|
||||
if (serviceCallResult <= 0) return kConsoleEOF;
|
||||
return (int)(unsigned char)character;
|
||||
}
|
||||
|
||||
char* ConsoleReadLine(char* string, UInt64 size) {
|
||||
if (size == 0) return string;
|
||||
|
||||
UInt64 i = 0;
|
||||
int character;
|
||||
|
||||
while (i < size - 1) {
|
||||
character = ConsoleGetCharacter();
|
||||
if (character == kConsoleEOF || character == '\n' || character == '\r') break;
|
||||
if (character == '\b') {
|
||||
if (i > 0) {
|
||||
i--;
|
||||
ConsolePrint("\b \b");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
string[i++] = (char)character;
|
||||
|
||||
sConsoleWriteCharacter(character);
|
||||
}
|
||||
|
||||
string[i] = '\0';
|
||||
sConsoleWriteCharacter('\n');
|
||||
|
||||
return string;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
// brutally copypasting from kernel/mm/heap.c
|
||||
|
||||
#include <Memory.h>
|
||||
#include <String.h>
|
||||
|
||||
static MemoryBlockHeader* sMemoryHeapListHead = nullptr;
|
||||
extern UInt64 OSServiceMemoryAllocate(UInt64 size);
|
||||
|
||||
static void sMemoryCombineForward(MemoryBlockHeader* current) {
|
||||
if (!current->next || !current->next->isFree) return;
|
||||
current->size += sizeof(MemoryBlockHeader) + current->next->size;
|
||||
current->next = current->next->next;
|
||||
if (current->next) current->next->previous = current;
|
||||
}
|
||||
|
||||
void* MemoryAllocate(UInt64 size) {
|
||||
if (size == 0) return nullptr;
|
||||
UInt64 alignedSize = (size + (kMemoryAlignment-1)) & ~(kMemoryAlignment - 1);
|
||||
|
||||
MemoryBlockHeader* current = sMemoryHeapListHead;
|
||||
MemoryBlockHeader* lastBlock = nullptr;
|
||||
|
||||
while (current) {
|
||||
if (current->isFree && current->size >= alignedSize) {
|
||||
if (current->size > alignedSize + sizeof(MemoryBlockHeader) + kMemoryAlignment) {
|
||||
MemoryBlockHeader* newBlock = (MemoryBlockHeader*)((UInt64)current + sizeof(MemoryBlockHeader) + alignedSize);
|
||||
newBlock->size = current->size - alignedSize - sizeof(MemoryBlockHeader);
|
||||
newBlock->isFree = true;
|
||||
newBlock->next = current->next;
|
||||
newBlock->previous = current;
|
||||
newBlock->magic = kMemoryBlockMagic;
|
||||
|
||||
if (current->next) current->next->previous = newBlock;
|
||||
current->next = newBlock;
|
||||
current->size = alignedSize;
|
||||
}
|
||||
current->isFree = false;
|
||||
return (void*)((UInt64)current + sizeof(MemoryBlockHeader));
|
||||
}
|
||||
lastBlock = current;
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
UInt64 sizeNeededToAllocate = alignedSize + sizeof(MemoryBlockHeader);
|
||||
|
||||
UInt64 pageAlignedSize = (sizeNeededToAllocate + (kMemoryPageSize-1)) & ~(kMemoryPageSize-1);
|
||||
|
||||
UInt64 newMemoryAddress = OSServiceMemoryAllocate(pageAlignedSize);
|
||||
if (newMemoryAddress == 0) return nullptr;
|
||||
|
||||
MemoryBlockHeader* newBlock = (MemoryBlockHeader*)newMemoryAddress;
|
||||
newBlock->size = pageAlignedSize - sizeof(MemoryBlockHeader);
|
||||
newBlock->isFree = true;
|
||||
newBlock->magic = kMemoryBlockMagic;
|
||||
newBlock->next = nullptr;
|
||||
newBlock->previous = lastBlock;
|
||||
|
||||
if (lastBlock) {
|
||||
lastBlock->next = newBlock;
|
||||
} else {
|
||||
sMemoryHeapListHead = newBlock;
|
||||
}
|
||||
|
||||
return MemoryAllocate(size);
|
||||
}
|
||||
|
||||
void MemoryFree(void* pointer) {
|
||||
if (!pointer) return;
|
||||
|
||||
MemoryBlockHeader* current = (MemoryBlockHeader*)((UInt64)pointer - sizeof(MemoryBlockHeader));
|
||||
if (current->magic != kMemoryBlockMagic) return;
|
||||
|
||||
current->isFree = true;
|
||||
if (current->next && current->next->isFree) sMemoryCombineForward(current);
|
||||
if (current->previous && current->previous->isFree) sMemoryCombineForward(current->previous);
|
||||
}
|
||||
|
||||
void* MemoryReallocate(void* pointer, UInt64 newSize) {
|
||||
if (!pointer) return MemoryAllocate(newSize);
|
||||
if (newSize == 0) {
|
||||
MemoryFree(pointer);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MemoryBlockHeader* current = (MemoryBlockHeader*)((UInt64)pointer - sizeof(MemoryBlockHeader));
|
||||
if (current->size >= newSize) return pointer;
|
||||
|
||||
if (current->next &&
|
||||
current->next->isFree &&
|
||||
(current->size + sizeof(MemoryBlockHeader) + current->next->size) >= newSize) {
|
||||
sMemoryCombineForward(current);
|
||||
return pointer;
|
||||
}
|
||||
|
||||
void* newPointer = MemoryAllocate(newSize);
|
||||
if (!newPointer) return nullptr;
|
||||
|
||||
MemoryCopy(newPointer, pointer, current->size);
|
||||
MemoryFree(pointer);
|
||||
|
||||
return newPointer;
|
||||
}
|
||||
@@ -5,39 +5,39 @@ bits 64
|
||||
|
||||
section .text
|
||||
|
||||
global sys_exit
|
||||
global sys_spawn
|
||||
global sys_mem
|
||||
global sys_write
|
||||
global sys_read
|
||||
global sys_wait
|
||||
global OSServiceProcessExit
|
||||
global OSServiceProcessSpawn
|
||||
global OSServiceMemoryAllocate
|
||||
global OSServiceIOWrite
|
||||
global OSServiceIORead
|
||||
global OSServiceProcessWait
|
||||
|
||||
sys_exit:
|
||||
OSServiceProcessExit:
|
||||
mov rax, 0
|
||||
syscall
|
||||
ret
|
||||
|
||||
sys_spawn:
|
||||
OSServiceProcessSpawn:
|
||||
mov rax, 1
|
||||
syscall
|
||||
ret
|
||||
|
||||
sys_mem:
|
||||
OSServiceMemoryAllocate:
|
||||
mov rax, 2
|
||||
syscall
|
||||
ret
|
||||
|
||||
sys_write:
|
||||
OSServiceIOWrite:
|
||||
mov rax, 3
|
||||
syscall
|
||||
ret
|
||||
|
||||
sys_read:
|
||||
OSServiceIORead:
|
||||
mov rax, 4
|
||||
syscall
|
||||
ret
|
||||
|
||||
sys_wait:
|
||||
OSServiceProcessWait:
|
||||
mov rax, 5
|
||||
syscall
|
||||
ret
|
||||
@@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <Process.h>
|
||||
|
||||
extern Int32 OSServiceProcessSpawn(const char* path);
|
||||
extern Int32 OSServiceProcessWait(UInt64 pid);
|
||||
|
||||
Int32 ProcessSpawn(const char* path) {
|
||||
return OSServiceProcessSpawn(path);
|
||||
}
|
||||
|
||||
Int32 ProcessWait(UInt64 pid) {
|
||||
return OSServiceProcessWait(pid);
|
||||
}
|
||||
@@ -6,9 +6,9 @@
|
||||
section .text
|
||||
global _start
|
||||
extern main
|
||||
extern sys_exit
|
||||
extern OSServiceProcessExit
|
||||
|
||||
_start:
|
||||
call main
|
||||
mov rdi, rax
|
||||
call sys_exit
|
||||
call OSServiceProcessExit
|
||||
@@ -0,0 +1,126 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <String.h>
|
||||
|
||||
static char* olds;
|
||||
|
||||
void* MemorySet(void* destination, UInt8 value, usize count) {
|
||||
UInt8* bytePointer = (UInt8*) destination;
|
||||
while (count--) {
|
||||
*bytePointer++ = (UInt8)value;
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
void* MemoryCopy(void* destination, const void* source, UInt64 count) {
|
||||
UInt8* destinationBuffer = (UInt8*)destination;
|
||||
const UInt8* sourceBuffer = (const UInt8*)source;
|
||||
|
||||
while (count >= 8) {
|
||||
*(UInt64*)destinationBuffer = *(const UInt64*)sourceBuffer;
|
||||
destinationBuffer += 8;
|
||||
sourceBuffer += 8;
|
||||
count -= 8;
|
||||
}
|
||||
|
||||
while (count > 0) {
|
||||
*destinationBuffer++ = *sourceBuffer++;
|
||||
count--;
|
||||
}
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
Int32 StringCompare(const char* firstString, const char* secondString) {
|
||||
while (*firstString && (*firstString == *secondString)) {
|
||||
firstString++;
|
||||
secondString++;
|
||||
}
|
||||
return *(const unsigned char*)firstString - *(const unsigned char*)secondString;
|
||||
}
|
||||
|
||||
Int32 StringCompareWithLimit(const char* firstString, const char* secondString, UInt64 limit) {
|
||||
while (limit > 0) {
|
||||
if (*firstString != *secondString) return *(unsigned char*)firstString - *(unsigned char*)secondString;
|
||||
if (*firstString == '\0') return 0;
|
||||
firstString++;
|
||||
secondString++;
|
||||
limit--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* StringCopy(char* destination, const char* source) {
|
||||
char* saved = destination;
|
||||
while (*source) *destination++ = *source++;
|
||||
*destination = 0;
|
||||
return saved;
|
||||
}
|
||||
|
||||
char* StringCopyWithLimit(char* destination, const char* source, UInt64 limit) {
|
||||
char* saved = destination;
|
||||
while (*source && limit > 0) {
|
||||
*destination++ = *source++;
|
||||
limit--;
|
||||
}
|
||||
while (limit > 0) {
|
||||
*destination++ = 0;
|
||||
limit--;
|
||||
}
|
||||
return saved;
|
||||
}
|
||||
|
||||
UInt64 StringGetLength(const char* string) {
|
||||
UInt64 result = 0;
|
||||
for (result = 0; string[result]; result++);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int sStringIsInSet(char character, const char* set) {
|
||||
while (*set) {
|
||||
if (*set == character) return 1;
|
||||
set++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt64 StringGetInitialSpan(const char* string, const char* characterSet) {
|
||||
UInt64 count = 0;
|
||||
while (*string && sStringIsInSet(*string, characterSet)) {
|
||||
count++;
|
||||
string++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
char* StringFindFirstCharacterFromSet(const char* string, const char* set) {
|
||||
while (*string) {
|
||||
if (sStringIsInSet(*string, set)) {
|
||||
return (char*)string;
|
||||
}
|
||||
string++;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
// took from https://github.com/walac/glibc/blob/master/string/strtok.c
|
||||
char* StringTokenize(char* string, const char* delimiters) {
|
||||
char* token;
|
||||
if (string == nullptr) string = olds;
|
||||
string += StringGetInitialSpan(string, delimiters);
|
||||
if (*string == '\0') {
|
||||
olds = string;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
token = string;
|
||||
string = StringFindFirstCharacterFromSet(token, delimiters);
|
||||
if (string == nullptr) olds = token + StringGetLength(token);
|
||||
else {
|
||||
*string = '\0';
|
||||
olds = string + 1;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
// brutally copypasting from kernel/mm/heap.c
|
||||
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
static block_header* heap_list_head = nullptr;
|
||||
extern UInt64 sys_mem(UInt64 size);
|
||||
|
||||
void combine_forward(block_header* curr) {
|
||||
if (!curr->next || !curr->next->is_free) return;
|
||||
curr->size += sizeof(block_header) + curr->next->size;
|
||||
curr->next = curr->next->next;
|
||||
if (curr->next) curr->next->prev = curr; // what the fuck
|
||||
}
|
||||
|
||||
void* malloc(UInt64 size) {
|
||||
if (size == 0) return nullptr;
|
||||
UInt64 aligned_size = (size + 15) & ~15;
|
||||
|
||||
block_header* curr = heap_list_head;
|
||||
block_header* last = nullptr;
|
||||
while (curr) {
|
||||
if (curr->is_free && curr->size >= aligned_size) {
|
||||
if (curr->size > aligned_size + sizeof(block_header) + 16) {
|
||||
block_header* new_block = (block_header*)((UInt64)curr + sizeof(block_header) + aligned_size);
|
||||
new_block->size = curr->size - aligned_size - sizeof(block_header);
|
||||
new_block->is_free = true;
|
||||
new_block->next = curr->next;
|
||||
new_block->prev = curr;
|
||||
new_block->magic = HEADER_MAGIC;
|
||||
|
||||
if (curr->next) curr->next->prev = new_block;
|
||||
curr->next = new_block;
|
||||
curr->size = aligned_size;
|
||||
}
|
||||
curr->is_free = false;
|
||||
return (void*)((UInt64)curr + sizeof(block_header));
|
||||
}
|
||||
last = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
UInt64 need_to_alloc = aligned_size + sizeof(block_header);
|
||||
|
||||
UInt64 page_aligned_size = (need_to_alloc + 4095) & ~4095;
|
||||
|
||||
UInt64 new_mem_addr = sys_mem(page_aligned_size);
|
||||
if (new_mem_addr == 0) return nullptr;
|
||||
|
||||
block_header* new_block = (block_header*)new_mem_addr;
|
||||
new_block->size = page_aligned_size - sizeof(block_header);
|
||||
new_block->is_free = true;
|
||||
new_block->magic = HEADER_MAGIC;
|
||||
new_block->next = nullptr;
|
||||
new_block->prev = last;
|
||||
|
||||
if (last) {
|
||||
last->next = new_block;
|
||||
} else {
|
||||
heap_list_head = new_block;
|
||||
}
|
||||
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void free(void* ptr) {
|
||||
if (!ptr) return;
|
||||
|
||||
block_header* curr = (block_header*)((UInt64)ptr - sizeof(block_header));
|
||||
if (curr->magic != HEADER_MAGIC) return;
|
||||
|
||||
curr->is_free = true;
|
||||
if (curr->next && curr->next->is_free) combine_forward(curr);
|
||||
if (curr->prev && curr->prev->is_free) combine_forward(curr->prev);
|
||||
}
|
||||
|
||||
void* realloc(void* ptr, UInt64 new_size) {
|
||||
if (!ptr) return malloc(new_size);
|
||||
if (new_size == 0) {
|
||||
free(ptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
block_header* curr = (block_header*)((UInt64)ptr - sizeof(block_header));
|
||||
if (curr->size >= new_size) return ptr;
|
||||
|
||||
if (curr->next &&
|
||||
curr->next->is_free &&
|
||||
(curr->size + sizeof(block_header) + curr->next->size) >= new_size) { // why ts so fucking unreadable
|
||||
combine_forward(curr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* new_ptr = malloc(new_size);
|
||||
if (!new_ptr) return nullptr;
|
||||
|
||||
memcpy(new_ptr, ptr, curr->size);
|
||||
free(ptr);
|
||||
|
||||
return new_ptr;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <process.h>
|
||||
|
||||
extern Int32 sys_spawn(const char* path);
|
||||
extern Int32 sys_wait(UInt64 pid);
|
||||
|
||||
Int32 spawn(const char* path) {
|
||||
return sys_spawn(path);
|
||||
}
|
||||
|
||||
Int32 wait(UInt64 pid) {
|
||||
return sys_wait(pid);
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
// 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;
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static char* olds;
|
||||
|
||||
void *memset(void *ptr, int value, usize num) {
|
||||
UInt8 *p = (UInt8 *)ptr;
|
||||
while (num--) {
|
||||
*p++ = (UInt8)value;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* memcpy(void* dest, const void* src, UInt64 n) {
|
||||
UInt8* d = (UInt8*)dest;
|
||||
const UInt8* s = (const UInt8*)src;
|
||||
|
||||
while (n >= 8) {
|
||||
*(UInt64*)d = *(const UInt64*)s;
|
||||
d += 8;
|
||||
s += 8;
|
||||
n -= 8;
|
||||
}
|
||||
|
||||
while (n > 0) {
|
||||
*d++ = *s++;
|
||||
n--;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
Int32 strcmp(const char *s1, const char *s2) {
|
||||
while (*s1 && (*s1 == *s2)) {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return *(const unsigned char*)s1 - *(const unsigned char*)s2;
|
||||
}
|
||||
|
||||
Int32 strncmp(const char* s1, const char* s2, UInt64 n) {
|
||||
while (n > 0) {
|
||||
if (*s1 != *s2) return *(unsigned char*)s1 - *(unsigned char*)s2;
|
||||
if (*s1 == '\0') return 0;
|
||||
s1++;
|
||||
s2++;
|
||||
n--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* strcpy(char* dest, const char* src) {
|
||||
char* saved = dest;
|
||||
while (*src) *dest++ = *src++;
|
||||
*dest = 0;
|
||||
return saved;
|
||||
}
|
||||
|
||||
char* strncpy(char* dest, const char* src, UInt64 n) {
|
||||
char* saved = dest;
|
||||
while (*src && n > 0) {
|
||||
*dest++ = *src++;
|
||||
n--;
|
||||
}
|
||||
while (n > 0) {
|
||||
*dest++ = 0;
|
||||
n--;
|
||||
}
|
||||
return saved;
|
||||
}
|
||||
|
||||
UInt64 strlen(const char* str) {
|
||||
UInt64 res = 0;
|
||||
for (res = 0; str[res]; res++);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int is_in_set(char c, const char* set) {
|
||||
while (*set) {
|
||||
if (*set == c) return 1;
|
||||
set++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt64 strspn(const char* s, const char* accept) {
|
||||
UInt64 count = 0;
|
||||
while (*s && is_in_set(*s, accept)) {
|
||||
count++;
|
||||
s++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
char* strpbrk(const char* s, const char* accept) {
|
||||
while (*s) {
|
||||
if (is_in_set(*s, accept)) {
|
||||
return (char*)s;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
// took from https://github.com/walac/glibc/blob/master/string/strtok.c
|
||||
char* strtok(char *s, const char* delim) {
|
||||
char* token;
|
||||
if (s == nullptr) s = olds;
|
||||
s += strspn(s, delim);
|
||||
if (*s == '\0') {
|
||||
olds = s;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
token = s;
|
||||
s = strpbrk(token, delim);
|
||||
if (s == nullptr) olds = token + strlen(token);
|
||||
else {
|
||||
*s = '\0';
|
||||
olds = s + 1;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
Reference in New Issue
Block a user