| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- #include "SystemFunctions.h"
- #include <stdio.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <termios.h>
- #include <threads.h>
- #include <unistd.h>
- #include "Memory.h"
- #include "Utils.h"
- #include "Window.h"
- #define RETURN_INT(value) \
- *r = INT_VALUE(value); \
- return false
- static u32 seed = 0;
- static bool rawMode = false;
- static struct termios originalTerminal;
- static void append(char** buffer, size_t* n, int change) {
- if(change > 0) {
- *buffer += change;
- *n -= (size_t)change;
- }
- }
- static void printUnicode(const Value* v, char** buffer, size_t* n) {
- UTF8 u = convertUnicodeToUTF8(v->data);
- for(u32 l = 0; l < u.length && *n > 1; l++) {
- **buffer = u.data[l];
- append(buffer, n, 1);
- }
- if(*n > 0) {
- **buffer = '\0';
- }
- }
- #define APPEND(b, n, format, ...) \
- append(b, n, snprintf(*b, *n, format __VA_OPT__(, ) __VA_ARGS__));
- static void printArray(
- const Code* c, const Value* v, char** buffer, size_t* n) {
- if(v->data == -1) {
- APPEND(buffer, n, "null array");
- return;
- }
- Allocation* a = memoryConvertToPointer(v->data);
- Value* end = a->values + a->values[0].data + 1;
- for(Value* i = a->values + 1; i != end; i++) {
- switch(i->type) {
- case VT_INT32: printUnicode(i, buffer, n); break;
- case VT_ARRAY: APPEND(buffer, n, "array"); break;
- case VT_CONSTANT_STRING:
- APPEND(buffer, n, "%s", c->code.data + i->data);
- break;
- }
- }
- }
- static void print(const Code* c, Value* vs, i32 n, char* buffer, size_t bn) {
- for(i32 i = 0; i < n; i++) {
- Value* v = vs + i;
- switch(v->type) {
- case VT_INT32: APPEND(&buffer, &bn, "%d", v->data); break;
- case VT_ARRAY: printArray(c, v, &buffer, &bn); break;
- case VT_CONSTANT_STRING:
- APPEND(&buffer, &bn, "%s", c->code.data + v->data);
- break;
- }
- }
- }
- static bool sfPrint(Code* c, Value* r, Value* vs, i32 n) {
- char buffer[1024];
- print(c, vs, n, buffer, sizeof(buffer));
- fputs(buffer, stdout);
- RETURN_INT(0);
- }
- static bool sfRender(Code* c, Value* r, Value* vs, i32 n) {
- i32 x = vs[0].data;
- i32 y = vs[1].data;
- Color color = (Color)vs[2].data;
- char buffer[1024];
- print(c, vs + 3, n - 3, buffer, sizeof(buffer));
- char* s = buffer;
- while(*s != 0) {
- UTF8 u = {.data = {*(s++)}, .length = 1};
- for(int k = 0; k < 3 && isUTF8Remainder(*s); k++) {
- u.data[u.length] = *s;
- u.length++;
- s++;
- }
- i32 i = convertUTF8toUnicode(u);
- windowSetCharacter(x, y, i, color);
- x += 8;
- }
- RETURN_INT(0);
- }
- static bool sfPrintLine(Code* c, Value* r, Value* vs, i32 n) {
- bool b = sfPrint(c, r, vs, n);
- putchar('\n');
- return b;
- }
- #define ESC "\33["
- #define esc(s) fputs(ESC s, stdout)
- static bool sfClear(Code*, Value* r, Value*, i32) {
- esc("2J");
- RETURN_INT(0);
- }
- static bool sfGetWidth(Code*, Value* r, Value*, i32) {
- struct winsize w;
- if(ioctl(0, TIOCGWINSZ, &w)) {
- RETURN_INT(0);
- }
- RETURN_INT(w.ws_col);
- }
- static bool sfGetHeight(Code*, Value* r, Value*, i32) {
- struct winsize w;
- if(ioctl(0, TIOCGWINSZ, &w)) {
- RETURN_INT(0);
- }
- RETURN_INT(w.ws_row);
- }
- static bool sfClearLine(Code*, Value* r, Value*, i32) {
- esc("2K\r");
- RETURN_INT(0);
- }
- static bool sfHideCursor(Code*, Value* r, Value*, i32) {
- esc("?25l");
- RETURN_INT(0);
- }
- static bool sfShowCursor(Code*, Value* r, Value*, i32) {
- esc("?25h");
- RETURN_INT(0);
- }
- static bool sfResetCursor(Code*, Value* r, Value*, i32) {
- esc("H");
- RETURN_INT(0);
- }
- static bool sfMoveCursorLeft(Code*, Value* r, Value* vs, i32) {
- if(vs[0].data > 0) {
- printf(ESC "%dD", vs[0].data);
- }
- RETURN_INT(0);
- }
- static bool sfMoveCursorRight(Code*, Value* r, Value* vs, i32) {
- if(vs[0].data > 0) {
- printf(ESC "%dC", vs[0].data);
- }
- RETURN_INT(0);
- }
- static bool sfMoveCursorUp(Code*, Value* r, Value* vs, i32) {
- if(vs[0].data > 0) {
- printf(ESC "%dA", vs[0].data);
- }
- RETURN_INT(0);
- }
- static bool sfMoveCursorDown(Code*, Value* r, Value* vs, i32) {
- if(vs[0].data > 0) {
- printf(ESC "%dB", vs[0].data);
- }
- RETURN_INT(0);
- }
- static bool sfSleep(Code*, Value* r, Value* vs, i32) {
- struct timespec t = {.tv_sec = vs[0].data, .tv_nsec = vs[1].data};
- thrd_sleep(&t, nullptr);
- RETURN_INT(0);
- }
- static bool sfRandom(Code*, Value* r, Value* vs, i32) {
- seed = seed * 1664525u + 1013904223u;
- u32 s = seed % (u32)(vs[1].data + 1 - vs[0].data);
- RETURN_INT(vs[0].data + (i32)s);
- }
- static bool codeAllocate(Code* c, Value* v, i32 n) {
- v->type = VT_ARRAY;
- v->data = -1;
- if(n <= 0) {
- return false;
- }
- codeRunCollector(c);
- size_t s = sizeof(Allocation) + ((size_t)n + 1) * sizeof(Value);
- Allocation* a = memoryAllocate(s);
- if(a == nullptr) {
- SET_ERROR("Out of memory");
- return true;
- }
- memset(a, 0, s);
- a->next = c->allocations;
- c->allocations = a;
- a->values[0].type = VT_INT32;
- a->values[0].data = n;
- v->data = memoryConvertToIndex(a);
- return false;
- }
- static bool sfArray(Code* c, Value* r, Value* vs, i32) {
- return codeAllocate(c, r, vs[0].data);
- }
- static bool sfGetAllocations(Code* c, Value* r, Value*, i32) {
- codeRunCollector(c);
- i32 counter = 0;
- for(Allocation* a = c->allocations; a != nullptr; a = a->next) {
- counter++;
- }
- RETURN_INT(counter);
- }
- static bool sfEnterRawTerminal(Code* c, Value* r, Value*, i32) {
- if(rawMode) {
- RETURN_INT(0);
- }
- if(tcgetattr(STDIN_FILENO, &originalTerminal)) {
- SET_ERROR("Cannot safe current terminal mode");
- return true;
- }
- struct termios raw = originalTerminal;
- raw.c_iflag &= ~(tcflag_t)(ICRNL | IXON);
- raw.c_lflag &= ~(tcflag_t)(ECHO | ICANON | IEXTEN | ISIG);
- raw.c_cc[VMIN] = 0;
- raw.c_cc[VTIME] = 0;
- if(tcsetattr(STDIN_FILENO, TCSANOW, &raw)) {
- SET_ERROR("Cannot enter raw terminal mode");
- return true;
- }
- RETURN_INT(0);
- }
- static bool sfLeaveRawTerminal(Code* c, Value* r, Value*, i32) {
- if(!rawMode) {
- RETURN_INT(0);
- }
- if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &originalTerminal)) {
- SET_ERROR("Cannot leave raw terminal mode");
- return true;
- }
- RETURN_INT(0);
- }
- static bool sfReadChar(Code*, Value* r, Value*, i32) {
- u8 ch = 0;
- ssize_t bytes = read(STDIN_FILENO, &ch, 1);
- RETURN_INT(bytes <= 0 ? '\0' : ch);
- }
- static bool sfFlush(Code*, Value* r, Value*, i32) {
- fflush(stdout);
- RETURN_INT(0);
- }
- static bool sfWindowInit(Code* c, Value* r, Value* vs, i32) {
- WindowSettings ws = {
- .width = vs[0].data, .height = vs[1].data, .title = "Dummy"};
- c->error = windowInit(&ws);
- *r = INT_VALUE(0);
- return hasError(&c->error);
- }
- #define WINDOW_CHECK() \
- do { \
- if(!windowExists()) { \
- SET_ERROR("No window exists"); \
- return true; \
- } \
- } while(false)
- static bool sfWindowShouldClose(Code* c, Value* r, Value*, i32) {
- WINDOW_CHECK();
- RETURN_INT(windowShouldClose());
- }
- static bool sfWindowNextFrame(Code* c, Value* r, Value*, i32) {
- WINDOW_CHECK();
- windowNextFrame();
- RETURN_INT(0);
- }
- static bool sfWindowClear(Code* c, Value* r, Value* vs, i32) {
- WINDOW_CHECK();
- windowClear((Color)vs[0].data);
- RETURN_INT(0);
- }
- static bool sfWindowSetPixel(Code* c, Value* r, Value* vs, i32) {
- WINDOW_CHECK();
- windowSetPixel(vs[0].data, vs[1].data, (Color)vs[2].data);
- RETURN_INT(0);
- }
- static bool sfColor(Code*, Value* r, Value* vs, i32) {
- RETURN_INT(COLOR(vs[0].data, vs[1].data, vs[2].data));
- }
- static bool sfGetRed(Code*, Value* r, Value* vs, i32) {
- RETURN_INT((vs[0].data & 0b1111100000000000) >> 11);
- }
- static bool sfGetGreen(Code*, Value* r, Value* vs, i32) {
- RETURN_INT((vs[0].data & 0b11111000000) >> 6);
- }
- static bool sfGetBlue(Code*, Value* r, Value* vs, i32) {
- RETURN_INT((vs[0].data & 0b111110) >> 1);
- }
- static bool sfIsButtonDown(Code*, Value* r, Value* vs, i32) {
- RETURN_INT(isButtonDown((Button)vs[0].data));
- }
- static bool sfGetButtonDownTime(Code*, Value* r, Value* vs, i32) {
- RETURN_INT(getButtonDownTime((Button)vs[0].data));
- }
- typedef struct {
- SystemFunction function;
- i32 arguments;
- const char* name;
- } FunctionEntry;
- static FunctionEntry systemFunctions[] = {
- {sfPrint, -1, "print"},
- {sfPrintLine, -1, "printLine"},
- {sfClear, 0, "clear"},
- {sfSleep, 2, "sleep"},
- {sfGetWidth, 0, "getWidth"},
- {sfGetHeight, 0, "getHeight"},
- {sfClearLine, 0, "clearLine"},
- {sfHideCursor, 0, "hideCursor"},
- {sfShowCursor, 0, "showCursor"},
- {sfResetCursor, 0, "resetCursor"},
- {sfMoveCursorLeft, 1, "moveCursorLeft"},
- {sfMoveCursorRight, 1, "moveCursorRight"},
- {sfMoveCursorUp, 1, "moveCursorUp"},
- {sfMoveCursorDown, 1, "moveCursorDown"},
- {sfRandom, 2, "random"},
- {sfArray, 1, "array"},
- {sfGetAllocations, 0, "getAllocations"},
- {sfEnterRawTerminal, 0, "enterRawTerminal"},
- {sfLeaveRawTerminal, 0, "leaveRawTerminal"},
- {sfReadChar, 0, "readChar"},
- {sfFlush, 0, "flush"},
- {sfWindowInit, 2, "initWindow"},
- {sfWindowShouldClose, 0, "shouldClose"},
- {sfWindowNextFrame, 0, "nextFrame"},
- {sfWindowClear, 1, "clearWindow"},
- {sfWindowSetPixel, 3, "setPixel"},
- {sfColor, 3, "color"},
- {sfGetRed, 1, "getRed"},
- {sfGetGreen, 1, "getGreen"},
- {sfGetBlue, 1, "getBlue"},
- {sfIsButtonDown, 1, "isButtonDown"},
- {sfGetButtonDownTime, 1, "getButtonDownTime"},
- {sfRender, -4, "render"},
- };
- static constexpr i32 amount = sizeof(systemFunctions) / sizeof(FunctionEntry);
- i32 getSystemFunctionIndex(const char* s) {
- for(i32 i = 0; i < amount; i++) {
- if(strcmp(systemFunctions[i].name, s) == 0) {
- return i;
- }
- }
- return -1;
- }
- i32 getSystemFunctionArguments(i32 index) {
- if(index >= 0 && index < amount) {
- return systemFunctions[index].arguments;
- }
- return -1;
- }
- SystemFunction getSystemFunction(i32 index) {
- if(index >= 0 && index < amount) {
- return systemFunctions[index].function;
- }
- return nullptr;
- }
- void initSystemFunctions() {
- struct timespec t = {};
- timespec_get(&t, TIME_UTC);
- seed = (u32)t.tv_nsec;
- }
|