From 4b55faa41e54589ac39bc59970da0aebf1768e32 Mon Sep 17 00:00:00 2001 From: krzosa Date: Sun, 10 Aug 2025 18:44:10 +0200 Subject: [PATCH] Porting to linux --- build.sh | 86 ++++++++++- build_file.cpp | 6 +- src/basic/basic.h | 1 + src/basic/filesystem.h | 2 +- src/basic/unix.cpp | 190 +++++++++++++++++++++++- src/basic/win32.cpp | 2 +- src/text_editor/generated.cpp | 2 +- src/text_editor/generated_variables.cpp | 2 +- src/text_editor/lua_api.cpp | 4 +- src/text_editor/process.cpp | 22 ++- src/text_editor/text_editor.cpp | 2 +- 11 files changed, 298 insertions(+), 21 deletions(-) diff --git a/build.sh b/build.sh index 2b4f477..d15a943 100644 --- a/build.sh +++ b/build.sh @@ -1,6 +1,84 @@ mkdir build -pushd build -clang -o build_tool.exe ../src/build_tool/build_tool_main.cpp -fdiagnostics-absolute-paths -g -nostdlib++ -fno-exceptions -popd +cd build -build/build_tool.exe \ No newline at end of file +if [ ! -f "lbaselib.o" ]; then + clang -g -I../src/external/lua/src -I../src/external/glad \ + ../src/external/lua/src/lbaselib.c \ + ../src/external/lua/src/lctype.c \ + ../src/external/lua/src/ldo.c \ + ../src/external/lua/src/lgc.c \ + ../src/external/lua/src/liolib.c \ + ../src/external/lua/src/lmem.c \ + ../src/external/lua/src/lopcodes.c \ + ../src/external/lua/src/lstate.c \ + ../src/external/lua/src/ltable.c \ + ../src/external/lua/src/lundump.c \ + ../src/external/lua/src/lzio.c \ + ../src/external/lua/src/lapi.c \ + ../src/external/lua/src/lcode.c \ + ../src/external/lua/src/ldblib.c \ + ../src/external/lua/src/ldump.c \ + ../src/external/lua/src/llex.c \ + ../src/external/lua/src/loadlib.c \ + ../src/external/lua/src/loslib.c \ + ../src/external/lua/src/lstring.c \ + ../src/external/lua/src/ltablib.c \ + ../src/external/lua/src/lutf8lib.c \ + ../src/external/lua/src/lauxlib.c \ + ../src/external/lua/src/lcorolib.c \ + ../src/external/lua/src/ldebug.c \ + ../src/external/lua/src/lfunc.c \ + ../src/external/lua/src/linit.c \ + ../src/external/lua/src/lmathlib.c \ + ../src/external/lua/src/lobject.c \ + ../src/external/lua/src/lparser.c \ + ../src/external/lua/src/lstrlib.c \ + ../src/external/lua/src/ltm.c \ + ../src/external/lua/src/lvm.c \ + ../src/external/glad/glad.c \ + -c +fi + +clang ../src/text_editor/text_editor.cpp ../src/basic/unix.cpp \ + -o te_linux.exe \ + -nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths -g \ + -Wno-writable-strings \ + -I../src/external/SDL/include \ + -I../src/external/lua/src \ + -I../src/external/glad \ + -I../src/ \ + -lm \ + ../src/external/SDL/build/libSDL3.a \ + lbaselib.o \ + lctype.o \ + ldo.o \ + lgc.o \ + liolib.o \ + lmem.o \ + lopcodes.o \ + lstate.o \ + ltable.o \ + lundump.o \ + lzio.o \ + lapi.o \ + lcode.o \ + ldblib.o \ + ldump.o \ + llex.o \ + loadlib.o \ + loslib.o \ + lstring.o \ + ltablib.o \ + lutf8lib.o \ + lauxlib.o \ + lcorolib.o \ + ldebug.o \ + lfunc.o \ + linit.o \ + lmathlib.o \ + lobject.o \ + lparser.o \ + lstrlib.o \ + ltm.o \ + lvm.o \ + glad.o \ diff --git a/build_file.cpp b/build_file.cpp index 9e7cc46..db5ea29 100644 --- a/build_file.cpp +++ b/build_file.cpp @@ -147,7 +147,7 @@ int CompileTextEditorLinux() { For2(lib, libs) For(lib.include_paths) cmd.add(Fmt("-I %.*s", S8_Expand(it))); For2(lib, libs) For(lib.defines) cmd.add(it); // cmd.add("-L../src/external/SDL/build/"); - cmd.add("-I../src/external/SDL/build/include"); + cmd.add("-I../src/external/SDL/include"); cmd.add("-lm"); cmd.add("../src/external/SDL/build/libSDL3.a"); For2(lib, libs) For(lib.link) cmd.add(it); @@ -294,7 +294,7 @@ void GenerateConfig() { style.add({"IndentSize", "4"}); style.add({"FontSize", "15"}); style.add({"FontFilter", "0"}); // nearest = 0, linear = 1 - seems like nearest always better? - style.add({"Font", "C:/Windows/Fonts/consola.ttf"}); + style.add({"Font", "/home/krz/text_editor/package/CascadiaMono.ttf"}); style.add({"VCVarsall", "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat"}); { @@ -400,4 +400,4 @@ int main() { SRC_SaveCache(); return 0; -} \ No newline at end of file +} diff --git a/src/basic/basic.h b/src/basic/basic.h index a98cc49..d84a452 100644 --- a/src/basic/basic.h +++ b/src/basic/basic.h @@ -795,6 +795,7 @@ String SkipToLastSlash(String s); String SkipToLastPeriod(String s); String Copy(Allocator allocator, String string); Int GetSize(Array array); +Array Split(Allocator allocator, String string, String delimiter); /* Hash table implementation: Pointers to values diff --git a/src/basic/filesystem.h b/src/basic/filesystem.h index c3021d8..6650213 100644 --- a/src/basic/filesystem.h +++ b/src/basic/filesystem.h @@ -46,7 +46,7 @@ struct Process { Process SpawnProcess(String command_line, String working_dir, String write_stdin = {}, Array enviroment = {}); bool IsValid(Process *process); void KillProcess(Process *process); -String PollStdout(Allocator allocator, Process *process); +String PollStdout(Allocator allocator, Process *process, bool force_read); void WriteStdin(Process *process, String string); void CloseStdin(Process *process); diff --git a/src/basic/unix.cpp b/src/basic/unix.cpp index 6e6f841..9320913 100644 --- a/src/basic/unix.cpp +++ b/src/basic/unix.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -11,6 +12,9 @@ #include #include #include +#include +#include + void (*Error)(const char *, ...); @@ -212,28 +216,204 @@ FileIter IterateFiles(Allocator alo, String path) { return it; } +// struct Process { +// bool is_valid; +// int exit_code; +// char platform[6 * 8]; +// +// int64_t view_id; // text editor view +// bool scroll_to_end; +// }; + struct UnixProcess { pid_t pid; + int child_stdout_read; + int stdin_write; }; +Array SplitCommand(Allocator allocator, String command_line) { + Array cmd = {allocator}; + + String curr = {}; + for (int i = 0; i < command_line.len; i += 1) { + if (command_line.data[i] == ' ') { + if (curr.len > 0) { + Add(&cmd, Copy(allocator, curr).data); + curr = {}; + } + continue; + } + if (curr.len == 0) { + curr.data = command_line.data + i; + } + curr.len += 1; + } + + if (curr.len > 0) { + Add(&cmd, Copy(allocator, curr).data); + } + + return cmd; +} + Process SpawnProcess(String command_line, String working_dir, String write_stdin, Array enviroment) { - return {}; + const int PIPE_READ = 0; + const int PIPE_WRITE = 1; + bool error = false; + + Scratch scratch; + Process process = {}; + UnixProcess *plat = (UnixProcess *)&process.platform; + Array args = SplitCommand(scratch, command_line); + Array env = {scratch}; + + For (enviroment) { + Add(&env, Copy(scratch, it).data); + } + + int stdout_desc[2] = {}; + int stdin_desc[2] = {}; + posix_spawn_file_actions_t actions = {}; + + if (posix_spawn_file_actions_init(&actions) != 0) { + perror("posix_spawn_file_actions_init"); + return process; + } + defer { + posix_spawn_file_actions_destroy(&actions); + }; + + if (pipe(stdout_desc) == -1) { + perror("pipe"); + return process; + } + defer { + if (error) { + close(stdout_desc[PIPE_READ]); + close(stdout_desc[PIPE_WRITE]); + } else { + close(stdout_desc[PIPE_WRITE]); + } + }; + + if (pipe(stdin_desc) == -1) { + perror("pipe"); + return process; + } + defer { + if (error) { + close(stdin_desc[PIPE_READ]); + close(stdin_desc[PIPE_WRITE]); + } else { + close(stdin_desc[PIPE_READ]); + } + }; + + error = posix_spawn_file_actions_addclose(&actions, stdout_desc[PIPE_READ]) != 0; + if (error) { + perror("posix_spawn_file_actions_addclose"); + return process; + } + + error = posix_spawn_file_actions_adddup2(&actions, stdout_desc[PIPE_WRITE], STDOUT_FILENO) != 0; + if (error) { + perror("posix_spawn_file_actions_adddup2 STDOUT_FILENO"); + return process; + } + + error = posix_spawn_file_actions_adddup2(&actions, stdout_desc[PIPE_WRITE], STDERR_FILENO) != 0; + if (error) { + perror("posix_spawn_file_actions_adddup2 STDERR_FILENO"); + return process; + } + + error = posix_spawn_file_actions_addclose(&actions, stdin_desc[PIPE_WRITE]) != 0; + if (error) { + perror("posix_spawn_file_actions_addclose"); + return process; + } + + error = posix_spawn_file_actions_adddup2(&actions, stdin_desc[PIPE_READ], STDIN_FILENO) != 0; + if (error) { + perror("posix_spawn_file_actions_adddup2 STDIN_FILENO"); + return process; + } + + pid_t process_pid = 0; + error = posix_spawnp(&process_pid, args[0], &actions, NULL, args.data, env.data) != 0; + if (error) { + perror("failed to create process\n"); + return process; + } + + + process.is_valid = true; + plat->child_stdout_read = stdout_desc[PIPE_READ]; + plat->stdin_write = stdin_desc[PIPE_WRITE]; + + if (write_stdin.len) { + WriteStdin(&process, write_stdin); + CloseStdin(&process); + } + + + + return process; } bool IsValid(Process *process) { - return false; + UnixProcess *plat = (UnixProcess *)&process->platform; + if (process->is_valid == false) { + return false; + } + + int status = 0; + pid_t result = waitpid(plat->pid, &status, WNOHANG); + if (result >= 0) { + if (WIFSIGNALED(status) || WIFEXITED(status)) { + process->exit_code = WEXITSTATUS(status); + return false; + } + } + + return true; } void KillProcess(Process *process) { - + Assert(process->is_valid); + UnixProcess *plat = (UnixProcess *)process->platform; + kill(plat->pid, SIGKILL); + process->exit_code = -1; } -String PollStdout(Allocator allocator, Process *process) { - return ""; +String PollStdout(Allocator allocator, Process *process, bool force_read) { + Assert(process->is_valid); + UnixProcess *plat = (UnixProcess *)process->platform; + + String result = {}; + result.data = AllocArray(allocator, char, 16 * 4096); + + pollfd p = {}; + p.fd = plat->child_stdout_read; + p.events = POLLIN; + int res = poll(&p, 1, 0); + if (res == 1 || force_read) { + result.len = read(plat->child_stdout_read, result.data, 4 * 4096); + } + return result; } void WriteStdin(Process *process, String string) { + if (string.len == 0) return; + Assert(process->is_valid); + + UnixProcess *plat = (UnixProcess *)process->platform; + ssize_t size = write(plat->stdin_write, string.data, string.len); + + Assert(size == string.len); } void CloseStdin(Process *process) { + UnixProcess *plat = (UnixProcess *)process->platform; + close(plat->stdin_write); } diff --git a/src/basic/win32.cpp b/src/basic/win32.cpp index 66ba448..3b9f9c7 100644 --- a/src/basic/win32.cpp +++ b/src/basic/win32.cpp @@ -458,7 +458,7 @@ void KillProcess(Process *process) { process->exit_code = -1; } -String PollStdout(Allocator allocator, Process *process) { +String PollStdout(Allocator allocator, Process *process, bool force_read) { Assert(process->is_valid); Win32Process *p = (Win32Process *)process->platform; diff --git a/src/text_editor/generated.cpp b/src/text_editor/generated.cpp index 4e9699f..0daed62 100644 --- a/src/text_editor/generated.cpp +++ b/src/text_editor/generated.cpp @@ -66,7 +66,7 @@ Style.DrawScrollbar = 1 Style.IndentSize = 4 Style.FontSize = 15 Style.FontFilter = 0 -Style.Font = "C:/Windows/Fonts/consola.ttf" +Style.Font = "/home/krz/text_editor/package/CascadiaMono.ttf" Style.VCVarsall = "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat" Style.TrimWhitespaceOnSave = true Style.ClangFormatOnSave = false diff --git a/src/text_editor/generated_variables.cpp b/src/text_editor/generated_variables.cpp index 158b598..4b93640 100644 --- a/src/text_editor/generated_variables.cpp +++ b/src/text_editor/generated_variables.cpp @@ -63,5 +63,5 @@ Int StyleDrawScrollbar = 1; Int StyleIndentSize = 4; Int StyleFontSize = 15; Int StyleFontFilter = 0; -String StyleFont = "C:/Windows/Fonts/consola.ttf"; +String StyleFont = "/home/krz/text_editor/package/CascadiaMono.ttf"; String StyleVCVarsall = "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat"; \ No newline at end of file diff --git a/src/text_editor/lua_api.cpp b/src/text_editor/lua_api.cpp index 64b23ab..21fd1e4 100644 --- a/src/text_editor/lua_api.cpp +++ b/src/text_editor/lua_api.cpp @@ -117,8 +117,8 @@ int Lua_KillWindow(lua_State *L) { static void HookLuaForceExit(lua_State *L, lua_Debug *debug) { SDL_PumpEvents(); int numkeys = 0; - const uint8_t *keys = SDL_GetKeyboardState(&numkeys); - if (keys[SDL_SCANCODE_F9] > 0) + const bool *keys = SDL_GetKeyboardState(&numkeys); + if (keys[SDL_SCANCODE_F9]) luaL_error(L, "lua execution got interrupted"); } diff --git a/src/text_editor/process.cpp b/src/text_editor/process.cpp index 88b275c..3bfb2a9 100644 --- a/src/text_editor/process.cpp +++ b/src/text_editor/process.cpp @@ -5,23 +5,41 @@ Array ActiveProcesses = {}; // and platform independent one Array Enviroment = {}; +struct UnixProcess { + pid_t pid; + int child_stdout_read; +}; + // WARNING: seems that this maybe can't work reliably? // in case of 'git grep a' it's possible that child process spawns it's own // child process and then it won't print anything because it won't have // the appropriate handles. This happens in this case when git grep calls // 'less' program which errors out and doesn't print anything // @todo: maybe I should ask someone smarter about this! + + +// @todo: rework to fit both linux and windows! void UpdateProcesses() { IterRemove(ActiveProcesses) { IterRemovePrepare(ActiveProcesses); Scratch scratch; - String poll = PollStdout(scratch, &it); View *view = GetView({it.view_id}); + String poll = PollStdout(scratch, &it, false); if (poll.len) { Command_Append(view, poll, it.scroll_to_end); } if (!IsValid(&it)) { + for (;;) { + String poll = PollStdout(scratch, &it, true); + if (poll.len) { + Command_Append(view, poll, it.scroll_to_end); + } else { + break; + } + } + + Command_Append(view, Format(scratch, "process exited with code: %d\n", it.exit_code), it.scroll_to_end); remove_item = true; } @@ -45,7 +63,7 @@ Buffer *ExecAndWait(Allocator allocator, String cmd, String working_dir, String Buffer *temp_buffer = CreateTempBuffer(allocator, 4096 * 4); for (Process process = SpawnProcess(cmd, working_dir, stdin_string, Enviroment); IsValid(&process);) { Scratch scratch(allocator); - String poll = PollStdout(scratch, &process); + String poll = PollStdout(scratch, &process, true); if (poll.len) RawAppend(temp_buffer, poll); } diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index bcdbf38..18c10f9 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -334,7 +334,7 @@ int main(int argc, char **argv) SDL_free(sdl_config_path.data); } - if (SDL_Init(SDL_INIT_VIDEO) == -1) { + if (!SDL_Init(SDL_INIT_VIDEO)) { ReportErrorf("Couldn't initialize SDL! %s", SDL_GetError()); return 1; }