Experimental Windows support
This commit is contained in:
parent
f4444cccaa
commit
a9b04cceb2
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,5 +1,7 @@
|
||||
*.o
|
||||
*.so
|
||||
kuroko
|
||||
*.exe
|
||||
*.dll
|
||||
wasm/
|
||||
jupyter/
|
||||
|
18
Makefile
18
Makefile
@ -5,9 +5,13 @@ OBJS = $(patsubst %.c, %.o, $(filter-out rline.c,$(filter-out kuroko.c,$(sor
|
||||
MODULES = $(patsubst src/%.c, modules/%.so, $(sort $(wildcard src/*.c)))
|
||||
|
||||
ifndef KRK_ENABLE_STATIC
|
||||
CFLAGS += -fPIC
|
||||
LDFLAGS += -L. -Wl,-rpath -Wl,'$$ORIGIN' -Wl,-z,origin
|
||||
LDLIBS += -lkuroko -ldl
|
||||
CFLAGS += -fPIC -L.
|
||||
ifeq (,$(findstring mingw,$(CC)))
|
||||
LDFLAGS += -Wl,-rpath -Wl,'$$ORIGIN' -Wl,-z,origin
|
||||
LDLIBS += -ldl -lkuroko
|
||||
else
|
||||
LDLIBS += libkuroko.so
|
||||
endif
|
||||
all: ${TARGET} ${MODULES}
|
||||
KUROKO_LIBS = libkuroko.so
|
||||
else
|
||||
@ -48,13 +52,13 @@ kuroko: ${KUROKO_LIBS}
|
||||
%.o: *.h
|
||||
|
||||
modules/%.so: src/%.c
|
||||
${CC} ${CFLAGS} -shared -o $@ $<
|
||||
${CC} ${CFLAGS} -shared -o $@ $< ${LDLIBS}
|
||||
|
||||
modules/math.so: src/math.c
|
||||
${CC} ${CFLAGS} -shared -o $@ $< -lm
|
||||
${CC} ${CFLAGS} -shared -o $@ $< -lm ${LDLIBS}
|
||||
|
||||
libkuroko.so: ${OBJS}
|
||||
${CC} ${CLFAGS} -shared -o $@ ${OBJS}
|
||||
${CC} ${CFLAGS} -shared -o $@ ${OBJS}
|
||||
|
||||
builtins.c: builtins.krk
|
||||
echo "const char krk_builtinsSrc[] = " > builtins.c
|
||||
@ -63,7 +67,7 @@ builtins.c: builtins.krk
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@rm -f ${OBJS} ${TARGET} ${MODULES} libkuroko.so rline.o kuroko.o src/*.o
|
||||
@rm -f ${OBJS} ${TARGET} ${MODULES} libkuroko.so rline.o kuroko.o src/*.o kuroko.exe
|
||||
|
||||
tags: $(wildcard *.c) $(wildcard *.h)
|
||||
@ctags --c-kinds=+lx *.c *.h
|
||||
|
@ -60,6 +60,14 @@ Additional options include `KRK_DISABLE_RLINE=1` to not link with the included r
|
||||
|
||||
See [klange/kuroko-wasm-repl](https://github.com/klange/kuroko-wasm-repl) for information on building Kuroko with Emscripten for use in a web browser.
|
||||
|
||||
### Building for Windows
|
||||
|
||||
Experimental support is available for building Kuroko to run on Windows using MingW:
|
||||
|
||||
CC=x86_64-w64-mingw32-gcc make
|
||||
|
||||
A capable terminal, such as Windows Terminal, is required to run the interpreter's REPL correctly. The older "Command Prompt" (cmd.exe) is specifically known to _not_ work.
|
||||
|
||||
## Code Examples
|
||||
|
||||
_**NOTE**: Due to limitations with Github's markdown renderer, these snippets will be highlighted as Python code._
|
||||
|
84
rline.c
84
rline.c
@ -13,14 +13,19 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <termios.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <unistd.h>
|
||||
#include <locale.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#ifndef _WIN32
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
/* How do we get this in Windows? Seems WT asks the font? */
|
||||
#define wcwidth(c) (1)
|
||||
#endif
|
||||
#ifdef __toaru__
|
||||
#include <toaru/rline.h>
|
||||
#else
|
||||
@ -223,35 +228,15 @@ int rline_exp_set_tab_complete_func(rline_callback_t func) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int _unget = -1;
|
||||
static void _ungetc(int c) {
|
||||
_unget = c;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int getch(int immediate, int timeout) {
|
||||
#ifndef _WIN32
|
||||
return fgetc(stdin);
|
||||
#if 0
|
||||
if (_unget != -1) {
|
||||
int out = _unget;
|
||||
_unget = -1;
|
||||
return out;
|
||||
}
|
||||
if (immediate) return fgetc(stdin);
|
||||
struct pollfd fds[1];
|
||||
fds[0].fd = STDIN_FILENO;
|
||||
fds[0].events = POLLIN;
|
||||
int ret = poll(fds,1,50);
|
||||
if (ret > 0 && fds[0].revents & POLLIN) {
|
||||
unsigned char buf[1];
|
||||
int unused = read(STDIN_FILENO, buf, 1);
|
||||
(void)unused;
|
||||
return buf[0];
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
TCHAR buf[1];
|
||||
DWORD dwRead;
|
||||
while (!ReadConsole(GetStdHandle(STD_INPUT_HANDLE),buf,1,&dwRead,NULL));
|
||||
return buf[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -298,7 +283,7 @@ static int to_eight(uint32_t codepoint, char * out) {
|
||||
* This is copied from bim. Supports a few useful
|
||||
* things like rendering escapes as codepoints.
|
||||
*/
|
||||
static int codepoint_width(wchar_t codepoint) {
|
||||
static int codepoint_width(int codepoint) {
|
||||
if (codepoint == '\t') {
|
||||
return 1; /* Recalculate later */
|
||||
}
|
||||
@ -1365,15 +1350,18 @@ static void render_line(void) {
|
||||
|
||||
set_colors(COLOR_FG, COLOR_BG);
|
||||
|
||||
/* Fill to end right hand side */
|
||||
for (; j < width + offset - prompt_width_calc; ++j) {
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
/* Print right hand side */
|
||||
if (show_right_side) {
|
||||
/* Fill to end right hand side */
|
||||
for (; j < width + offset - prompt_width_calc; ++j) {
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
/* Print right hand side */
|
||||
printf("\033[0m%s", prompt_right);
|
||||
} else {
|
||||
printf("\033[0K");
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1424,9 +1412,15 @@ static line_t * line_insert(line_t * line, char_t c, int offset) {
|
||||
* We don't listen for sigwinch for various reasons...
|
||||
*/
|
||||
static void get_size(void) {
|
||||
#ifndef _WIN32
|
||||
struct winsize w;
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
rline_terminal_width = w.ws_col;
|
||||
#else
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
|
||||
rline_terminal_width = csbi.srWindow.Right - csbi.srWindow.Left + 1;
|
||||
#endif
|
||||
if (rline_terminal_width - prompt_right_width - prompt_width > MINIMUM_SIZE) {
|
||||
show_right_side = 1;
|
||||
show_left_side = 1;
|
||||
@ -1778,6 +1772,7 @@ static int handle_escape(int * this_buf, int * timeout, int c) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static unsigned int _INTR, _EOF;
|
||||
static struct termios old;
|
||||
static void get_initial_termios(void) {
|
||||
@ -1785,7 +1780,6 @@ static void get_initial_termios(void) {
|
||||
_INTR = old.c_cc[VINTR];
|
||||
_EOF = old.c_cc[VEOF];
|
||||
}
|
||||
|
||||
static void set_unbuffered(void) {
|
||||
struct termios new = old;
|
||||
new.c_lflag &= (~ICANON & ~ECHO & ~ISIG);
|
||||
@ -1795,6 +1789,18 @@ static void set_unbuffered(void) {
|
||||
static void set_buffered(void) {
|
||||
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &old);
|
||||
}
|
||||
#else
|
||||
static unsigned int _INTR = 3;
|
||||
static unsigned int _EOF = 4;
|
||||
static void get_initial_termios(void) {
|
||||
}
|
||||
static void set_unbuffered(void) {
|
||||
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_VIRTUAL_TERMINAL_INPUT);
|
||||
}
|
||||
static void set_buffered(void) {
|
||||
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int tabbed;
|
||||
|
||||
@ -1910,11 +1916,14 @@ static int read_line(void) {
|
||||
uint32_t istate = 0;
|
||||
int immediate = 1;
|
||||
|
||||
#ifndef _WIN32
|
||||
/* Let's disable this under Windows... */
|
||||
set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
|
||||
fprintf(stdout, "◄\033[0m"); /* TODO: This could be retrieved from an envvar */
|
||||
for (int i = 0; i < rline_terminal_width - 1; ++i) {
|
||||
fprintf(stdout, " ");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rline_preload) {
|
||||
char * c = rline_preload;
|
||||
@ -1980,6 +1989,7 @@ static int read_line(void) {
|
||||
delete_at_cursor();
|
||||
immediate = 0;
|
||||
break;
|
||||
case 13:
|
||||
case ENTER_KEY:
|
||||
/* Finished */
|
||||
loading = 1;
|
||||
|
55
src/os.c
55
src/os.c
@ -6,7 +6,11 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#ifndef _WIN32
|
||||
#include <sys/utsname.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "../vm.h"
|
||||
#include "../value.h"
|
||||
@ -21,6 +25,7 @@ extern char ** environ;
|
||||
* system.uname()
|
||||
*/
|
||||
static KrkValue krk_uname(int argc, KrkValue argv[]) {
|
||||
#ifndef _WIN32
|
||||
struct utsname buf;
|
||||
if (uname(&buf) < 0) return NONE_VAL();
|
||||
|
||||
@ -35,8 +40,56 @@ static KrkValue krk_uname(int argc, KrkValue argv[]) {
|
||||
});
|
||||
|
||||
KRK_RESUME_GC();
|
||||
|
||||
return result;
|
||||
#else
|
||||
KRK_PAUSE_GC();
|
||||
|
||||
TCHAR buffer[256] = TEXT("");
|
||||
DWORD dwSize = sizeof(buffer);
|
||||
GetComputerName(buffer, &dwSize);
|
||||
|
||||
OSVERSIONINFOA versionInfo = {0};
|
||||
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionExA(&versionInfo);
|
||||
KrkValue release;
|
||||
if (versionInfo.dwMajorVersion == 10) {
|
||||
release = OBJECT_VAL(S("10"));
|
||||
} else if (versionInfo.dwMajorVersion == 6) {
|
||||
if (versionInfo.dwMinorVersion == 3) {
|
||||
release = OBJECT_VAL(S("8.1"));
|
||||
} else if (versionInfo.dwMinorVersion == 2) {
|
||||
release = OBJECT_VAL(S("8.0"));
|
||||
} else if (versionInfo.dwMinorVersion == 1) {
|
||||
release = OBJECT_VAL(S("7"));
|
||||
} else if (versionInfo.dwMinorVersion == 0) {
|
||||
release = OBJECT_VAL(S("Vista"));
|
||||
}
|
||||
} else {
|
||||
release = OBJECT_VAL(S("XP or earlier"));
|
||||
}
|
||||
|
||||
char tmp[256];
|
||||
sprintf(tmp, "%ld", versionInfo.dwBuildNumber);
|
||||
|
||||
KrkValue version = OBJECT_VAL(krk_copyString(tmp,strlen(tmp)));
|
||||
KrkValue machine;
|
||||
if (sizeof(void *) == 8) {
|
||||
machine = OBJECT_VAL(S("x64"));
|
||||
} else {
|
||||
machine = OBJECT_VAL(S("x86"));
|
||||
}
|
||||
|
||||
KrkValue result = krk_dict_of(5 * 2, (KrkValue[]) {
|
||||
OBJECT_VAL(S("sysname")), OBJECT_VAL(S("Windows")),
|
||||
OBJECT_VAL(S("nodename")), OBJECT_VAL(krk_copyString(buffer,dwSize)),
|
||||
OBJECT_VAL(S("release")), release,
|
||||
OBJECT_VAL(S("version")), version,
|
||||
OBJECT_VAL(S("machine")), machine
|
||||
});
|
||||
|
||||
KRK_RESUME_GC();
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
KrkValue krk_os_setenviron(int argc, KrkValue * argv[]) {
|
||||
|
31
vm.c
31
vm.c
@ -5,10 +5,6 @@
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef STATIC_ONLY
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include "vm.h"
|
||||
#include "debug.h"
|
||||
#include "memory.h"
|
||||
@ -38,6 +34,24 @@
|
||||
# define KRK_BUILD_COMPILER ""
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
# ifndef STATIC_ONLY
|
||||
# include <dlfcn.h>
|
||||
# endif
|
||||
# define PATH_SEP "/"
|
||||
# define dlRefType void *
|
||||
# define dlSymType void *
|
||||
# define dlOpen(fileName) dlopen(fileName, RTLD_NOW)
|
||||
# define dlSym(dlRef, handlerName) dlsym(dlRef,handlerName)
|
||||
#else
|
||||
# include <windows.h>
|
||||
# define PATH_SEP "\\"
|
||||
# define dlRefType HINSTANCE
|
||||
# define dlSymType FARPROC
|
||||
# define dlOpen(fileName) LoadLibraryA(fileName)
|
||||
# define dlSym(dlRef, handlerName) GetProcAddress(dlRef, handlerName)
|
||||
#endif
|
||||
|
||||
#define S(c) (krk_copyString(c,sizeof(c)-1))
|
||||
|
||||
#define likely(cond) __builtin_expect(!!(cond), 1)
|
||||
@ -3247,6 +3261,7 @@ void krk_initVM(int flags) {
|
||||
krk_attachNamedObject(&vm.system->fields, "builddate", (KrkObj*)S(KRK_BUILD_DATE));
|
||||
krk_defineNative(&vm.system->fields, "getsizeof", krk_getsize);
|
||||
krk_defineNative(&vm.system->fields, "set_clean_output", krk_setclean);
|
||||
krk_attachNamedObject(&vm.system->fields, "path_sep", (KrkObj*)S(PATH_SEP));
|
||||
|
||||
KrkInstance * gcModule = krk_newInstance(vm.moduleClass);
|
||||
krk_attachNamedObject(&vm.modules, "gc", (KrkObj*)gcModule);
|
||||
@ -3698,7 +3713,7 @@ int krk_loadModule(KrkString * path, KrkValue * moduleOut, KrkString * runAs) {
|
||||
krk_push(AS_LIST(modulePathsInternal)->values[i]);
|
||||
krk_push(OBJECT_VAL(path));
|
||||
addObjects();
|
||||
krk_push(OBJECT_VAL(S("/__init__.krk")));
|
||||
krk_push(OBJECT_VAL(S(PATH_SEP "__init__.krk")));
|
||||
addObjects();
|
||||
fileName = AS_CSTRING(krk_peek(0));
|
||||
if (stat(fileName,&statbuf) < 0) {
|
||||
@ -3744,7 +3759,7 @@ int krk_loadModule(KrkString * path, KrkValue * moduleOut, KrkString * runAs) {
|
||||
char * fileName = AS_CSTRING(krk_peek(0));
|
||||
if (stat(fileName,&statbuf) < 0) continue;
|
||||
|
||||
void * dlRef = dlopen(fileName, RTLD_NOW);
|
||||
dlRefType dlRef = dlOpen(fileName);
|
||||
if (!dlRef) {
|
||||
*moduleOut = NONE_VAL();
|
||||
krk_runtimeError(vm.exceptions.importError,
|
||||
@ -3764,7 +3779,7 @@ int krk_loadModule(KrkString * path, KrkValue * moduleOut, KrkString * runAs) {
|
||||
char * handlerName = AS_CSTRING(krk_peek(0));
|
||||
|
||||
KrkValue (*moduleOnLoad)(KrkString * name);
|
||||
void * out = dlsym(dlRef, handlerName);
|
||||
dlSymType out = dlSym(dlRef, handlerName);
|
||||
memcpy(&moduleOnLoad,&out,sizeof(out));
|
||||
|
||||
if (!moduleOnLoad) {
|
||||
@ -3887,7 +3902,7 @@ int krk_doRecursiveModuleLoad(KrkString * name) {
|
||||
vm.stack[argBase-1] = krk_pop();
|
||||
/* Now concatenate forward slash... */
|
||||
krk_push(vm.stack[argBase+1]); /* Slash path */
|
||||
krk_push(OBJECT_VAL(S("/")));
|
||||
krk_push(OBJECT_VAL(S(PATH_SEP)));
|
||||
addObjects();
|
||||
vm.stack[argBase+1] = krk_pop();
|
||||
/* And now for the dot... */
|
||||
|
Loading…
Reference in New Issue
Block a user