Pull in Kuroko (as a submodule, but with build integration)

This commit is contained in:
K. Lange 2021-01-01 17:19:44 +09:00
parent adb33b9b88
commit db23c987a9
10 changed files with 321 additions and 3 deletions

View File

@ -8,6 +8,7 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
fetch-depth: 0 fetch-depth: 0
submodules: true
- name: Pull Builder Image - name: Pull Builder Image
run: docker pull toaruos/build-tools:1.8.x run: docker pull toaruos/build-tools:1.8.x
- name: Run Builder - name: Run Builder

3
.gitignore vendored
View File

@ -71,3 +71,6 @@
# SDL # SDL
/base/usr/include/SDL /base/usr/include/SDL
# Kuroko build files
/base/usr/share/kuroko

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "kuroko"]
path = kuroko
url = git@github.com:klange/kuroko

View File

@ -38,7 +38,7 @@ LC=base/lib/libc.so
## ##
# APPS = C sources from apps/ # APPS = C sources from apps/
# APPS_X = binaries # APPS_X = binaries
# APPS_Y = generated makefiles for binaries (except init) # APPS_Y = generated makefiles for binaries
# APPS_SH = shell scripts to copy to base/bin/ and mark executable # APPS_SH = shell scripts to copy to base/bin/ and mark executable
# APPS_SH_X = destinations for shell scripts # APPS_SH_X = destinations for shell scripts
APPS=$(patsubst apps/%.c,%,$(wildcard apps/*.c)) APPS=$(patsubst apps/%.c,%,$(wildcard apps/*.c))
@ -63,7 +63,7 @@ tags: $(SOURCE_FILES)
## ##
# Files that must be present in the ramdisk (apps, libraries) # Files that must be present in the ramdisk (apps, libraries)
RAMDISK_FILES= ${APPS_X} ${APPS_SH_X} ${LIBS_X} base/lib/ld.so base/lib/libm.so RAMDISK_FILES= ${APPS_X} ${APPS_SH_X} ${LIBS_X} base/lib/ld.so base/lib/libm.so ${KUROKO_FILES}
# Kernel / module flags # Kernel / module flags
@ -162,13 +162,15 @@ base/cdrom:
mkdir -p $@ mkdir -p $@
base/var: base/var:
mkdir -p $@ mkdir -p $@
base/usr/share/kuroko:
mkdir -p $@
fatbase/efi/boot: fatbase/efi/boot:
mkdir -p $@ mkdir -p $@
cdrom: cdrom:
mkdir -p $@ mkdir -p $@
.make: .make:
mkdir -p .make mkdir -p .make
dirs: base/dev base/tmp base/proc base/bin base/lib base/cdrom cdrom base/var fatbase/efi/boot .make dirs: base/dev base/tmp base/proc base/bin base/lib base/cdrom base/usr/share/kuroko cdrom base/var fatbase/efi/boot .make
# C Library # C Library
@ -192,6 +194,34 @@ base/lib/libc.so: ${LIBC_OBJS} | dirs crts
base/lib/libm.so: util/lm.c | dirs crts base/lib/libm.so: util/lm.c | dirs crts
$(CC) -nodefaultlibs -o $@ $(CFLAGS) -shared -fPIC $^ -lgcc $(CC) -nodefaultlibs -o $@ $(CFLAGS) -shared -fPIC $^ -lgcc
KUROKO_OBJS=$(patsubst %.c, %.o, $(filter-out kuroko/rline.c kuroko/kuroko.c, $(sort $(wildcard kuroko/*.c)))) kuroko/builtins.o
kuroko/builtins.c: kuroko/builtins.krk
echo "const char _builtins_src[] = {\n" > $@
hexdump -v -e '16/1 "0x%02x,"' -e '"\n"' $< | sed s'/0x ,//g' >> $@
echo "0x00 };" >> $@
kuroko/%.o: kuroko/%.c
$(CC) $(CFLAGS) -fPIC -c -o $@ $^
KUROKO_CMODS=$(patsubst kuroko/src/%.c,%,$(wildcard kuroko/src/*.c))
KUROKO_CMODS_X=$(foreach lib,$(KUROKO_CMODS),base/usr/share/kuroko/$(lib).so)
KUROKO_CMODS_Y=$(foreach lib,$(KUROKO_CMODS),.make/$(lib).kmak)
KUROKO_KRK_MODS=$(patsubst kuroko/modules/%.krk,base/usr/share/kuroko/%.krk,$(wildcard kuroko/modules/*.krk))
KUROKO_FILES=$(KUROKO_CMODS_X) $(KUROKO_KRK_MODS) base/lib/libkuroko.so
base/usr/share/kuroko/%.krk: kuroko/modules/%.krk
cp $< $@
.make/%.kmak: kuroko/src/%.c util/auto-dep.py | dirs
util/auto-dep.py --makekurokomod $< > $@
ifeq (,$(findstring clean,$(MAKECMDGOALS)))
-include ${KUROKO_CMODS_Y}
endif
base/lib/libkuroko.so: $(KUROKO_OBJS) | dirs crts ${LC}
$(CC) $(CFLAGS) -shared -fPIC -o $@ $^ -lgcc
# Userspace Linker/Loader # Userspace Linker/Loader
base/lib/ld.so: linker/linker.c base/lib/libc.a | dirs base/lib/ld.so: linker/linker.c base/lib/libc.a | dirs
@ -305,6 +335,7 @@ clean:
rm -f base/lib/crt*.o rm -f base/lib/crt*.o
rm -f ${MODULES} rm -f ${MODULES}
rm -f ${APPS_Y} ${LIBS_Y} ${EXT_LIBS_Y} rm -f ${APPS_Y} ${LIBS_Y} ${EXT_LIBS_Y}
rm -f ${KUROKO_FILES}
ifneq (,$(findstring Microsoft,$(shell uname -r))) ifneq (,$(findstring Microsoft,$(shell uname -r)))
QEMU_ARGS=-serial mon:stdio -m 1G -rtc base=localtime -vnc :0 QEMU_ARGS=-serial mon:stdio -m 1G -rtc base=localtime -vnc :0

159
apps/kuroko.c Normal file
View File

@ -0,0 +1,159 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <toaru/rline.h>
#include <toaru/rline_exp.h>
#include <kuroko.h>
#include "chunk.h"
#include "debug.h"
#include "vm.h"
#include "memory.h"
int main(int argc, char * argv[]) {
int flags = 0;
int opt;
while ((opt = getopt(argc, argv, "tdgs")) != -1) {
switch (opt) {
case 't':
flags |= KRK_ENABLE_TRACING;
break;
case 'd':
flags |= KRK_ENABLE_DEBUGGING;
break;
case 's':
flags |= KRK_ENABLE_SCAN_TRACING;
break;
case 'g':
flags |= KRK_ENABLE_STRESS_GC;
break;
}
}
krk_initVM(flags);
KrkValue result = INTEGER_VAL(0);
if (optind == argc) {
/* Run the repl */
int exit = 0;
rline_exit_string="";
rline_exp_set_syntax("krk");
//rline_exp_set_shell_commands(shell_commands, shell_commands_len);
//rline_exp_set_tab_complete_func(tab_complete_func);
while (!exit) {
size_t lineCapacity = 8;
size_t lineCount = 0;
char ** lines = ALLOCATE(char *, lineCapacity);
size_t totalData = 0;
int valid = 1;
char * allData = NULL;
int inBlock = 0;
int blockWidth = 0;
rline_exp_set_prompts(">>> ", "", 4, 0);
while (1) {
/* This would be a nice place for line editing */
char buf[4096] = {0};
if (inBlock) {
rline_exp_set_prompts(" > ", "", 4, 0);
rline_preload = malloc(blockWidth + 1);
for (int i = 0; i < blockWidth; ++i) {
rline_preload[i] = ' ';
}
rline_preload[blockWidth] = '\0';
}
rline_scroll = 0;
if (rline_experimental(buf, 4096) == 0) {
valid = 0;
exit = 1;
break;
}
if (buf[strlen(buf)-1] != '\n') {
fprintf(stderr, "Expected end of line in repl input. Did you ^D early?\n");
valid = 0;
break;
}
if (lineCapacity < lineCount + 1) {
size_t old = lineCapacity;
lineCapacity = GROW_CAPACITY(old);
lines = GROW_ARRAY(char *,lines,old,lineCapacity);
}
int i = lineCount++;
lines[i] = strdup(buf);
size_t lineLength = strlen(lines[i]);
totalData += lineLength;
int is_spaces = 1;
int count_spaces = 0;
for (size_t j = 0; j < lineLength; ++j) {
if (lines[i][j] != ' ' && lines[i][j] != '\n') {
is_spaces = 0;
break;
}
count_spaces += 1;
}
if (lineLength > 2 && lines[i][lineLength-2] == ':') {
inBlock = 1;
blockWidth = count_spaces + 4;
continue;
} else if (inBlock && lineLength != 1) {
if (is_spaces) {
free(lines[i]);
totalData -= lineLength;
lineCount--;
break;
}
blockWidth = count_spaces;
continue;
}
break;
}
if (valid) {
allData = malloc(totalData + 1);
allData[0] = '\0';
}
for (size_t i = 0; i < lineCount; ++i) {
if (valid) strcat(allData, lines[i]);
rline_history_insert(strdup(lines[i]));
free(lines[i]);
}
FREE_ARRAY(char *, lines, lineCapacity);
if (valid) {
KrkValue result = krk_interpret(allData, 0, "<module>","<stdin>");
if (!IS_NONE(result)) {
fprintf(stdout, " \033[1;30m=> ");
krk_printValue(stdout, result);
fprintf(stdout, "\033[0m\n");
}
}
}
} else {
for (int i = optind; i < argc; ++i) {
KrkValue out = krk_runfile(argv[i],0,"<module>",argv[i]);
if (i + 1 == argc) result = out;
}
}
krk_freeVM();
if (IS_INTEGER(result)) return AS_INTEGER(result);
return 0;
}

View File

@ -10,5 +10,6 @@ extern int rline_exp_set_prompts(char * left, char * right, int left_width, int
extern int rline_exp_set_shell_commands(char ** cmds, int len); extern int rline_exp_set_shell_commands(char ** cmds, int len);
extern int rline_exp_set_tab_complete_func(rline_callback_t func); extern int rline_exp_set_tab_complete_func(rline_callback_t func);
extern int rline_exp_set_syntax(char * name); extern int rline_exp_set_syntax(char * name);
extern char * rline_preload;
_End_C_Header _End_C_Header

1
kuroko Submodule

@ -0,0 +1 @@
Subproject commit a9fffce795bef002469b6c1cb17aef7962a785bd

View File

@ -726,6 +726,95 @@ int syn_py_calculate(struct syntax_state * state) {
return -1; return -1;
} }
void paint_single_string(struct syntax_state * state) {
/* Assumes you came in from a check of charat() == '\'' */
paint(1, FLAG_NUMERAL);
while (charat() != -1) {
if (charat() == '\\' && nextchar() == '\'') {
paint(2, FLAG_ESCAPE);
} else if (charat() == '\'') {
paint(1, FLAG_NUMERAL);
return;
} else if (charat() == '\\') {
paint(2, FLAG_ESCAPE);
} else {
paint(1, FLAG_NUMERAL);
}
}
}
char * syn_krk_keywords[] = {
"and","class","def","else","export","for","if","in","import",
"let","not","or","print","return","while","try","except","raise",
"continue","break",
NULL
};
char * syn_krk_types[] = {
/* built-in functions */
"self", "super", /* implicit in a class method */
"len", "str", "int", "float", "dir", "repr", /* global functions from __builtins__ */
"list","dict","range", /* builtin classes */
"object","exception","isinstance","type",
NULL
};
char * syn_krk_special[] = {
"True","False","None",
NULL
};
int paint_krk_numeral(struct syntax_state * state) {
if (charat() == '0' && (nextchar() == 'x' || nextchar() == 'X')) {
paint(2, FLAG_NUMERAL);
while (isxdigit(charat())) paint(1, FLAG_NUMERAL);
} else if (charat() == '0' && (nextchar() == 'o' || nextchar() == 'O')) {
paint(2, FLAG_NUMERAL);
while (charat() >= '0' && charat() <= '7') paint(1, FLAG_NUMERAL);
} else if (charat() == '0' && (nextchar() == 'b' || nextchar() == 'B')) {
paint(2, FLAG_NUMERAL);
while (charat() == '0' || charat() == '1') paint(1, FLAG_NUMERAL);
} else {
while (isdigit(charat())) paint(1, FLAG_NUMERAL);
if (charat() == '.') {
paint(1, FLAG_NUMERAL);
while (isdigit(charat())) paint(1, FLAG_NUMERAL);
}
}
return 0;
}
int syn_krk_calculate(struct syntax_state * state) {
switch (state->state) {
case -1:
case 0:
if (charat() == '#') {
paint_comment(state);
} else if (charat() == '"') {
paint_simple_string(state);
return 0;
} else if (charat() == '\'') {
paint_single_string(state);
return 0;
} else if (find_keywords(state, syn_krk_keywords, FLAG_KEYWORD, c_keyword_qualifier)) {
return 0;
} else if (lastchar() != '.' && find_keywords(state, syn_krk_types, FLAG_TYPE, c_keyword_qualifier)) {
return 0;
} else if (find_keywords(state, syn_krk_special, FLAG_NUMERAL, c_keyword_qualifier)) {
return 0;
} else if (!c_keyword_qualifier(lastchar()) && isdigit(charat())) {
paint_krk_numeral(state);
return 0;
} else if (charat() != -1) {
skip();
return 0;
}
break;
}
return -1;
}
/** /**
* Convert syntax hilighting flag to color code * Convert syntax hilighting flag to color code
*/ */
@ -767,6 +856,7 @@ struct syntax_definition {
} syntaxes[] = { } syntaxes[] = {
{"esh",syn_esh_calculate}, {"esh",syn_esh_calculate},
{"python",syn_py_calculate}, {"python",syn_py_calculate},
{"krk",syn_krk_calculate},
{NULL, NULL}, {NULL, NULL},
}; };
@ -1579,6 +1669,8 @@ static void call_rline_func(rline_callback_t func, rline_context_t * context) {
place_cursor_actual(); place_cursor_actual();
} }
char * rline_preload = NULL;
/** /**
* Perform actual interactive line editing. * Perform actual interactive line editing.
* *
@ -1600,6 +1692,17 @@ static int read_line(void) {
for (int i = 0; i < full_width - 1; ++i) { for (int i = 0; i < full_width - 1; ++i) {
fprintf(stdout, " "); fprintf(stdout, " ");
} }
if (rline_preload) {
char * c = rline_preload;
while (*c) {
insert_char(*c);
c++;
}
free(rline_preload);
rline_preload = NULL;
}
render_line(); render_line();
place_cursor_actual(); place_cursor_actual();

View File

@ -217,6 +217,7 @@ int xvasprintf(char * buf, const char * fmt, va_list args) {
case 'p': case 'p':
if (!arg_width) { if (!arg_width) {
arg_width = 8; arg_width = 8;
alt = 1;
} }
case 'x': /* Hexadecimal number */ case 'x': /* Hexadecimal number */
if (alt) { if (alt) {

View File

@ -36,6 +36,8 @@ class Classifier(object):
'<toaru/menu.h>': (None, '-ltoaru_menu', ['<toaru/sdf.h>', '<toaru/yutani.h>', '<toaru/icon_cache.h>', '<toaru/graphics.h>', '<toaru/hashmap.h>']), '<toaru/menu.h>': (None, '-ltoaru_menu', ['<toaru/sdf.h>', '<toaru/yutani.h>', '<toaru/icon_cache.h>', '<toaru/graphics.h>', '<toaru/hashmap.h>']),
'<toaru/textregion.h>': (None, '-ltoaru_textregion', ['<toaru/sdf.h>', '<toaru/yutani.h>','<toaru/graphics.h>', '<toaru/hashmap.h>']), '<toaru/textregion.h>': (None, '-ltoaru_textregion', ['<toaru/sdf.h>', '<toaru/yutani.h>','<toaru/graphics.h>', '<toaru/hashmap.h>']),
'<toaru/button.h>': (None, '-ltoaru_button', ['<toaru/graphics.h>','<toaru/sdf.h>', '<toaru/icon_cache.h>']), '<toaru/button.h>': (None, '-ltoaru_button', ['<toaru/graphics.h>','<toaru/sdf.h>', '<toaru/icon_cache.h>']),
# Kuroko
'<kuroko.h>': ('../../../kuroko', '-lkuroko', []),
# OPTIONAL third-party libraries, for extensions / ports # OPTIONAL third-party libraries, for extensions / ports
'<ft2build.h>': ('freetype2', '-lfreetype', []), '<ft2build.h>': ('freetype2', '-lfreetype', []),
'<pixman.h>': ('pixman-1', '-lpixman-1', []), '<pixman.h>': ('pixman-1', '-lpixman-1', []),
@ -101,6 +103,8 @@ def todep(name):
name = name.replace("-l","",1) name = name.replace("-l","",1)
if name.startswith('toaru'): if name.startswith('toaru'):
return (True, "%s/lib%s.so" % ('base/lib', name)) return (True, "%s/lib%s.so" % ('base/lib', name))
elif name.startswith('kuroko'):
return (True, "%s/lib%s.so" % ('base/lib', name))
else: else:
return (True, "%s/lib%s.so" % ('base/usr/lib', name)) return (True, "%s/lib%s.so" % ('base/usr/lib', name))
else: else:
@ -173,4 +177,15 @@ if __name__ == "__main__":
libraries=" ".join([x for x in _libs]), libraries=" ".join([x for x in _libs]),
includes=" ".join([x for x in c.includes if x is not None]) includes=" ".join([x for x in c.includes if x is not None])
)) ))
elif command == "--makekurokomod":
libname = os.path.basename(filename).replace(".c","")
_libs = [x for x in c.libs if not x.startswith('-ltoaru_') or x.replace("-ltoaru_","") != libname]
print("base/usr/share/kuroko/{lib}.so: {source} {headers} util/auto-dep.py | {libraryfiles} $(LC)\n\t$(CC) $(CFLAGS) {includes} -shared -fPIC -o $@ $< {libraries}".format(
lib=libname,
source=filename,
headers=" ".join([toheader(x) for x in c.libs]),
libraryfiles=" ".join([todep(x)[1] for x in _libs]),
libraries=" ".join([x for x in _libs]),
includes=" ".join([x for x in c.includes if x is not None])
))