Adds dynamic.h and dynamic.S creating a dynamic call utility.

This commit is contained in:
Felix Queissner 2015-08-14 23:53:51 +02:00
parent 0f54fabc99
commit 6cea5944c3
9 changed files with 241 additions and 531 deletions

View file

@ -17,8 +17,8 @@ LEX=flex
YACC=bison
# Flags
FLAGS=-m32 -Dnullptr=0 -D__cdecl="__attribute__((cdecl))"
ASFLAGS=
FLAGS=-m32 -Dnullptr=0 -D__cdecl="__attribute__((cdecl))" -mno-sse -mno-sse2 -mno-mmx
ASFLAGS=-masm=intel
CCFLAGS=-g -std=c11 -Dnullptr=0 -Wall -g -fno-stack-protector -ffreestanding -Iinclude
CXXFLAGS=-g -std=c++11 -Wall -g -fno-stack-protector -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -Wall -Wextra -ffreestanding -Wno-unused-function -Iinclude
LDFLAGS=-g -m32 -nostdlib -fno-builtin -Tkernel.ld

View file

@ -10,14 +10,14 @@ LEX = flex
YACC = bison
# File Lists
SRCS_AS = asm/intr_common_handler.S asm/multiboot.S asm/start.S
SRCS_AS = asm/dynamic.S asm/intr_common_handler.S asm/multiboot.S asm/start.S
SRCS_CC = src/console.c src/init.c src/interrupts.c src/malloc.c src/pmm.c src/stdlib.c src/timer.c src/vmm.c
SRCS_CXX = trainscript/tsvm.cpp src/cplusplus.cpp src/vm.cpp obj/trainscript.yy.cpp obj/trainscript.tab.cpp
OBJS = obj/tsvm.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
OBJS = obj/tsvm.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
# Flags
FLAGS = -m32 -Dnullptr=0 -D__cdecl="__attribute__((cdecl))"
ASFLAGS =
FLAGS = -m32 -Dnullptr=0 -D__cdecl="__attribute__((cdecl))" -mno-sse -mno-sse2 -mno-mmx
ASFLAGS = -masm=intel
CCFLAGS = -g -std=c11 -Dnullptr=0 -Wall -g -fno-stack-protector -ffreestanding -Iinclude
CXXFLAGS = -g -std=c++11 -Wall -g -fno-stack-protector -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -Wall -Wextra -ffreestanding -Wno-unused-function -Iinclude
LDFLAGS = -g -m32 -nostdlib -fno-builtin -Tkernel.ld
@ -27,10 +27,10 @@ all: kernel
.PHONY: clean
clean:
$(RM) obj/trainscript.yy.cpp obj/trainscript.tab.cpp obj/tsvm.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
$(RM) obj/trainscript.yy.cpp obj/trainscript.tab.cpp obj/tsvm.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
kernel: obj/tsvm.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
$(LD) $(FLAGS) $(LDFLAGS) -o $@ obj/tsvm.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
kernel: obj/tsvm.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
$(LD) $(FLAGS) $(LDFLAGS) -o $@ obj/tsvm.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
# src/console.c
obj/console.o: src/console.c include/console.h include/stdlib.h \
@ -89,9 +89,10 @@ obj/cplusplus.o: src/cplusplus.cpp include/stdlib.h include/varargs.h \
# src/vm.cpp
obj/vm.o: src/vm.cpp include/stdlib.h include/varargs.h include/timer.h \
src/../trainscript/tsvm.hpp include/console.h include/ker/string.hpp \
include/ker/vector.hpp include/ker/new.hpp include/ker/dictionary.hpp \
include/kernel.h include/ker/pair.hpp src/../trainscript/typeid.hpp
include/dynamic.h src/../trainscript/tsvm.hpp include/console.h \
include/ker/string.hpp include/ker/vector.hpp include/ker/new.hpp \
include/ker/dictionary.hpp include/kernel.h include/ker/pair.hpp \
src/../trainscript/typeid.hpp
$(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c src/vm.cpp
# obj/trainscript.yy.cpp
@ -112,6 +113,10 @@ obj/trainscript.tab.o: obj/trainscript.tab.cpp include/stdlib.h \
include/string.h
$(CXX) -iquotetrainscript $(FLAGS) $(CXXFLAGS) -o $@ -c obj/trainscript.tab.cpp
# asm/dynamic.S
obj/dynamic.o: asm/dynamic.S
$(AS) $(FLAGS) $(ASFLAGS) -o $@ -c asm/dynamic.S
# asm/intr_common_handler.S
obj/intr_common_handler.o: asm/intr_common_handler.S
$(AS) $(FLAGS) $(ASFLAGS) -o $@ -c asm/intr_common_handler.S

42
asm/dynamic.S Normal file
View file

@ -0,0 +1,42 @@
.section .text
.intel_syntax noprefix
.extern _callee
/**
* void __cdecl dynamic_call(void *func, void *stack, size_t stacksize)
*/
.global dynamic_call
dynamic_call:
/* save everything except EAX, ECX, EDX */
push ebx
push esi
push edi
/* setup call */
mov ebx, [esp+0x18] /* stacksize */
mov eax, [esp+0x10] /* function */
mov esi /* src */, [esp+0x14] /* stackptr */
sub esp, ebx /* adjust stack pointer for call */
mov edi /* dst */, esp
mov ecx /* num */, ebx
/* jump to label if we don't need to copy anything */
cmp ebx, 0x00
jz label
/* copy virtual stack data */
cld
rep movsb
label:
/* call function and restore stack */
call eax
add esp, ebx /* ebx = stacksize */
/* clean up */
pop edi
pop esi
pop ebx
ret

12
include/dynamic.h Normal file
View file

@ -0,0 +1,12 @@
#pragma once
#include <inttypes.h>
#if defined(__cplusplus)
extern "C" {
#endif
extern void __cdecl dynamic_call(void *func, void *stack, uint32_t stackSize);
#if defined(__cplusplus)
}
#endif

View file

@ -2,7 +2,10 @@ VAR global : INT;
PUB main() | i : INT
BEGIN
fun() -> i;
0 -> i;
# Print numbers from 1 to 5
WHILE ((i + 1) -> i) <= 5 DO
printInt(i);
END
PUB fun() -> i : INT

View file

@ -150,6 +150,10 @@ void init(const MultibootStructure *mbHeader)
cpp_init();
putsuccess();
double f = 1.0;
int i = (int)f;
vm_start();
kputs("\x12\x04trainOS stopped.\x12\x07!\n");

View file

@ -1,5 +1,6 @@
#include <stdlib.h>
#include <timer.h>
#include <dynamic.h>
#include "../trainscript/tsvm.hpp"
using namespace ker;
@ -37,7 +38,9 @@ public:
}
Vector<Type> arguments() const {
return Vector<Type>();
Vector<Type> list;
list.append(Type::Int);
return list;
}
Type returnType() const {
@ -45,16 +48,6 @@ public:
}
};
static void copyCode(uint8_t **ptr, const uint8_t *src, size_t length)
{
for(size_t i = 0; i < length; i++) {
// Copy byte
**ptr = src[i];
// Iterate
(*ptr)++;
}
}
/**
* @brief Invokes a cdecl function
* @param arguments Arguments passed to the c function
@ -66,66 +59,45 @@ Variable NativeMethod::invoke(Vector<Variable> arguments)
return Variable::Invalid;
}
// ASM code:
// push ebp
// mov ebp, esp
// (push imm32) * num
// call [function]
// add esp, 4 * num
// ret
uint8_t headerCode[] = {
0x55, // push ebp
0x89, 0xE5, // mov ebp, esp
};
uint8_t tailCode[] = {
0xB8, 0x42, 0x00, 0x00, 0x00, // mov eax,0x42
0xFF, 0xD0, // call eax
0x83, 0xC4, 0x08, // add esp, 0x00
0xC9, // leave
// 0x5D, // pop ebp
0xC3, // ret
};
// Store some memory for a function
uint8_t pushCode[] = {
0x68, 0x00, 0x00, 0x00, 0x00 // push 0x00
};
size_t stackSize = 4 * arguments.length();
// Copy target address to mov eax, 0x42
*reinterpret_cast<uintptr_t*>(&tailCode[1]) = reinterpret_cast<uintptr_t>(this->function);
// Copy stack size to add esp, 0x00
*reinterpret_cast<uint8_t*>(&tailCode[9]) = static_cast<uint8_t>(stackSize);
uint8_t code[128];
// Built the function
{
uint8_t *codePtr = &code[0];
// Copy function header
copyCode(&codePtr, headerCode, sizeof(headerCode));
// Copy arguments
for(int i = arguments.length() - 1; i >= 0; i--) {
// Copy argument value to push 0x00
*reinterpret_cast<int32_t*>(&pushCode[1]) = reinterpret_cast<int32_t>(arguments[i].integer);
// Copy push code
copyCode(&codePtr, pushCode, sizeof(pushCode));
// Copy arguments
size_t stackSize = 0;
for(int i = 0; i < arguments.length(); i++) {
switch(arguments[i].type.id) {
case TypeID::Bool: stackSize += sizeof(Int); break;
case TypeID::Int: stackSize += sizeof(Int); break;
case TypeID::Real: stackSize += sizeof(Real); break;
default: die("invalid argument type."); break;
}
// Copy function end
copyCode(&codePtr, tailCode, sizeof(tailCode));
}
// Call some crazy
uint32_t (*func)() = (uint32_t(*)())code;
uint8_t *stack = (uint8_t*)malloc(stackSize);
for(int i = arguments.length() - 1; i >= 0; i--) {
switch(arguments[i].type.id) {
case TypeID::Bool:
*reinterpret_cast<Int*>(stack) = arguments[i].boolean ? 1 : 0;
stack += sizeof(Int);
break;
case TypeID::Int:
*reinterpret_cast<Int*>(stack) = arguments[i].integer;
stack += sizeof(Int);
break;
case TypeID::Real:
*reinterpret_cast<Real*>(stack) = arguments[i].real;
stack += sizeof(Real);
break;
default: die("invalid argument type."); break;
}
}
uint32_t result = func();
dynamic_call(this->function, stack-stackSize, stackSize);
return mkvar((Int)result);
free(stack);
return mkvar((Int)0);
}
extern "C" void __cdecl printInt(int i) {
kprintf("{%d}\n", i);
}
struct NativeModuleDef
@ -138,6 +110,7 @@ NativeModuleDef methods[] = {
{ "sleep", (void*)sleep },
{ "timer_get", (void*)timer_get },
{ "timer_set", (void*)timer_set },
{ "printInt", (void*)printInt },
{ nullptr, 0 }
};
@ -151,23 +124,17 @@ extern "C" void vm_start()
(uint32_t)&mainscript_size
};
// cpp_test();
// cpp_test();
kprintf("Parse kernel module: ");
kprintf("Parse kernel module: ");
Module *module = VM::load(mainfile.ptr, mainfile.size);
if(module == nullptr) {
kprintf("Could not load module :(\n");
return;
}
kprintf("Module successfully loaded :)\n");
String errorCode;
if(module->validate(errorCode) == false) {
kprintf("Module validation failed: \x12\x06%s\x12\x07\n", errorCode.str());
if(module == nullptr) {
kprintf("Could not load module :(\n");
return;
}
kprintf("Module successfully loaded :)\n");
// Load native modules
NativeModuleDef *mod = methods;
while(mod->name != nullptr) {
@ -175,155 +142,161 @@ extern "C" void vm_start()
mod++;
}
Method *main = module->method("main");
if(main == nullptr) {
kprintf("Script has no main method.\n");
return;
}
String errorCode;
if(module->validate(errorCode) == false) {
kprintf("Module validation failed: \x12\x06%s\x12\x07\n", errorCode.str());
return;
}
main->invoke({ });
Method *main = module->method("main");
if(main == nullptr) {
kprintf("Script has no main method.\n");
return;
}
delete module;
main->invoke({ });
delete module;
}
String fn()
String strfn()
{
return String("keks");
return String("keks");
}
void put(Vector<int> &v)
{
kprintf("v[%d]: ", v.length());
for(int i : v) { kprintf("%d,", i); }
kprintf("\n");
kprintf("v[%d]: ", v.length());
for(int i : v) { kprintf("%d,", i); }
kprintf("\n");
}
void put(Vector<String> &v)
{
kprintf("v[%d]: ", v.length());
for(String &s : v) { kprintf("[%s],", s.str()); }
kprintf("\n");
kprintf("v[%d]: ", v.length());
for(String &s : v) { kprintf("[%s],", s.str()); }
kprintf("\n");
}
void put(Dictionary<int, int> &d)
{
kprintf("dict: ");
for(auto &it : d)
{
kprintf("[%d -> %d] ", it.first, it.second);
}
kprintf("\n");
kprintf("dict: ");
for(auto &it : d)
{
kprintf("[%d -> %d] ", it.first, it.second);
}
kprintf("\n");
}
void put(Dictionary<String, String> &d)
{
kprintf("dict: ");
for(auto &it : d)
{
kprintf("[%s -> %s] ", it.first.str(), it.second.str());
}
kprintf("\n");
kprintf("dict: ");
for(auto &it : d)
{
kprintf("[%s -> %s] ", it.first.str(), it.second.str());
}
kprintf("\n");
}
void cpp_test()
{
kprintf("Testing ker::String:\n");
{
String a("hello");
String b(a);
String c;
String d(fn());
String e;
c = a;
e = fn();
kprintf("Testing ker::String:\n");
{
String a("hello");
String b(a);
String c;
String d(strfn());
String e;
c = a;
e = strfn();
kprintf("'%s' '%s' '%s' '%s' '%s'\n", a.str(), b.str(), c.str(), d.str(), e.str());
}
kprintf("'%s' '%s' '%s' '%s' '%s'\n", a.str(), b.str(), c.str(), d.str(), e.str());
}
kprintf("Testing ker::Pair:\n");
{
Pair<int, int> a(10, 20);
Pair<String, String> b("Hey", "Affe");
kprintf("Testing ker::Pair:\n");
{
Pair<int, int> a(10, 20);
Pair<String, String> b("Hey", "Affe");
Pair<int, int> c(a);
Pair<String, String> d(b);
Pair<int, int> c(a);
Pair<String, String> d(b);
Pair<int, int> e; e = a;
Pair<String, String> f; f = b;
Pair<int, int> e; e = a;
Pair<String, String> f; f = b;
kprintf("'%d,%d' '%d,%d' '%d,%d'\n", a.first, a.second, c.first, c.second, e.first, e.second);
kprintf("'%s,%s' '%s,%s' '%s,%s'\n", b.first.str(), b.second.str(), d.first.str(), d.second.str(), f.first.str(), f.second.str());
}
kprintf("'%d,%d' '%d,%d' '%d,%d'\n", a.first, a.second, c.first, c.second, e.first, e.second);
kprintf("'%s,%s' '%s,%s' '%s,%s'\n", b.first.str(), b.second.str(), d.first.str(), d.second.str(), f.first.str(), f.second.str());
}
kprintf("Testing ker::Vector:\n");
{
Vector<int> a;
a.append(1);
a.append(2);
a.append(3);
kprintf("Testing ker::Vector:\n");
{
Vector<int> a;
a.append(1);
a.append(2);
a.append(3);
Vector<int> c;
Vector<int> b(a);
c = a;
Vector<int> c;
Vector<int> b(a);
c = a;
put(a);
put(b);
put(c);
}
{
Vector<String> a;
a.append("x");
a.append("y");
a.append("z");
put(a);
put(b);
put(c);
}
{
Vector<String> a;
a.append("x");
a.append("y");
a.append("z");
Vector<String> c;
Vector<String> b(a);
c = a;
Vector<String> c;
Vector<String> b(a);
c = a;
put(a);
put(b);
put(c);
}
put(a);
put(b);
put(c);
}
kprintf("Testing ker::Dictionary:\n");
{
kprintf("int -> int\n");
Dictionary<int, int> a;
a.add(1, 30);
a.add(2, 20);
a.add(3, 10);
kprintf("Testing ker::Dictionary:\n");
{
kprintf("int -> int\n");
Dictionary<int, int> a;
a.add(1, 30);
a.add(2, 20);
a.add(3, 10);
kprintf("%d %d\n", a.contains(1), a.contains(4));
kprintf("%d %d\n", a.at(1), a.at(3));
kprintf("%d %d\n", a[1], a[3]);
kprintf("%d %d\n", a.contains(1), a.contains(4));
kprintf("%d %d\n", a.at(1), a.at(3));
kprintf("%d %d\n", a[1], a[3]);
Dictionary<int, int> b(a);
Dictionary<int, int> c;
c = a;
Dictionary<int, int> b(a);
Dictionary<int, int> c;
c = a;
put(a);
put(b);
put(c);
}
put(a);
put(b);
put(c);
}
{
kprintf("String -> String\n");
Dictionary<String, String> a;
a.add("x", "30");
a.add("y", "20");
a.add("z", "10");
{
kprintf("String -> String\n");
Dictionary<String, String> a;
a.add("x", "30");
a.add("y", "20");
a.add("z", "10");
kprintf("%d %d\n", a.contains("x"), a.contains("w"));
kprintf("%s %s\n", a.at("x").str(), a.at("z").str());
kprintf("%s %s\n", a["x"].str(), a["z"].str());
kprintf("%d %d\n", a.contains("x"), a.contains("w"));
kprintf("%s %s\n", a.at("x").str(), a.at("z").str());
kprintf("%s %s\n", a["x"].str(), a["z"].str());
Dictionary<String, String> b(a);
Dictionary<String, String> c;
c = a;
Dictionary<String, String> b(a);
Dictionary<String, String> c;
c = a;
put(a);
put(b);
put(c);
}
put(a);
put(b);
put(c);
}
}

View file

@ -1,331 +0,0 @@
#include <stdlib.h>
#include <timer.h>
#include "../trainscript/tsvm.hpp"
using namespace ker;
using namespace trainscript;
extern "C" {
extern const char mainscript_start;
extern const char mainscript_end;
extern const char mainscript_size;
}
void cpp_test();
class NativeMethod :
public Method
{
private:
void *function;
public:
NativeMethod(void *fn) :
function(fn)
{
}
Variable invoke(Vector<Variable> arguments) override;
bool validate(ker::String &errorCode) const
{
if(this->function == nullptr) {
errorCode = "Native method with nullptr interface.";
return false;
}
return true;
}
Vector<Type> arguments() const {
return Vector<Type>();
}
Type returnType() const {
return Type::Int;
}
};
static void copyCode(uint8_t **ptr, const uint8_t *src, size_t length)
{
for(size_t i = 0; i < length; i++) {
// Copy byte
**ptr = src[i];
// Iterate
(*ptr)++;
}
}
/**
* @brief Invokes a cdecl function
* @param arguments Arguments passed to the c function
* @return uint32_t return value of the c function
*/
Variable NativeMethod::invoke(Vector<Variable> arguments)
{
if(this->function == nullptr) {
return Variable::Invalid;
}
// ASM code:
// push ebp
// mov ebp, esp
// (push imm32) * num
// call [function]
// add esp, 4 * num
// ret
uint8_t headerCode[] = {
0x55, // push ebp
0x89, 0xE5, // mov ebp, esp
};
uint8_t tailCode[] = {
0xB8, 0x42, 0x00, 0x00, 0x00, // mov eax,0x42
0xFF, 0xD0, // call eax
0x83, 0xC4, 0x08, // add esp, 0x00
0xC9, // leave
// 0x5D, // pop ebp
0xC3, // ret
};
// Store some memory for a function
uint8_t pushCode[] = {
0x68, 0x00, 0x00, 0x00, 0x00 // push 0x00
};
size_t stackSize = 4 * arguments.length();
// Copy target address to mov eax, 0x42
*reinterpret_cast<uintptr_t*>(&tailCode[1]) = reinterpret_cast<uintptr_t>(this->function);
// Copy stack size to add esp, 0x00
*reinterpret_cast<uint8_t*>(&tailCode[9]) = static_cast<uint8_t>(stackSize);
uint8_t code[128];
// Built the function
{
uint8_t *codePtr = &code[0];
// Copy function header
copyCode(&codePtr, headerCode, sizeof(headerCode));
// Copy arguments
for(int i = arguments.length() - 1; i >= 0; i--) {
// Copy argument value to push 0x00
*reinterpret_cast<int32_t*>(&pushCode[1]) = reinterpret_cast<int32_t>(arguments[i].integer);
// Copy push code
copyCode(&codePtr, pushCode, sizeof(pushCode));
}
// Copy function end
copyCode(&codePtr, tailCode, sizeof(tailCode));
}
// Call some crazy
uint32_t (*func)() = (uint32_t(*)())code;
uint32_t result = func();
return mkvar((Int)result);
}
struct NativeModuleDef
{
const char *name;
void *function;
};
NativeModuleDef methods[] = {
{ "sleep", (void*)sleep },
{ "timer_get", (void*)timer_get },
{ "timer_set", (void*)timer_set },
{ nullptr, 0 }
};
extern "C" void vm_start()
{
struct {
const char *ptr;
uint32_t size;
} mainfile {
&mainscript_start,
(uint32_t)&mainscript_size
};
// cpp_test();
kprintf("Parse kernel module: ");
Module *module = VM::load(mainfile.ptr, mainfile.size);
if(module == nullptr) {
kprintf("Could not load module :(\n");
return;
}
kprintf("Module successfully loaded :)\n");
String errorCode;
if(module->validate(errorCode) == false) {
kprintf("Module validation failed: \x12\x06%s\x12\x07\n", errorCode.str());
return;
}
// Load native modules
NativeModuleDef *mod = methods;
while(mod->name != nullptr) {
module->methods.add(mod->name, new NativeMethod(mod->function));
mod++;
}
Method *main = module->method("main");
if(main == nullptr) {
kprintf("Script has no main method.\n");
return;
}
main->invoke({ });
delete module;
}
String fn()
{
return String("keks");
}
void put(Vector<int> &v)
{
kprintf("v[%d]: ", v.length());
for(int i : v) { kprintf("%d,", i); }
kprintf("\n");
}
void put(Vector<String> &v)
{
kprintf("v[%d]: ", v.length());
for(String &s : v) { kprintf("[%s],", s.str()); }
kprintf("\n");
}
void put(Dictionary<int, int> &d)
{
kprintf("dict: ");
for(auto &it : d)
{
kprintf("[%d -> %d] ", it.first, it.second);
}
kprintf("\n");
}
void put(Dictionary<String, String> &d)
{
kprintf("dict: ");
for(auto &it : d)
{
kprintf("[%s -> %s] ", it.first.str(), it.second.str());
}
kprintf("\n");
}
void cpp_test()
{
kprintf("Testing ker::String:\n");
{
String a("hello");
String b(a);
String c;
String d(fn());
String e;
c = a;
e = fn();
kprintf("'%s' '%s' '%s' '%s' '%s'\n", a.str(), b.str(), c.str(), d.str(), e.str());
}
kprintf("Testing ker::Pair:\n");
{
Pair<int, int> a(10, 20);
Pair<String, String> b("Hey", "Affe");
Pair<int, int> c(a);
Pair<String, String> d(b);
Pair<int, int> e; e = a;
Pair<String, String> f; f = b;
kprintf("'%d,%d' '%d,%d' '%d,%d'\n", a.first, a.second, c.first, c.second, e.first, e.second);
kprintf("'%s,%s' '%s,%s' '%s,%s'\n", b.first.str(), b.second.str(), d.first.str(), d.second.str(), f.first.str(), f.second.str());
}
kprintf("Testing ker::Vector:\n");
{
Vector<int> a;
a.append(1);
a.append(2);
a.append(3);
Vector<int> c;
Vector<int> b(a);
c = a;
put(a);
put(b);
put(c);
}
{
Vector<String> a;
a.append("x");
a.append("y");
a.append("z");
Vector<String> c;
Vector<String> b(a);
c = a;
put(a);
put(b);
put(c);
}
kprintf("Testing ker::Dictionary:\n");
{
kprintf("int -> int\n");
Dictionary<int, int> a;
a.add(1, 30);
a.add(2, 20);
a.add(3, 10);
kprintf("%d %d\n", a.contains(1), a.contains(4));
kprintf("%d %d\n", a.at(1), a.at(3));
kprintf("%d %d\n", a[1], a[3]);
Dictionary<int, int> b(a);
Dictionary<int, int> c;
c = a;
put(a);
put(b);
put(c);
}
{
kprintf("String -> String\n");
Dictionary<String, String> a;
a.add("x", "30");
a.add("y", "20");
a.add("z", "10");
kprintf("%d %d\n", a.contains("x"), a.contains("w"));
kprintf("%s %s\n", a.at("x").str(), a.at("z").str());
kprintf("%s %s\n", a["x"].str(), a["z"].str());
Dictionary<String, String> b(a);
Dictionary<String, String> c;
c = a;
put(a);
put(b);
put(c);
}
}

View file

@ -38,7 +38,8 @@ HEADERS += \
include/ker/vector.hpp \
include/ker/dictionary.hpp \
include/string.h \
include/ker/new.hpp
include/ker/new.hpp \
include/dynamic.h
DISTFILES += \
asm/intr_common_handler.S \
@ -54,7 +55,8 @@ DISTFILES += \
kernel.ld \
Depfile \
Makefile.new \
scripts/main.ts
scripts/main.ts \
asm/dynamic.S
QMAKE_INCDIR =