diff options
| -rw-r--r-- | Makefile | 90 | ||||
| -rw-r--r-- | build_win.bat | 53 | ||||
| -rw-r--r-- | meson.build | 49 | ||||
| -rw-r--r-- | src/boot/boot.c | 39 | ||||
| -rw-r--r-- | src/boot/boot.janet | 99 | ||||
| -rw-r--r-- | src/core/array.c | 12 | ||||
| -rw-r--r-- | src/core/buffer.c | 13 | ||||
| -rw-r--r-- | src/core/compile.c | 4 | ||||
| -rw-r--r-- | src/core/corelib.c | 2 | ||||
| -rw-r--r-- | src/core/debug.c | 2 | ||||
| -rw-r--r-- | src/core/fiber.c | 6 | ||||
| -rw-r--r-- | src/core/gc.c | 67 | ||||
| -rw-r--r-- | src/core/marsh.c | 8 | ||||
| -rw-r--r-- | src/core/parse.c | 11 | ||||
| -rw-r--r-- | src/core/peg.c | 10 | ||||
| -rw-r--r-- | src/core/state.h | 4 | ||||
| -rw-r--r-- | src/core/string.c | 18 | ||||
| -rw-r--r-- | src/core/strtod.c | 12 | ||||
| -rw-r--r-- | src/core/symcache.c | 2 | ||||
| -rw-r--r-- | src/core/tuple.c | 2 | ||||
| -rw-r--r-- | src/core/util.c | 10 | ||||
| -rw-r--r-- | src/core/util.h | 1 | ||||
| -rw-r--r-- | src/core/vector.c | 2 | ||||
| -rw-r--r-- | src/include/janet.h | 5 | ||||
| -rw-r--r-- | src/mainclient/line.h | 40 | ||||
| -rw-r--r-- | src/mainclient/main.c | 90 | ||||
| -rw-r--r-- | src/mainclient/shell.c (renamed from src/mainclient/line.c) | 78 | ||||
| -rw-r--r-- | tools/xxd.c | 104 |
28 files changed, 345 insertions, 488 deletions
@@ -39,7 +39,7 @@ DEBUGGER=gdb CFLAGS:=$(CFLAGS) -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fPIC -O2 -fvisibility=hidden \ -DJANET_BUILD=$(JANET_BUILD) -LDFLAGS=-rdynamic +LDFLAGS:=$(LDFLAGS) -rdynamic # For installation LDCONFIG:=ldconfig "$(LIBDIR)" @@ -124,17 +124,11 @@ JANET_BOOT_SOURCES=src/boot/array_test.c \ src/boot/table_test.c JANET_BOOT_HEADERS=src/boot/tests.h -JANET_MAINCLIENT_SOURCES=src/mainclient/line.c src/mainclient/main.c -JANET_MAINCLIENT_HEADERS=src/mainclient/line.h - -JANET_WEBCLIENT_SOURCES=src/webclient/main.c - -################################################################## -##### The bootstrap interpreter that compiles the core image ##### -################################################################## +########################################################## +##### The bootstrap interpreter that creates janet.c ##### +########################################################## -JANET_BOOT_OBJECTS=$(patsubst src/%.c,build/%.boot.o,$(JANET_CORE_SOURCES) $(JANET_BOOT_SOURCES)) \ - build/boot.gen.o +JANET_BOOT_OBJECTS=$(patsubst src/%.c,build/%.boot.o,$(JANET_CORE_SOURCES) $(JANET_BOOT_SOURCES)) $(JANET_BOOT_OBJECTS): $(JANET_BOOT_HEADERS) @@ -142,65 +136,18 @@ build/%.boot.o: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS) $(CC) $(CFLAGS) -DJANET_BOOTSTRAP -o $@ -c $< build/janet_boot: $(JANET_BOOT_OBJECTS) - $(CC) $(CFLAGS) -DJANET_BOOTSTRAP -o $@ $^ $(CLIBS) + $(CC) $(CFLAGS) -DJANET_BOOTSTRAP -o $@ $(JANET_BOOT_OBJECTS) $(CLIBS) # Now the reason we bootstrap in the first place -build/core_image.c: build/janet_boot - build/janet_boot $@ JANET_PATH '$(JANET_PATH)' JANET_HEADERPATH '$(INCLUDEDIR)/janet' - -########################################################## -##### The main interpreter program and shared object ##### -########################################################## - -JANET_CORE_OBJECTS=$(patsubst src/%.c,build/%.o,$(JANET_CORE_SOURCES)) build/core_image.o -JANET_MAINCLIENT_OBJECTS=$(patsubst src/%.c,build/%.o,$(JANET_MAINCLIENT_SOURCES)) - -$(JANET_MAINCLIENT_OBJECTS): $(JANET_MAINCLIENT_HEADERS) - -# Compile the core image generated by the bootstrap build -build/core_image.o: build/core_image.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS) - $(CC) $(CFLAGS) -o $@ -c $< - -build/%.o: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS) - $(CC) $(CFLAGS) -o $@ -c $< - -$(JANET_TARGET): $(JANET_CORE_OBJECTS) $(JANET_MAINCLIENT_OBJECTS) - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^ $(CLIBS) - -$(JANET_LIBRARY): $(JANET_CORE_OBJECTS) - $(CC) $(LDFLAGS) $(CFLAGS) -shared -o $@ $^ $(CLIBS) - -$(JANET_STATIC_LIBRARY): $(JANET_CORE_OBJECTS) - $(AR) rcs $@ $^ - -############################# -##### Generated C files ##### -############################# - -%.gen.o: %.gen.c - $(CC) $(CFLAGS) -o $@ -c $< - -build/xxd: tools/xxd.c - $(CC) $< -o $@ - -build/webinit.gen.c: src/webclient/webinit.janet build/xxd - build/xxd $< $@ janet_gen_webinit -build/boot.gen.c: src/boot/boot.janet build/xxd - build/xxd $< $@ janet_gen_boot +build/janet.c: build/janet_boot src/boot/boot.janet + build/janet_boot . JANET_PATH '$(JANET_PATH)' JANET_HEADERPATH '$(INCLUDEDIR)/janet' > $@ ######################## ##### Amalgamation ##### ######################## -amalg: build/shell.c build/janet.c build/janet.h build/core_image.c build/janetconf.h - -AMALG_SOURCE=$(JANET_LOCAL_HEADERS) $(JANET_CORE_SOURCES) build/core_image.c -build/janet.c: $(AMALG_SOURCE) tools/amalg.janet $(JANET_TARGET) - $(JANET_TARGET) tools/amalg.janet $(AMALG_SOURCE) > $@ - -AMALG_SHELL_SOURCE=src/mainclient/line.h src/mainclient/line.c src/mainclient/main.c -build/shell.c: $(JANET_TARGET) tools/amalg.janet $(AMALG_SHELL_SOURCE) - $(JANET_TARGET) tools/amalg.janet $(AMALG_SHELL_SOURCE) > $@ +build/shell.c: src/mainclient/shell.c + cp $< $@ build/janet.h: src/include/janet.h cp $< $@ @@ -208,6 +155,21 @@ build/janet.h: src/include/janet.h build/janetconf.h: src/conf/janetconf.h cp $< $@ +build/janet.o: build/janet.c build/janet.h build/janetconf.h + $(CC) $(LDFLAGS) $(CFLAGS) -c $< -o $@ -I build $(CLIBS) + +build/shell.o: build/shell.c build/janet.h build/janetconf.h + $(CC) $(LDFLAGS) $(CFLAGS) -c $< -o $@ -I build $(CLIBS) + +$(JANET_TARGET): build/janet.o build/shell.o + $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^ $(CLIBS) + +$(JANET_LIBRARY): build/janet.o build/shell.o + $(CC) $(LDFLAGS) $(CFLAGS) -shared -o $@ $^ $(CLIBS) + +$(JANET_STATIC_LIBRARY): build/janet.o build/shell.o + $(AR) rcs $@ $^ + ################### ##### Testing ##### ################### @@ -349,5 +311,5 @@ build/embed_test: build/embed_janet.o build/embed_main.o test-amalg: build/embed_test ./build/embed_test -.PHONY: clean install repl debug valgrind test amalg \ +.PHONY: clean install repl debug valgrind test \ valtest emscripten dist uninstall docs grammar format diff --git a/build_win.bat b/build_win.bat index aca1dbbe..e783064e 100644 --- a/build_win.bat +++ b/build_win.bat @@ -33,20 +33,6 @@ mkdir build\core mkdir build\mainclient mkdir build\boot -@rem Build the xxd tool for generating sources -cl /nologo /c tools/xxd.c /Fobuild\xxd.obj -@if errorlevel 1 goto :BUILDFAIL -link /nologo /out:build\xxd.exe build\xxd.obj -@if errorlevel 1 goto :BUILDFAIL - -@rem Generate the embedded sources -build\xxd.exe src\boot\boot.janet build\boot.gen.c janet_gen_boot -@if errorlevel 1 goto :BUILDFAIL - -@rem Build the generated sources -%JANET_COMPILE% /Fobuild\boot\boot.gen.obj build\boot.gen.c -@if errorlevel 1 goto :BUILDFAIL - @rem Build the bootstrap interpreter for %%f in (src\core\*.c) do ( %JANET_COMPILE% /DJANET_BOOTSTRAP /Fobuild\boot\%%~nf.obj %%f @@ -58,48 +44,25 @@ for %%f in (src\boot\*.c) do ( ) %JANET_LINK% /out:build\janet_boot.exe build\boot\*.obj @if errorlevel 1 goto :BUILDFAIL -build\janet_boot build\core_image.c - -@rem Build the core image -%JANET_COMPILE% /Fobuild\core_image.obj build\core_image.c -@if errorlevel 1 goto :BUILDFAIL +build\janet_boot . > build\janet.c @rem Build the sources -for %%f in (src\core\*.c) do ( - %JANET_COMPILE% /Fobuild\core\%%~nf.obj %%f - @if errorlevel 1 goto :BUILDFAIL -) +%JANET_COMPILE% /Fobuild\janet.obj build\janet.c +@if errorlevel 1 goto :BUILDFAIL +%JANET_COMPILE% /Fobuild\shell.obj src\mainclient\shell.c +@if errorlevel 1 goto :BUILDFAIL @rem Build the resources rc /nologo /fobuild\janet_win.res janet_win.rc -@rem Build the main client -for %%f in (src\mainclient\*.c) do ( - %JANET_COMPILE% /Fobuild\mainclient\%%~nf.obj %%f - @if errorlevel 1 goto :BUILDFAIL -) - @rem Link everything to main client -%JANET_LINK% /out:janet.exe build\core\*.obj build\mainclient\*.obj build\core_image.obj build\janet_win.res +%JANET_LINK% /out:janet.exe build\janet.obj build\shell.obj build\janet_win.res @if errorlevel 1 goto :BUILDFAIL @rem Build static library (libjanet.a) -%JANET_LINK_STATIC% /out:build\libjanet.lib build\core\*.obj build\core_image.obj +%JANET_LINK_STATIC% /out:build\libjanet.lib build\janet.obj @if errorlevel 1 goto :BUILDFAIL -@rem Gen amlag -setlocal enabledelayedexpansion -set "amalg_files=" -for %%f in (src\core\*.c) do ( - set "amalg_files=!amalg_files! %%f" -) -janet.exe tools\amalg.janet src\core\features.h src\core\util.h src\core\state.h src\core\gc.h src\core\vector.h src\core\fiber.h src\core\regalloc.h src\core\compile.h src\core\emit.h src\core\symcache.h %amalg_files% build\core_image.c > build\janet.c -janet.exe tools\removecr.janet build\janet.c - -@rem Gen shell.c -janet.exe tools\amalg.janet src\mainclient\line.h src\mainclient\line.c src\mainclient\main.c > build\shell.c -janet.exe tools\removecr.janet build\shell.c - echo === Successfully built janet.exe for Windows === echo === Run 'build_win test' to run tests. == echo === Run 'build_win clean' to delete build artifacts. === @@ -141,7 +104,7 @@ janet.exe tools\gendoc.janet > dist\doc.html janet.exe tools\removecr.janet dist\doc.html copy build\janet.c dist\janet.c -copy build\shell.c dist\shell.c +copy src\mainclient\shell.c dist\shell.c copy janet.exe dist\janet.exe copy LICENSE dist\LICENSE copy README.md dist\README.md diff --git a/meson.build b/meson.build index ad02b255..fe9a02f8 100644 --- a/meson.build +++ b/meson.build @@ -79,13 +79,6 @@ jconf = configure_file(output : 'janetconf.h', # Include directories incdir = include_directories(['src/include', '.']) -# Building generated sources -xxd = executable('xxd', 'tools/xxd.c', native : true) -gen = generator(xxd, - output : '@BASENAME@.gen.c', - arguments : ['@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@']) -boot_gen = gen.process('src/boot/boot.janet', extra_args: 'janet_gen_boot') - # Order is important here, as some headers # depend on other headers for the amalg target core_headers = [ @@ -151,24 +144,27 @@ boot_src = [ ] mainclient_src = [ - 'src/mainclient/line.c', - 'src/mainclient/main.c' + 'src/mainclient/shell.c' ] # Build boot binary -janet_boot = executable('janet-boot', core_src, boot_src, boot_gen, +janet_boot = executable('janet-boot', core_src, boot_src, include_directories : incdir, c_args : '-DJANET_BOOTSTRAP', dependencies : [m_dep, dl_dep, thread_dep], native : true) -# Build core image -core_image = custom_target('core_image', +# Build janet.c +janetc = custom_target('janetc', input : [janet_boot], - output : 'core_image.gen.c', - command : [janet_boot, '@OUTPUT@', 'JANET_PATH', janet_path, 'JANET_HEADERPATH', header_path]) + output : 'janet.c', + capture : true, + command : [ + janet_boot, '@CURRENT_SOURCE_DIR@', + 'JANET_PATH', janet_path, 'JANET_HEADERPATH', header_path + ]) -libjanet = library('janet', core_src, core_image, +libjanet = library('janet', janetc, include_directories : incdir, dependencies : [m_dep, dl_dep, thread_dep], install : true) @@ -188,14 +184,14 @@ else extra_cross_cflags = [] endif -janet_mainclient = executable('janet', core_src, core_image, mainclient_src, +janet_mainclient = executable('janet', janetc, mainclient_src, include_directories : incdir, dependencies : [m_dep, dl_dep, thread_dep], c_args : extra_native_cflags, install : true) if meson.is_cross_build() - janet_nativeclient = executable('janet-native', core_src, core_image, mainclient_src, + janet_nativeclient = executable('janet-native', janetc, mainclient_src, include_directories : incdir, dependencies : [m_dep, dl_dep, thread_dep], c_args : extra_cross_cflags, @@ -211,25 +207,6 @@ docs = custom_target('docs', capture : true, command : [janet_nativeclient, '@INPUT@']) -# Amalgamated source -amalg = custom_target('amalg', - input : ['tools/amalg.janet', core_headers, core_src, core_image], - output : ['janet.c'], - capture : true, - command : [janet_nativeclient, '@INPUT@']) -amalg_shell = custom_target('amalg-shell', - input : ['tools/amalg.janet', 'src/mainclient/line.h', - 'src/mainclient/line.c', 'src/mainclient/main.c'], - output : ['shell.c'], - capture : true, - command : [janet_nativeclient, '@INPUT@']) - -# Amalgamated client -janet_amalgclient = executable('janet-amalg', amalg, amalg_shell, - include_directories : incdir, - dependencies : [m_dep, dl_dep, thread_dep], - build_by_default : false) - # Tests test_files = [ 'test/suite0.janet', diff --git a/src/boot/boot.c b/src/boot/boot.c index 0caf017b..9cf64f2b 100644 --- a/src/boot/boot.c +++ b/src/boot/boot.c @@ -23,6 +23,13 @@ #include <janet.h> #include "tests.h" +#ifdef JANET_WINDOWS +#include <windows.h> +#define chdir(x) _chdir(x) +#else +#include <unistd.h> +#endif + extern const unsigned char *janet_gen_boot; extern int32_t janet_gen_boot_size; @@ -63,13 +70,37 @@ int main(int argc, const char **argv) { janet_def(env, "boot/config", janet_wrap_table(opts), "Boot options"); /* Run bootstrap script to generate core image */ - const char *boot_file; + const char *boot_filename; #ifdef JANET_NO_SOURCEMAPS - boot_file = NULL; + boot_filename = NULL; #else - boot_file = "boot.janet"; + boot_filename = "boot.janet"; #endif - status = janet_dobytes(env, janet_gen_boot, janet_gen_boot_size, boot_file, NULL); + + chdir(argv[1]); + + FILE *boot_file = fopen("src/boot/boot.janet", "rb"); + if (NULL == boot_file) { + fprintf(stderr, "Could not open src/boot/boot.janet\n"); + exit(1); + } + + /* Slurp file into buffer */ + fseek(boot_file, 0, SEEK_END); + size_t boot_size = ftell(boot_file); + fseek(boot_file, 0, SEEK_SET); + unsigned char *boot_buffer = malloc(boot_size); + if (NULL == boot_buffer) { + fprintf(stderr, "Failed to allocate boot buffer\n"); + exit(1); + } + if (!fread(boot_buffer, 1, boot_size, boot_file)) { + fprintf(stderr, "Failed to read into boot buffer\n"); + exit(1); + } + fclose(boot_file); + + status = janet_dobytes(env, boot_buffer, boot_size, boot_filename, NULL); /* Deinitialize vm */ janet_deinit(); diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 5b0e53a8..f1360943 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -1,5 +1,5 @@ # The core janet library -# Copyright 2019 © Calvin Rose +# Copyright 2020 © Calvin Rose ### ### @@ -2391,21 +2391,88 @@ reverse-lookup (invert lookup)] (marshal env reverse-lookup))) + # Create amalgamation + + (def local-headers + ["src/core/features.h" + "src/core/util.h" + "src/core/state.h" + "src/core/gc.h" + "src/core/vector.h" + "src/core/fiber.h" + "src/core/regalloc.h" + "src/core/compile.h" + "src/core/emit.h" + "src/core/symcache.h"]) + + (def core-sources + ["src/core/abstract.c" + "src/core/array.c" + "src/core/asm.c" + "src/core/buffer.c" + "src/core/bytecode.c" + "src/core/capi.c" + "src/core/cfuns.c" + "src/core/compile.c" + "src/core/corelib.c" + "src/core/debug.c" + "src/core/emit.c" + "src/core/fiber.c" + "src/core/gc.c" + "src/core/inttypes.c" + "src/core/io.c" + "src/core/marsh.c" + "src/core/math.c" + "src/core/os.c" + "src/core/parse.c" + "src/core/peg.c" + "src/core/pp.c" + "src/core/regalloc.c" + "src/core/run.c" + "src/core/specials.c" + "src/core/string.c" + "src/core/strtod.c" + "src/core/struct.c" + "src/core/symcache.c" + "src/core/table.c" + "src/core/thread.c" + "src/core/tuple.c" + "src/core/typedarray.c" + "src/core/util.c" + "src/core/value.c" + "src/core/vector.c" + "src/core/vm.c" + "src/core/wrap.c"]) + + # Print janet.c to stdout + (print "/* Amalgamated build - DO NOT EDIT */") + (print "/* Generated from janet version " janet/version "-" janet/build " */") + (print "#define JANET_BUILD \"" janet/build "\"") + (print ```#define JANET_AMALG```) + (print ```#define _POSIX_C_SOURCE 200112L```) + (print ```#include "janet.h"```) + + (defn do-one-flie + [fname] + (print "\n/* " fname " */\n") + (def source (slurp fname)) + (print (string/replace-all "\r" "" source))) + + (each h local-headers + (do-one-flie h)) + + (each s core-sources + (do-one-flie s)) + # Create C source file that contains images a uint8_t buffer. This # can be compiled and linked statically into the main janet library # and example client. - (def chunks (string/bytes image)) - (def image-file (file/open (boot/args 1) :wb)) - (file/write image-file - "#ifndef JANET_AMALG\n" - "#include <janet.h>\n" - "#endif\n" - "static const unsigned char janet_core_image_bytes[] = {\n") - (loop [line :in (partition 10 chunks)] - (def str (string ;(interpose ", " (map (partial string/format "0x%.2X") line)))) - (file/write image-file " " str ",\n")) - (file/write image-file - " 0\n};\n\n" - "const unsigned char *janet_core_image = janet_core_image_bytes;\n" - "size_t janet_core_image_size = sizeof(janet_core_image_bytes);\n") - (file/close image-file)) + (print "static const unsigned char janet_core_image_bytes[] = {") + (loop [line :in (partition 16 image)] + (prin " ") + (each b line + (prinf "0x%.2X, " b)) + (print)) + (print " 0\n};\n") + (print "const unsigned char *janet_core_image = janet_core_image_bytes;") + (print "size_t janet_core_image_size = sizeof(janet_core_image_bytes);")) diff --git a/src/core/array.c b/src/core/array.c index 22a929cf..46014d9c 100644 --- a/src/core/array.c +++ b/src/core/array.c @@ -56,7 +56,7 @@ JanetArray *janet_array_n(const Janet *elements, int32_t n) { if (!array->data) { JANET_OUT_OF_MEMORY; } - memcpy(array->data, elements, sizeof(Janet) * n); + safe_memcpy(array->data, elements, sizeof(Janet) * n); return array; } @@ -235,10 +235,12 @@ static Janet cfun_array_insert(int32_t argc, Janet *argv) { janet_panic("array overflow"); } janet_array_ensure(array, array->count + argc - 2, 2); - memmove(array->data + at + argc - 2, - array->data + at, - restsize); - memcpy(array->data + at, argv + 2, chunksize); + if (restsize) { + memmove(array->data + at + argc - 2, + array->data + at, + restsize); + } + safe_memcpy(array->data + at, argv + 2, chunksize); array->count += (argc - 2); return argv[0]; } diff --git a/src/core/buffer.c b/src/core/buffer.c index 9691a552..1f2327a5 100644 --- a/src/core/buffer.c +++ b/src/core/buffer.c @@ -112,6 +112,7 @@ void janet_buffer_push_cstring(JanetBuffer *buffer, const char *cstring) { /* Push multiple bytes into the buffer */ void janet_buffer_push_bytes(JanetBuffer *buffer, const uint8_t *string, int32_t length) { + if (0 == length) return; janet_buffer_extra(buffer, length); memcpy(buffer->data + buffer->count, string, length); buffer->count += length; @@ -338,11 +339,13 @@ static Janet cfun_buffer_blit(int32_t argc, Janet *argv) { janet_panic("buffer blit out of range"); janet_buffer_ensure(dest, (int32_t) last, 2); if (last > dest->count) dest->count = (int32_t) last; - if (same_buf) { - src.bytes = dest->data; - memmove(dest->data + offset_dest, src.bytes + offset_src, length_src); - } else { - memcpy(dest->data + offset_dest, src.bytes + offset_src, length_src); + if (length_src) { + if (same_buf) { + src.bytes = dest->data; + memmove(dest->data + offset_dest, src.bytes + offset_src, length_src); + } else { + memcpy(dest->data + offset_dest, src.bytes + offset_src, length_src); + } } return argv[0]; } diff --git a/src/core/compile.c b/src/core/compile.c index c388c37d..62fb4b0b 100644 --- a/src/core/compile.c +++ b/src/core/compile.c @@ -713,7 +713,7 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) { if (NULL == def->bytecode) { JANET_OUT_OF_MEMORY; } - memcpy(def->bytecode, c->buffer + scope->bytecode_start, s); + safe_memcpy(def->bytecode, c->buffer + scope->bytecode_start, s); janet_v__cnt(c->buffer) = scope->bytecode_start; if (NULL != c->mapbuffer && c->source) { size_t s = sizeof(JanetSourceMapping) * (size_t) def->bytecode_length; @@ -721,7 +721,7 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) { if (NULL == def->sourcemap) { JANET_OUT_OF_MEMORY; } - memcpy(def->sourcemap, c->mapbuffer + scope->bytecode_start, s); + safe_memcpy(def->sourcemap, c->mapbuffer + scope->bytecode_start, s); janet_v__cnt(c->mapbuffer) = scope->bytecode_start; } } diff --git a/src/core/corelib.c b/src/core/corelib.c index bb981bbe..5042ddbf 100644 --- a/src/core/corelib.c +++ b/src/core/corelib.c @@ -346,7 +346,7 @@ static Janet janet_core_tuple(int32_t argc, Janet *argv) { static Janet janet_core_array(int32_t argc, Janet *argv) { JanetArray *array = janet_array(argc); array->count = argc; - memcpy(array->data, argv, argc * sizeof(Janet)); + safe_memcpy(array->data, argv, argc * sizeof(Janet)); return janet_wrap_array(array); } diff --git a/src/core/debug.c b/src/core/debug.c index 3e79c641..9a7e9db5 100644 --- a/src/core/debug.c +++ b/src/core/debug.c @@ -275,7 +275,7 @@ static Janet doframe(JanetStackFrame *frame) { } /* Add stack arguments */ slots = janet_array(def->slotcount); - memcpy(slots->data, stack, sizeof(Janet) * def->slotcount); + safe_memcpy(slots->data, stack, sizeof(Janet) * def->slotcount); slots->count = def->slotcount; janet_table_put(t, janet_ckeywordv("slots"), janet_wrap_array(slots)); } diff --git a/src/core/fiber.c b/src/core/fiber.c index 5e4a0845..124b9f39 100644 --- a/src/core/fiber.c +++ b/src/core/fiber.c @@ -65,7 +65,7 @@ JanetFiber *janet_fiber_reset(JanetFiber *fiber, JanetFunction *callee, int32_t if (newstacktop >= fiber->capacity) { janet_fiber_setcapacity(fiber, 2 * newstacktop); } - memcpy(fiber->data + fiber->stacktop, argv, argc * sizeof(Janet)); + safe_memcpy(fiber->data + fiber->stacktop, argv, argc * sizeof(Janet)); fiber->stacktop = newstacktop; } if (janet_fiber_funcframe(fiber, callee)) return NULL; @@ -135,7 +135,7 @@ void janet_fiber_pushn(JanetFiber *fiber, const Janet *arr, int32_t n) { if (newtop > fiber->capacity) { janet_fiber_grow(fiber, newtop); } - memcpy(fiber->data + fiber->stacktop, arr, n * sizeof(Janet)); + safe_memcpy(fiber->data + fiber->stacktop, arr, n * sizeof(Janet)); fiber->stacktop = newtop; } @@ -217,7 +217,7 @@ static void janet_env_detach(JanetFuncEnv *env) { if (NULL == vmem) { JANET_OUT_OF_MEMORY; } - memcpy(vmem, env->as.fiber->data + env->offset, s); + safe_memcpy(vmem, env->as.fiber->data + env->offset, s); env->offset = 0; env->as.values = vmem; } diff --git a/src/core/gc.c b/src/core/gc.c index b5d62ddd..ba3e3400 100644 --- a/src/core/gc.c +++ b/src/core/gc.c @@ -29,6 +29,11 @@ #include "util.h" #endif +struct JanetScratch { + JanetScratchFinalizer finalize; + long long mem[]; /* for proper alignment */ +}; + /* GC State */ JANET_THREAD_LOCAL void *janet_vm_blocks; JANET_THREAD_LOCAL size_t janet_vm_gc_interval; @@ -41,14 +46,7 @@ JANET_THREAD_LOCAL size_t janet_vm_root_count; JANET_THREAD_LOCAL size_t janet_vm_root_capacity; /* Scratch Memory */ -#ifdef JANET_64 -#define SCRATCH_HDR_SIZE 16 /* smalloc must guarantee 16 byte alignment. */ -#elif JANET_32 -#define SCRATCH_HDR_SIZE 8 /* smalloc must guarantee 8 byte alignment. */ -#else -#error "unknown scratch alignment" -#endif -JANET_THREAD_LOCAL void **janet_scratch_mem; +JANET_THREAD_LOCAL JanetScratch **janet_scratch_mem; JANET_THREAD_LOCAL size_t janet_scratch_cap; JANET_THREAD_LOCAL size_t janet_scratch_len; @@ -360,11 +358,11 @@ void *janet_gcalloc(enum JanetMemoryType type, size_t size) { return (void *)mem; } -static void free_one_scratch(void *mem) { - ScratchFinalizer finalize = *(ScratchFinalizer *)mem; - if (finalize) - finalize((char *)mem + SCRATCH_HDR_SIZE); - free(mem); +static void free_one_scratch(JanetScratch *s) { + if (NULL != s->finalize) { + s->finalize((char *) s->mem); + } + free(s); } /* Free all allocated scratch memory */ @@ -375,6 +373,11 @@ static void janet_free_all_scratch(void) { janet_scratch_len = 0; } +static JanetScratch *janet_mem2scratch(void *mem) { + JanetScratch *s = (JanetScratch *)mem; + return s - 1; +} + /* Run garbage collection */ void janet_collect(void) { uint32_t i; @@ -478,26 +481,26 @@ void janet_gcunlock(int handle) { /* Scratch memory API */ void *janet_smalloc(size_t size) { - void *mem = malloc(SCRATCH_HDR_SIZE + size); - if (NULL == mem) { + JanetScratch *s = malloc(sizeof(JanetScratch) + size); + if (NULL == s) { JANET_OUT_OF_MEMORY; } - *(ScratchFinalizer *)mem = NULL; + s->finalize = NULL; if (janet_scratch_len == janet_scratch_cap) { size_t newcap = 2 * janet_scratch_cap + 2; - void **newmem = (void **) realloc(janet_scratch_mem, newcap * sizeof(void *)); + JanetScratch **newmem = (JanetScratch **) realloc(janet_scratch_mem, newcap * sizeof(JanetScratch)); if (NULL == newmem) { JANET_OUT_OF_MEMORY; } janet_scratch_cap = newcap; janet_scratch_mem = newmem; } - janet_scratch_mem[janet_scratch_len++] = mem; - return (char *)mem + SCRATCH_HDR_SIZE; + janet_scratch_mem[janet_scratch_len++] = s; + return (char *)(s->mem); } void *janet_scalloc(size_t nmemb, size_t size) { - if (nmemb && size > (size_t) -1 / size) { + if (nmemb && size > SIZE_MAX / nmemb) { JANET_OUT_OF_MEMORY; } size_t n = nmemb * size; @@ -508,16 +511,16 @@ void *janet_scalloc(size_t nmemb, size_t size) { void *janet_srealloc(void *mem, size_t size) { if (NULL == mem) return janet_smalloc(size); - mem = (char *)mem - SCRATCH_HDR_SIZE; + JanetScratch *s = janet_mem2scratch(mem); if (janet_scratch_len) { for (size_t i = janet_scratch_len - 1; ; i--) { - if (janet_scratch_mem[i] == mem) { - void *newmem = realloc(mem, size + SCRATCH_HDR_SIZE); - if (NULL == newmem) { + if (janet_scratch_mem[i] == s) { + JanetScratch *news = realloc(s, size + sizeof(JanetScratch)); + if (NULL == news) { JANET_OUT_OF_MEMORY; } - janet_scratch_mem[i] = newmem; - return (char *)newmem + SCRATCH_HDR_SIZE; + janet_scratch_mem[i] = news; + return (char *)(news->mem); } if (i == 0) break; } @@ -525,19 +528,19 @@ void *janet_srealloc(void *mem, size_t size) { janet_exit("invalid janet_srealloc"); } -void janet_sfinalizer(void *mem, ScratchFinalizer finalizer) { - mem = (char *)mem - SCRATCH_HDR_SIZE; - *(ScratchFinalizer *)mem = finalizer; +void janet_sfinalizer(void *mem, JanetScratchFinalizer finalizer) { + JanetScratch *s = janet_mem2scratch(mem); + s->finalize = finalizer; } void janet_sfree(void *mem) { if (NULL == mem) return; - mem = (char *)mem - SCRATCH_HDR_SIZE; + JanetScratch *s = janet_mem2scratch(mem); if (janet_scratch_len) { for (size_t i = janet_scratch_len - 1; ; i--) { - if (janet_scratch_mem[i] == mem) { + if (janet_scratch_mem[i] == s) { janet_scratch_mem[i] = janet_scratch_mem[--janet_scratch_len]; - free_one_scratch(mem); + free_one_scratch(s); return; } if (i == 0) break; diff --git a/src/core/marsh.c b/src/core/marsh.c index 263dec39..48ba55cb 100644 --- a/src/core/marsh.c +++ b/src/core/marsh.c @@ -95,8 +95,8 @@ void janet_env_lookup_into(JanetTable *renv, JanetTable *env, const char *prefix const uint8_t *oldsym = janet_unwrap_symbol(env->data[i].key); int32_t oldlen = janet_string_length(oldsym); uint8_t *symbuf = janet_smalloc(prelen + oldlen); - memcpy(symbuf, prefix, prelen); - memcpy(symbuf + prelen, oldsym, oldlen); + safe_memcpy(symbuf, prefix, prelen); + safe_memcpy(symbuf + prelen, oldsym, oldlen); Janet s = janet_symbolv(symbuf, prelen + oldlen); janet_sfree(symbuf); janet_table_put(renv, s, entry_getval(env->data[i].value)); @@ -1017,7 +1017,7 @@ uint8_t janet_unmarshal_byte(JanetMarshalContext *ctx) { void janet_unmarshal_bytes(JanetMarshalContext *ctx, uint8_t *dest, size_t len) { UnmarshalState *st = (UnmarshalState *)(ctx->u_state); MARSH_EOS(st, ctx->data + len - 1); - memcpy(dest, ctx->data, len); + safe_memcpy(dest, ctx->data, len); ctx->data += len; } @@ -1139,7 +1139,7 @@ static const uint8_t *unmarshal_one( } else { /* (lead == LB_BUFFER) */ JanetBuffer *buffer = janet_buffer(len); buffer->count = len; - memcpy(buffer->data, data, len); + safe_memcpy(buffer->data, data, len); *out = janet_wrap_buffer(buffer); } janet_v_push(st->lookup, *out); diff --git a/src/core/parse.c b/src/core/parse.c index 5a44c494..8e477580 100644 --- a/src/core/parse.c +++ b/src/core/parse.c @@ -688,20 +688,19 @@ void janet_parser_clone(const JanetParser *src, JanetParser *dest) { if (dest->bufcap) { dest->buf = malloc(dest->bufcap); if (!dest->buf) goto nomem; + memcpy(dest->buf, src->buf, dest->bufcap); } if (dest->argcap) { dest->args = malloc(sizeof(Janet) * dest->argcap); if (!dest->args) goto nomem; + memcpy(dest->args, src->args, dest->argcap * sizeof(Janet)); } if (dest->statecap) { dest->states = malloc(sizeof(JanetParseState) * dest->statecap); if (!dest->states) goto nomem; + memcpy(dest->states, src->states, dest->statecap * sizeof(JanetParseState)); } - memcpy(dest->buf, src->buf, dest->bufcap); - memcpy(dest->args, src->args, dest->argcap * sizeof(Janet)); - memcpy(dest->states, src->states, dest->statecap * sizeof(JanetParseState)); - return; nomem: @@ -808,7 +807,7 @@ static Janet cfun_parse_insert(int32_t argc, Janet *argv) { } p->bufcap = newcap; } - memcpy(p->buf + p->bufcount, str, slen); + safe_memcpy(p->buf + p->bufcount, str, slen); p->bufcount = newcount; } else { janet_panic("cannot insert value into parser"); @@ -891,7 +890,7 @@ static Janet janet_wrap_parse_state(JanetParseState *s, Janet *args, if (s->flags & PFLAG_CONTAINER) { JanetArray *container_args = janet_array(s->argn); container_args->count = s->argn; - memcpy(container_args->data, args, sizeof(args[0])*s->argn); + safe_memcpy(container_args->data, args, sizeof(args[0])*s->argn); janet_table_put(state, janet_ckeywordv("args"), janet_wrap_array(container_args)); } diff --git a/src/core/peg.c b/src/core/peg.c index 53f436d6..07775412 100644 --- a/src/core/peg.c +++ b/src/core/peg.c @@ -348,9 +348,9 @@ tail: if (!result) return NULL; int32_t num_sub_captures = s->captures->count - cs.cap; JanetArray *sub_captures = janet_array(num_sub_captures); - memcpy(sub_captures->data, - s->captures->data + cs.cap, - sizeof(Janet) * num_sub_captures); + safe_memcpy(sub_captures->data, + s->captures->data + cs.cap, + sizeof(Janet) * num_sub_captures); sub_captures->count = num_sub_captures; cap_load(s, cs); pushcap(s, janet_wrap_array(sub_captures), tag); @@ -1227,8 +1227,8 @@ static Peg *make_peg(Builder *b) { peg->bytecode = (uint32_t *)(mem + bytecode_start); peg->constants = (Janet *)(mem + constants_start); peg->num_constants = janet_v_count(b->constants); - memcpy(peg->bytecode, b->bytecode, bytecode_size); - memcpy(peg->constants, b->constants, constants_size); + safe_memcpy(peg->bytecode, b->bytecode, bytecode_size); + safe_memcpy(peg->constants, b->constants, constants_size); peg->bytecode_len = janet_v_count(b->bytecode); return peg; } diff --git a/src/core/state.h b/src/core/state.h index bd3789c4..8674b07a 100644 --- a/src/core/state.h +++ b/src/core/state.h @@ -32,6 +32,8 @@ * be in it. However, thread local global variables for interpreter * state should allow easy multi-threading. */ +typedef struct JanetScratch JanetScratch; + /* Cache the core environment */ extern JANET_THREAD_LOCAL JanetTable *janet_vm_core_env; @@ -69,7 +71,7 @@ extern JANET_THREAD_LOCAL size_t janet_vm_root_count; extern JANET_THREAD_LOCAL size_t janet_vm_root_capacity; /* Scratch memory */ -extern JANET_THREAD_LOCAL void **janet_scratch_mem; +extern JANET_THREAD_LOCAL JanetScratch **janet_scratch_mem; extern JANET_THREAD_LOCAL size_t janet_scratch_cap; extern JANET_THREAD_LOCAL size_t janet_scratch_len; diff --git a/src/core/string.c b/src/core/string.c index a8b5758d..cb00b941 100644 --- a/src/core/string.c +++ b/src/core/string.c @@ -51,7 +51,7 @@ const uint8_t *janet_string(const uint8_t *buf, int32_t len) { head->length = len; head->hash = janet_string_calchash(buf, len); uint8_t *data = (uint8_t *)head->data; - memcpy(data, buf, len); + safe_memcpy(data, buf, len); data[len] = 0; return data; } @@ -187,7 +187,7 @@ static Janet cfun_string_repeat(int32_t argc, Janet *argv) { uint8_t *newbuf = janet_string_begin((int32_t) mulres); uint8_t *end = newbuf + mulres; for (uint8_t *p = newbuf; p < end; p += view.len) { - memcpy(p, view.bytes, view.len); + safe_memcpy(p, view.bytes, view.len); } return janet_wrap_string(janet_string_end(newbuf)); } @@ -343,11 +343,11 @@ static Janet cfun_string_replace(int32_t argc, Janet *argv) { return janet_stringv(s.kmp.text, s.kmp.textlen); } buf = janet_string_begin(s.kmp.textlen - s.kmp.patlen + s.substlen); - memcpy(buf, s.kmp.text, result); - memcpy(buf + result, s.subst, s.substlen); - memcpy(buf + result + s.substlen, - s.kmp.text + result + s.kmp.patlen, - s.kmp.textlen - result - s.kmp.patlen); + safe_memcpy(buf, s.kmp.text, result); + safe_memcpy(buf + result, s.subst, s.substlen); + safe_memcpy(buf + result + s.substlen, + s.kmp.text + result + s.kmp.patlen, + s.kmp.textlen - result - s.kmp.patlen); kmp_deinit(&s.kmp); return janet_wrap_string(janet_string_end(buf)); } @@ -445,11 +445,11 @@ static Janet cfun_string_join(int32_t argc, Janet *argv) { const uint8_t *chunk = NULL; int32_t chunklen = 0; if (i) { - memcpy(out, joiner.bytes, joiner.len); + safe_memcpy(out, joiner.bytes, joiner.len); out += joiner.len; } janet_bytes_view(parts.items[i], &chunk, &chunklen); - memcpy(out, chunk, chunklen); + safe_memcpy(out, chunk, chunklen); out += chunklen; } return janet_wrap_string(janet_string_end(buf)); diff --git a/src/core/strtod.c b/src/core/strtod.c index 05dfac9f..78f9c8f0 100644 --- a/src/core/strtod.c +++ b/src/core/strtod.c @@ -447,12 +447,16 @@ int janet_scan_int64(const uint8_t *str, int32_t len, int64_t *out) { int neg; uint64_t bi; if (scan_uint64(str, len, &bi, &neg)) { - if (neg && bi <= 0x8000000000000000ULL) { - *out = -((int64_t) bi); + if (neg && bi <= (UINT64_MAX / 2)) { + if (bi > INT64_MAX) { + *out = INT64_MIN; + } else { + *out = -((int64_t) bi); + } return 1; } - if (!neg && bi <= 0x7FFFFFFFFFFFFFFFULL) { - *out = bi; + if (!neg && bi <= INT64_MAX) { + *out = (int64_t) bi; return 1; } } diff --git a/src/core/symcache.c b/src/core/symcache.c index 8e887d47..b8366f06 100644 --- a/src/core/symcache.c +++ b/src/core/symcache.c @@ -183,7 +183,7 @@ const uint8_t *janet_symbol(const uint8_t *str, int32_t len) { head->hash = hash; head->length = len; newstr = (uint8_t *)(head->data); - memcpy(newstr, str, len); + safe_memcpy(newstr, str, len); newstr[len] = 0; janet_symcache_put((const uint8_t *)newstr, bucket); return newstr; diff --git a/src/core/tuple.c b/src/core/tuple.c index a75c846b..9a3415a2 100644 --- a/src/core/tuple.c +++ b/src/core/tuple.c @@ -49,7 +49,7 @@ const Janet *janet_tuple_end(Janet *tuple) { /* Build a tuple with n values */ const Janet *janet_tuple_n(const Janet *values, int32_t n) { Janet *t = janet_tuple_begin(n); - memcpy(t, values, sizeof(Janet) * n); + safe_memcpy(t, values, sizeof(Janet) * n); return janet_tuple_end(t); } diff --git a/src/core/util.c b/src/core/util.c index 63c3ff92..738127a9 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -248,6 +248,12 @@ int32_t janet_tablen(int32_t n) { return n + 1; } +/* Avoid some undefined behavior that was common in the code base. */ +void safe_memcpy(void *dest, const void *src, size_t len) { + if (!len) return; + memcpy(dest, src, len); +} + /* Helper to find a value in a Janet struct or table. Returns the bucket * containing the key, or the first empty bucket if there is no such key. */ const JanetKV *janet_dict_find(const JanetKV *buckets, int32_t cap, Janet key) { @@ -385,7 +391,7 @@ void janet_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns) if (NULL == longname_buffer) { JANET_OUT_OF_MEMORY; } - memcpy(longname_buffer, regprefix, prefixlen); + safe_memcpy(longname_buffer, regprefix, prefixlen); longname_buffer[prefixlen] = '/'; prefixlen++; } @@ -402,7 +408,7 @@ void janet_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns) JANET_OUT_OF_MEMORY; } } - memcpy(longname_buffer + prefixlen, cfuns->name, nmlen); + safe_memcpy(longname_buffer + prefixlen, cfuns->name, nmlen); name = janet_wrap_symbol(janet_symbol(longname_buffer, totallen)); } else { name = janet_csymbolv(cfuns->name); diff --git a/src/core/util.h b/src/core/util.h index 7c7f6919..5a3f5568 100644 --- a/src/core/util.h +++ b/src/core/util.h @@ -68,6 +68,7 @@ int32_t janet_array_calchash(const Janet *array, int32_t len); int32_t janet_kv_calchash(const JanetKV *kvs, int32_t len); int32_t janet_string_calchash(const uint8_t *str, int32_t len); int32_t janet_tablen(int32_t n); +void safe_memcpy(void *dest, const void *src, size_t len); void janet_buffer_push_types(JanetBuffer *buffer, int types); const JanetKV *janet_dict_find(const JanetKV *buckets, int32_t cap, Janet key); Janet janet_dict_get(const JanetKV *buckets, int32_t cap, Janet key); diff --git a/src/core/vector.c b/src/core/vector.c index 794da7e1..96fe77ba 100644 --- a/src/core/vector.c +++ b/src/core/vector.c @@ -45,7 +45,7 @@ void *janet_v_flattenmem(void *v, int32_t itemsize) { size_t size = (size_t) itemsize * janet_v__cnt(v); p = malloc(size); if (NULL != p) { - memcpy(p, v, size); + safe_memcpy(p, v, size); return p; } else { JANET_OUT_OF_MEMORY; diff --git a/src/include/janet.h b/src/include/janet.h index 5b678d04..cc8d7069 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -1360,11 +1360,12 @@ JANET_API Janet janet_mcall(const char *name, int32_t argc, Janet *argv); JANET_API void janet_stacktrace(JanetFiber *fiber, Janet err); /* Scratch Memory API */ -typedef void (*ScratchFinalizer)(void *); +typedef void (*JanetScratchFinalizer)(void *); + JANET_API void *janet_smalloc(size_t size); JANET_API void *janet_srealloc(void *mem, size_t size); JANET_API void *janet_scalloc(size_t nmemb, size_t size); -JANET_API void janet_sfinalizer(void *mem, ScratchFinalizer finalizer); +JANET_API void janet_sfinalizer(void *mem, JanetScratchFinalizer finalizer); JANET_API void janet_sfree(void *mem); /* C Library helpers */ diff --git a/src/mainclient/line.h b/src/mainclient/line.h deleted file mode 100644 index 5ff5929b..00000000 --- a/src/mainclient/line.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -* Copyright (c) 2020 Calvin Rose -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to -* deal in the Software without restriction, including without limitation the -* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -* sell copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -*/ - -#ifndef JANET_LINE_H_defined -#define JANET_LINE_H_defined - -#if !defined(_POSIX_C_SOURCE) -#define _POSIX_C_SOURCE 200112L -#endif - -#ifndef JANET_AMALG -#include <janet.h> -#endif - -void janet_line_init(); -void janet_line_deinit(); - -void janet_line_get(const char *p, JanetBuffer *buffer); -Janet janet_line_getter(int32_t argc, Janet *argv); - -#endif diff --git a/src/mainclient/main.c b/src/mainclient/main.c deleted file mode 100644 index 2dbacbdf..00000000 --- a/src/mainclient/main.c +++ /dev/null @@ -1,90 +0,0 @@ -/* -* Copyright (c) 2020 Calvin Rose -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to -* deal in the Software without restriction, including without limitation the -* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -* sell copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -*/ - -#if !defined(_POSIX_C_SOURCE) -#define _POSIX_C_SOURCE 200112L -#endif - -#ifndef JANET_AMALG -#include <janet.h> -#include "line.h" -#endif - -#ifdef _WIN32 -#include <windows.h> -#include <shlwapi.h> -#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING -#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 -#endif -#endif - -int main(int argc, char **argv) { - int i, status; - JanetArray *args; - JanetTable *env; - -#ifdef _WIN32 - /* Enable color console on windows 10 console and utf8 output. */ - HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); - DWORD dwMode = 0; - GetConsoleMode(hOut, &dwMode); - dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; - SetConsoleMode(hOut, dwMode); - SetConsoleOutputCP(65001); -#endif - - /* Set up VM */ - janet_init(); - - /* Replace original getline with new line getter */ - JanetTable *replacements = janet_table(0); - janet_table_put(replacements, janet_csymbolv("getline"), janet_wrap_cfunction(janet_line_getter)); - janet_line_init(); - - /* Get core env */ - env = janet_core_env(replacements); - - /* Create args tuple */ - args = janet_array(argc); - for (i = 1; i < argc; i++) - janet_array_push(args, janet_cstringv(argv[i])); - - /* Save current executable path to (dyn :executable) */ - janet_table_put(env, janet_ckeywordv("executable"), janet_cstringv(argv[0])); - - /* Run startup script */ - Janet mainfun, out; - janet_resolve(env, janet_csymbol("cli-main"), &mainfun); - Janet mainargs[1] = { janet_wrap_array(args) }; - JanetFiber *fiber = janet_fiber(janet_unwrap_function(mainfun), 64, 1, mainargs); - fiber->env = env; - status = janet_continue(fiber, janet_wrap_nil(), &out); - if (status != JANET_SIGNAL_OK) { - janet_stacktrace(fiber, out); - } - - /* Deinitialize vm */ - janet_deinit(); - janet_line_deinit(); - - return status; -} diff --git a/src/mainclient/line.c b/src/mainclient/shell.c index 6e0a2f0b..1ef3fd5c 100644 --- a/src/mainclient/line.c +++ b/src/mainclient/shell.c @@ -24,10 +24,26 @@ #define _POSIX_C_SOURCE 200112L #endif -#ifndef JANET_AMALG -#include "line.h" +#include <janet.h> + +#ifdef _WIN32 +#include <windows.h> +#include <shlwapi.h> +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 +#endif #endif +void janet_line_init(); +void janet_line_deinit(); + +void janet_line_get(const char *p, JanetBuffer *buffer); +Janet janet_line_getter(int32_t argc, Janet *argv); + +/* + * Line Editing + */ + static JANET_THREAD_LOCAL JanetTable *gbl_complete_env; /* Common */ @@ -80,8 +96,6 @@ void janet_line_get(const char *p, JanetBuffer *buffer) { https://github.com/antirez/linenoise/blob/master/linenoise.c */ -#include <janet.h> - #include <termios.h> #include <unistd.h> #include <stdlib.h> @@ -809,3 +823,59 @@ void janet_line_get(const char *p, JanetBuffer *buffer) { } #endif + +/* + * Entry + */ + +int main(int argc, char **argv) { + int i, status; + JanetArray *args; + JanetTable *env; + +#ifdef _WIN32 + /* Enable color console on windows 10 console and utf8 output. */ + HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD dwMode = 0; + GetConsoleMode(hOut, &dwMode); + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + SetConsoleMode(hOut, dwMode); + SetConsoleOutputCP(65001); +#endif + + /* Set up VM */ + janet_init(); + + /* Replace original getline with new line getter */ + JanetTable *replacements = janet_table(0); + janet_table_put(replacements, janet_csymbolv("getline"), janet_wrap_cfunction(janet_line_getter)); + janet_line_init(); + + /* Get core env */ + env = janet_core_env(replacements); + + /* Create args tuple */ + args = janet_array(argc); + for (i = 1; i < argc; i++) + janet_array_push(args, janet_cstringv(argv[i])); + + /* Save current executable path to (dyn :executable) */ + janet_table_put(env, janet_ckeywordv("executable"), janet_cstringv(argv[0])); + + /* Run startup script */ + Janet mainfun, out; + janet_resolve(env, janet_csymbol("cli-main"), &mainfun); + Janet mainargs[1] = { janet_wrap_array(args) }; + JanetFiber *fiber = janet_fiber(janet_unwrap_function(mainfun), 64, 1, mainargs); + fiber->env = env; + status = janet_continue(fiber, janet_wrap_nil(), &out); + if (status != JANET_SIGNAL_OK) { + janet_stacktrace(fiber, out); + } + + /* Deinitialize vm */ + janet_deinit(); + janet_line_deinit(); + + return status; +} diff --git a/tools/xxd.c b/tools/xxd.c deleted file mode 100644 index a45f4f03..00000000 --- a/tools/xxd.c +++ /dev/null @@ -1,104 +0,0 @@ -/* -* Copyright (c) 2020 Calvin Rose -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to -* deal in the Software without restriction, including without limitation the -* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -* sell copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -*/ - -/* Simple clone of the xxd tool used at build time. Used to - * create headers out of source files. Only used for core libraries - * like the bootstrapping code and the stl. */ - -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> - -#define BUFSIZE 1024 -#define PERLINE 10 - -int main(int argc, const char **argv) { - - static const char hex[] = "0123456789ABCDEF"; - char buf[BUFSIZE]; - size_t bytesRead = 0; - int32_t totalRead = 0; - int lineIndex = 0; - int line = 0; - - if (argc != 4) { - fprintf(stderr, "Usage: %s infile outfile symbol\n", argv[0]); - return 1; - } - - /* Open the files */ - FILE *in = fopen(argv[1], "rb"); - FILE *out = fopen(argv[2], "wb"); - - /* Check if files open successfully */ - if (in == NULL) { - fprintf(stderr, "Could not open input file %s\n", argv[1]); - return 1; - } else if (out == NULL) { - fprintf(stderr, "Could not open output file %s\n", argv[2]); - return 1; - } - - /* Write the header */ - fprintf(out, "/* Auto generated - DO NOT EDIT */\n\n#include <stdint.h>\n\n"); - fprintf(out, "static const unsigned char bytes_%s[] = {", argv[3]); - - /* Read in chunks from buffer */ - while ((bytesRead = fread(buf, 1, sizeof(buf), in)) > 0) { - size_t i; - totalRead += bytesRead; - for (i = 0; i < bytesRead; ++i) { - int byte = ((uint8_t *)buf) [i]; - - /* Write the byte */ - if (lineIndex++ == 0) { - if (line++) - fputc(',', out); - fputs("\n ", out); - } else { - fputs(", ", out); - } - fputs("0x", out); - fputc(hex[byte >> 4], out); - fputc(hex[byte & 0xF], out); - - /* Make line index wrap */ - if (lineIndex >= PERLINE) - lineIndex = 0; - - } - } - - /* Write the tail */ - fputs("\n};\n\n", out); - - fprintf(out, "const unsigned char *%s = bytes_%s;\n\n", argv[3], argv[3]); - - /* Write chunk size */ - fprintf(out, "int32_t %s_size = %d;\n", argv[3], totalRead); - - /* Close the file handles */ - fclose(in); - fclose(out); - - return 0; -} |
