From dad571f1691dbc40af86a3c821877e2933116634 Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Wed, 8 Jan 2025 09:59:16 -0600 Subject: [PATCH] Push to git --- .onedev-buildspec.yml | 27 +++++ CMakeLists.txt | 115 +++++++++++++++---- Dockerfile | 10 +- FileAssociation.nsh | 190 ++++++++++++++++++++++++++++++ README.md | 15 ++- crossvm-binfmt.conf.in | 1 + icon.png | Bin 2878 -> 0 bytes include/CrossLang.hpp | 4 +- logo-wiibrew.svg | 8 -- src/archive.cpp | 30 ++++- src/compiler/lexer.cpp | 1 + src/crosslang.cpp | 112 +++++++++++------- src/crosslangvm.cpp | 2 - src/runtime_methods/console.cpp | 26 +++-- src/runtime_methods/crypto.cpp | 138 +++++++++++++++------- src/runtime_methods/env.cpp | 78 ++++++++++--- src/runtime_methods/io.cpp | 35 ++++++ src/runtime_methods/net.cpp | 6 +- src/runtime_methods/ogc.cpp | 52 +++++++++ src/runtime_methods/process.cpp | 53 ++++++++- src/runtime_methods/sdl2.cpp | 197 +++++++++++++++++++++++++++++++- src/types/dictionary.cpp | 4 +- src/types/rootenvironment.cpp | 1 + src/vm/filereader.cpp | 4 +- src/vm/gc.cpp | 15 ++- src/vm/vm.cpp | 39 +++++-- winicon.ico | Bin 0 -> 46215 bytes winicon.rc | 1 + 28 files changed, 983 insertions(+), 181 deletions(-) create mode 100644 .onedev-buildspec.yml create mode 100644 FileAssociation.nsh create mode 100644 crossvm-binfmt.conf.in delete mode 100644 icon.png delete mode 100644 logo-wiibrew.svg create mode 100755 winicon.ico create mode 100644 winicon.rc diff --git a/.onedev-buildspec.yml b/.onedev-buildspec.yml new file mode 100644 index 0000000..913236a --- /dev/null +++ b/.onedev-buildspec.yml @@ -0,0 +1,27 @@ +version: 38 +jobs: +- name: Build for x86_64 + steps: + - !CheckoutStep + name: Checkout + cloneCredential: !DefaultCredential {} + withLfs: true + withSubmodules: false + condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL + - !BuildImageStep + name: Build Docker Image + output: !RegistryOutput + tags: onedev.site.tesses.net/crosslang/crosslang:latest + registryLogins: + - registryUrl: '@server_url@' + userName: '@job_token@' + passwordSecret: 'dockersecret' + platforms: linux/amd64 + condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL + triggers: + - !BranchUpdateTrigger + projects: crosslang + retryCondition: never + maxRetries: 3 + retryDelay: 30 + timeout: 14400 diff --git a/CMakeLists.txt b/CMakeLists.txt index 9735576..477883a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,11 +15,17 @@ option(CROSSLANG_ENABLE_JSON "Enable JSON" ON) option(CROSSLANG_ENABLE_PROCESS "Enable process" ON) option(CROSSLANG_ENABLE_SDL2 "Enable SDL2 (For Drawing)" ON) option(CROSSLANG_ENABLE_TERMIOS "Enable termios (For changing terminal options)" ON) +option(CROSSLANG_ENABLE_PLATFORM_FOLDERS "Enable platform folders" ON) +option(CROSSLANG_CUSTOM_CONSOLE "Enable custom Console" OFF) +if(CROSSLANG_CUSTOM_CONSOLE) +set(CROSSLANG_ENABLE_BINARIES OFF) +set(CROSSLANG_ENABLE_SHARED OFF) +endif() +set(CROSSLANG_OFFLINE_SHELL_PACKAGE "" CACHE FILEPATH "Path to the shell package generated from https://onedev.site.tesses.net/CrossLang/CrossLangExtras") set(JANSSON_DIR "" CACHE PATH "Directory for Jansson") - find_package(TessesFramework REQUIRED) function(CROSSLANG_LINK_DEPS CROSSLANG_TARGET_NAME) if(CROSSLANG_ENABLE_PROCESS) @@ -33,6 +39,7 @@ target_include_directories(${CROSSLANG_TARGET_NAME} PUBLIC ${JANSSON_DIR}/includ target_link_directories(${CROSSLANG_TARGET_NAME} PUBLIC ${JANSSON_DIR}/lib) endif() target_link_libraries(${CROSSLANG_TARGET_NAME} PUBLIC jansson) + endif() if(CROSSLANG_ENABLE_THREADING) target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_THREADING) @@ -45,6 +52,12 @@ if(CROSSLANG_ENABLE_SQLITE) target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_SQLITE) endif() +if(CROSSLANG_CUSTOM_CONSOLE) +target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_CUSTOM_CONSOLE) +endif() +if(CROSSLANG_ENABLE_PLATFORM_FOLDERS) +target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_PLATFORM_FOLDERS) +endif() if(CROSSLANG_ENABLE_SDL2) target_compile_definitions(${CROSSLANG_TARGET_NAME} PUBLIC CROSSLANG_ENABLE_SDL2) @@ -93,7 +106,6 @@ src/runtime_methods/crypto.cpp src/runtime_methods/ogc.cpp src/runtime_methods/path.cpp src/runtime_methods/env.cpp -src/sago/platform_folders.cpp src/types/ittr.cpp src/types/closure.cpp src/types/dictionary.cpp @@ -112,9 +124,24 @@ src/bitconverter.cpp src/archive.cpp ) +if(CROSSLANG_ENABLE_PLATFORM_FOLDERS) +list(APPEND CROSSLANG_SOURCE src/sago/platform_folders.cpp) +endif() if(CROSSLANG_ENABLE_SQLITE) list(APPEND CROSSLANG_SOURCE src/sqlite/sqlite3.c src/sqlite/vfs.c) endif() +if(CROSSLANG_OFFLINE_SHELL_PACKAGE STREQUAL "") + +else() +install(FILES ${CROSSLANG_OFFLINE_SHELL_PACKAGE} DESTINATION share/Tesses/CrossLang) +endif() + +if(MINGW) +list(APPEND CROSSLANG_WIN32_EXE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/winicon.rc") +if(MINGW) + ENABLE_LANGUAGE(RC) +endif(MINGW) +endif() @@ -124,13 +151,13 @@ if(CROSSLANG_ENABLE_STATIC) add_library(crosslang_static STATIC ${CROSSLANG_SOURCE}) target_link_libraries(crosslang_static PUBLIC TessesFramework::tessesframework) + CROSSLANG_LINK_DEPS(crosslang_static) list(APPEND TessesCrossLangLibs crosslang_static) endif() if(CROSSLANG_ENABLE_SHARED) - add_library(crosslang_shared SHARED ${CROSSLANG_SOURCE}) CROSSLANG_LINK_DEPS(crosslang_shared) target_link_libraries(crosslang_shared PUBLIC TessesFramework::tessesframework_shared) @@ -173,17 +200,20 @@ install(TARGETS crosslang_shared ) endif() endif() + + + if(CROSSLANG_ENABLE_BINARIES) if(CROSSLANG_ENABLE_SHARED) set(CMAKE_MACOSX_RPATH 1) set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -add_executable(crossc src/crosslangcompiler.cpp) -add_executable(crossvm src/crosslangvm.cpp) -add_executable(crossint src/crosslanginterperter.cpp) -add_executable(crossdump src/crosslangdump.cpp) -add_executable(crosslang src/crosslang.cpp) -add_executable(crossarchiveextract src/crossarchiveextract.cpp) -add_executable(crossarchivecreate src/crossarchivecreate.cpp) +add_executable(crossc src/crosslangcompiler.cpp ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossvm src/crosslangvm.cpp ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossint src/crosslanginterperter.cpp ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossdump src/crosslangdump.cpp ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crosslang src/crosslang.cpp ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossarchiveextract src/crossarchiveextract.cpp ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossarchivecreate src/crossarchivecreate.cpp ${CROSSLANG_WIN32_EXE_SRC}) target_link_libraries(crossc PUBLIC crosslang_shared) target_link_libraries(crossvm PUBLIC crosslang_shared) target_link_libraries(crossint PUBLIC crosslang_shared) @@ -193,13 +223,13 @@ target_link_libraries(crossarchiveextract PUBLIC crosslang_shared) target_link_libraries(crossarchivecreate PUBLIC crosslang_shared) elseif(CROSSLANG_ENABLE_STATIC) -add_executable(crossc src/crosslangcompiler.cpp) -add_executable(crossvm src/crosslangvm.cpp) -add_executable(crossint src/crosslanginterperter.cpp) -add_executable(crossdump src/crosslangdump.cpp) -add_executable(crosslang src/crosslang.cpp) -add_executable(crossarchiveextract src/crossarchiveextract.cpp) -add_executable(crossarchivecreate src/crossarchivecreate.cpp) +add_executable(crossc src/crosslangcompiler.cpp ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossvm src/crosslangvm.cpp ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossint src/crosslanginterperter.cpp ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossdump src/crosslangdump.cpp ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crosslang src/crosslang.cpp ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossarchiveextract src/crossarchiveextract.cpp ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossarchivecreate src/crossarchivecreate.cpp ${CROSSLANG_WIN32_EXE_SRC}) target_link_libraries(crossc PUBLIC crosslang_static) target_link_libraries(crossvm PUBLIC crosslang_static) target_link_libraries(crossint PUBLIC crosslang_static) @@ -208,13 +238,13 @@ target_link_libraries(crosslang PUBLIC crosslang_static) target_link_libraries(crossarchiveextract PUBLIC crosslang_static) target_link_libraries(crossarchivecreate PUBLIC crosslang_static) else() -add_executable(crossc src/crosslangcompiler.cpp ${CROSSLANG_SOURCE}) -add_executable(crossvm src/crosslangvm.cpp ${CROSSLANG_SOURCE}) -add_executable(crossint src/crosslanginterperter.cpp ${CROSSLANG_SOURCE}) -add_executable(crossdump src/crosslangdump.cpp ${CROSSLANG_SOURCE}) -add_executable(crosslang src/crosslang.cpp ${CROSSLANG_SOURCE}) -add_executable(crossarchiveextract src/crossarchiveextract.cpp ${CROSSLANG_SOURCE}) -add_executable(crossarchivecreate src/crossarchivecreate.cpp ${CROSSLANG_SOURCE}) +add_executable(crossc src/crosslangcompiler.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossvm src/crosslangvm.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossint src/crosslanginterperter.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossdump src/crosslangdump.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crosslang src/crosslang.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossarchiveextract src/crossarchiveextract.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) +add_executable(crossarchivecreate src/crossarchivecreate.cpp ${CROSSLANG_SOURCE} ${CROSSLANG_WIN32_EXE_SRC}) CROSSLANG_LINK_DEPS(crossc) CROSSLANG_LINK_DEPS(crossvm) CROSSLANG_LINK_DEPS(crossint) @@ -230,10 +260,45 @@ install(TARGETS crossdump DESTINATION bin) install(TARGETS crosslang DESTINATION bin) install(TARGETS crossarchiveextract DESTINATION bin) install(TARGETS crossarchivecreate DESTINATION bin) +configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/crossvm-binfmt.conf.in "${CMAKE_CURRENT_BINARY_DIR}/crossvm-binfmt.conf" +INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/binfmt.d) +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/crossvm-binfmt.conf" +DESTINATION ${CMAKE_INSTALL_LIBDIR}/binfmt.d) endif() include(InstallRequiredSystemLibraries) set(CPACK_PACKAGE_CONTACT "Mike Nolan ") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.md") set(CPACK_PACKAGE_VERSION_MAJOR "${TessesCrossLang_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${TessesCrossLang_VERSION_MINOR}") -include(CPack) \ No newline at end of file + +set(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS +"!include \\\"FileFunc.nsh\\\"\n!include \\\"${CMAKE_CURRENT_SOURCE_DIR}/FileAssociation.nsh\\\"") + + +# Create association on install +set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS + "\\\${RegisterExtension} '$INSTDIR\\\\bin\\\\crossvm.exe' '.crvm' 'CrossLang Executable'\n\ + \\\${RefreshShellIcons}") + +# Remove association on uninstall + + + set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS + "\\\${RegisterExtension} '$INSTDIR\\\\bin\\\\crossint.exe' '.tcross' 'CrossLang Script'\n\ + \\\${RefreshShellIcons}\n\ + \\\${UnRegisterExtension} '.crvm' 'CrossLang Executable'\n\ + \\\${RefreshShellIcons}") + +# Remove association on uninstall +set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS + "\\\${UnRegisterExtension} '.tcross' 'CrossLang Script'\n\ + \\\${RefreshShellIcons}\n\ + \\\${UnRegisterExtension} '.crvm' 'CrossLang Executable'\n\ + \\\${RefreshShellIcons}") + + set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/winicon.ico") +set(CPACK_NSIS_MODIFY_PATH ON) +set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$DESKTOP\\\\CrossLang Interperter.lnk' '$INSTDIR\\\\bin\\\\crossint.exe'") + + +include(CPack) diff --git a/Dockerfile b/Dockerfile index 6181417..1e08062 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,8 @@ -FROM ubuntu:noble +FROM onedev.site.tesses.net/tesses-framework/tesses-framework:latest RUN apt update -y && \ apt install -y --no-install-recommends \ - libjansson-dev cmake git ca-certificates wget libmbedtls-dev g++ gcc libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev build-essential && \ + libjansson-dev wget libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev && \ apt clean -y && \ rm -rf /var/lib/apt/lists/* -WORKDIR /tmp -RUN git clone https://onedev.site.tesses.net/TessesFramework && cd tesses-framework && mkdir build && cd build && cmake -S .. -B . && make -j4 && make install && cd /tmp && rm -r /tmp/tesses-framework -COPY . /src -WORKDIR /src -RUN mkdir build && cd build && cmake -S .. -B . && make -j4 && make install && cd / && rm -r /src +RUN mkdir /src && git clone https://onedev.site.tesses.net/crosslang . && cd /src && mkdir build && cd build && cmake -S .. -B . && make -j4 && make install && cd / && rm -r /src WORKDIR / diff --git a/FileAssociation.nsh b/FileAssociation.nsh new file mode 100644 index 0000000..b8c1e5e --- /dev/null +++ b/FileAssociation.nsh @@ -0,0 +1,190 @@ +/* +_____________________________________________________________________________ + + File Association +_____________________________________________________________________________ + + Based on code taken from http://nsis.sourceforge.net/File_Association + + Usage in script: + 1. !include "FileAssociation.nsh" + 2. [Section|Function] + ${FileAssociationFunction} "Param1" "Param2" "..." $var + [SectionEnd|FunctionEnd] + + FileAssociationFunction=[RegisterExtension|UnRegisterExtension] + +_____________________________________________________________________________ + + ${RegisterExtension} "[executable]" "[extension]" "[description]" + +"[executable]" ; executable which opens the file format + ; +"[extension]" ; extension, which represents the file format to open + ; +"[description]" ; description for the extension. This will be display in Windows Explorer. + ; + + + ${UnRegisterExtension} "[extension]" "[description]" + +"[extension]" ; extension, which represents the file format to open + ; +"[description]" ; description for the extension. This will be display in Windows Explorer. + ; + +_____________________________________________________________________________ + + Macros +_____________________________________________________________________________ + + Change log window verbosity (default: 3=no script) + + Example: + !include "FileAssociation.nsh" + !insertmacro RegisterExtension + ${FileAssociation_VERBOSE} 4 # all verbosity + !insertmacro UnRegisterExtension + ${FileAssociation_VERBOSE} 3 # no script +*/ + + +!ifndef FileAssociation_INCLUDED +!define FileAssociation_INCLUDED + +!include Util.nsh + +!verbose push +!verbose 3 +!ifndef _FileAssociation_VERBOSE + !define _FileAssociation_VERBOSE 3 +!endif +!verbose ${_FileAssociation_VERBOSE} +!define FileAssociation_VERBOSE `!insertmacro FileAssociation_VERBOSE` +!verbose pop + +!macro FileAssociation_VERBOSE _VERBOSE + !verbose push + !verbose 3 + !undef _FileAssociation_VERBOSE + !define _FileAssociation_VERBOSE ${_VERBOSE} + !verbose pop +!macroend + + + +!macro RegisterExtensionCall _EXECUTABLE _EXTENSION _DESCRIPTION + !verbose push + !verbose ${_FileAssociation_VERBOSE} + Push `${_DESCRIPTION}` + Push `${_EXTENSION}` + Push `${_EXECUTABLE}` + ${CallArtificialFunction} RegisterExtension_ + !verbose pop +!macroend + +!macro UnRegisterExtensionCall _EXTENSION _DESCRIPTION + !verbose push + !verbose ${_FileAssociation_VERBOSE} + Push `${_EXTENSION}` + Push `${_DESCRIPTION}` + ${CallArtificialFunction} UnRegisterExtension_ + !verbose pop +!macroend + + + +!define RegisterExtension `!insertmacro RegisterExtensionCall` +!define un.RegisterExtension `!insertmacro RegisterExtensionCall` + +!macro RegisterExtension +!macroend + +!macro un.RegisterExtension +!macroend + +!macro RegisterExtension_ + !verbose push + !verbose ${_FileAssociation_VERBOSE} + + Exch $R2 ;exe + Exch + Exch $R1 ;ext + Exch + Exch 2 + Exch $R0 ;desc + Exch 2 + Push $0 + Push $1 + + ReadRegStr $1 HKCR $R1 "" ; read current file association + StrCmp "$1" "" NoBackup ; is it empty + StrCmp "$1" "$R0" NoBackup ; is it our own + WriteRegStr HKCR $R1 "backup_val" "$1" ; backup current value +NoBackup: + WriteRegStr HKCR $R1 "" "$R0" ; set our file association + + ReadRegStr $0 HKCR $R0 "" + StrCmp $0 "" 0 Skip + WriteRegStr HKCR "$R0" "" "$R0" + WriteRegStr HKCR "$R0\shell" "" "open" + WriteRegStr HKCR "$R0\DefaultIcon" "" "$R2,0" +Skip: + WriteRegStr HKCR "$R0\shell\open\command" "" '"$R2" "%1"' + WriteRegStr HKCR "$R0\shell\edit" "" "Edit $R0" + WriteRegStr HKCR "$R0\shell\edit\command" "" '"$R2" "%1"' + + Pop $1 + Pop $0 + Pop $R2 + Pop $R1 + Pop $R0 + + !verbose pop +!macroend + + + +!define UnRegisterExtension `!insertmacro UnRegisterExtensionCall` +!define un.UnRegisterExtension `!insertmacro UnRegisterExtensionCall` + +!macro UnRegisterExtension +!macroend + +!macro un.UnRegisterExtension +!macroend + +!macro UnRegisterExtension_ + !verbose push + !verbose ${_FileAssociation_VERBOSE} + + Exch $R1 ;desc + Exch + Exch $R0 ;ext + Exch + Push $0 + Push $1 + + ReadRegStr $1 HKCR $R0 "" + StrCmp $1 $R1 0 NoOwn ; only do this if we own it + ReadRegStr $1 HKCR $R0 "backup_val" + StrCmp $1 "" 0 Restore ; if backup="" then delete the whole key + DeleteRegKey HKCR $R0 + Goto NoOwn + +Restore: + WriteRegStr HKCR $R0 "" $1 + DeleteRegValue HKCR $R0 "backup_val" + DeleteRegKey HKCR $R1 ;Delete key with association name settings + +NoOwn: + + Pop $1 + Pop $0 + Pop $R1 + Pop $R0 + + !verbose pop +!macroend + +!endif # !FileAssociation_INCLUDED \ No newline at end of file diff --git a/README.md b/README.md index 4be84fa..d0f6f7d 100644 --- a/README.md +++ b/README.md @@ -4,20 +4,25 @@ Tesses Cross Language ![CrossImage](logo.png) ## What is required to build this project -- [TessesFramework](https://onedev.site.tesses.net/TessesFramework) +- [TessesFramework](https://onedev.site.tesses.net/tesses-framework) - Jansson (but can be turned off but is strongly recommended otherwise many programs will not work) - CMake - SDL2 (but can be turned off) -## Use in docker +## Use in docker (use my container) ```bash - git clone https://onedev.site.tesses.net/CrossLang - cd CrossLang + sudo docker pull -t onedev.site.tesses.net/crosslang/crosslang:latest +``` + +## Use in docker (build the container yourself) +```bash + git clone https://onedev.site.tesses.net/crosslang + cd crosslang sudo docker build -t crosslang:latest . ``` ## To Install -- [Follow TessesFramework setup](https://onedev.site.tesses.net/TessesFramework) +- [Follow TessesFramework setup](https://onedev.site.tesses.net/tesses-framework) - Follow the commands bellow ## Run these commands to install crosslang (or use binaries from [here](https://crosslang.tesseslanguage.com/download/)) diff --git a/crossvm-binfmt.conf.in b/crossvm-binfmt.conf.in new file mode 100644 index 0000000..50aa4ee --- /dev/null +++ b/crossvm-binfmt.conf.in @@ -0,0 +1 @@ +:CrossVM:M::TCROSSVM::@CMAKE_INSTALL_PREFIX@/bin/crossvm: diff --git a/icon.png b/icon.png deleted file mode 100644 index 2b568dffde4e8c06339cd4c2cf40c07a19022fa7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2878 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 diff --git a/include/CrossLang.hpp b/include/CrossLang.hpp index 39b0ef9..da920ce 100644 --- a/include/CrossLang.hpp +++ b/include/CrossLang.hpp @@ -23,6 +23,8 @@ namespace Tesses::CrossLang { std::string EscapeString(std::string text,bool quote); + Tesses::Framework::Filesystem::VFSPath GetRealExecutablePath(Tesses::Framework::Filesystem::VFSPath realPath); + enum TVMVersionStage : uint8_t { DevVersion=0, @@ -641,7 +643,7 @@ class Parser { } THeapObjectHolder() { - this->obj = obj; + } }; class MethodInvoker { diff --git a/logo-wiibrew.svg b/logo-wiibrew.svg deleted file mode 100644 index 6f3a156..0000000 --- a/logo-wiibrew.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/archive.cpp b/src/archive.cpp index fe7e8fc..28f4270 100644 --- a/src/archive.cpp +++ b/src/archive.cpp @@ -5,6 +5,25 @@ namespace Tesses::CrossLang void CrossArchiveCreate(Tesses::Framework::Filesystem::VFS* vfs,Tesses::Framework::Streams::Stream* strm,std::string name, TVMVersion version, std::string info) { + std::vector ignored_files; + std::string file = "/.crossarchiveignore"; + if(vfs->FileExists(file)) + { + auto strm = vfs->OpenFile(file,"rb"); + if(strm != nullptr) + { + Tesses::Framework::TextStreams::StreamReader reader(strm,true); + std::string ignores; + while(reader.ReadLine(ignores)) + { + if(!ignores.empty() && ignores[0] != '#') + { + ignored_files.push_back(ignores); + } + ignores.clear(); + } + } + } static std::vector error_message_byte_code = { PUSHSTRING, 0, @@ -73,7 +92,7 @@ namespace Tesses::CrossLang }; Tesses::Framework::Streams::MemoryStream ms(true); - std::function walkFS = [vfs,&ensureString,&ensureResource,&ms,&walkFS,&writeInt](Tesses::Framework::Filesystem::VFSPath path)->void { + std::function walkFS = [&ignored_files,vfs,&ensureString,&ensureResource,&ms,&walkFS,&writeInt](Tesses::Framework::Filesystem::VFSPath path)->void { if(vfs->DirectoryExists(path)) { @@ -83,6 +102,11 @@ namespace Tesses::CrossLang for(auto item : vfs->EnumeratePaths(path)) { if(!item.relative && item.path.size() == 1 && item.path[0] == "__resdir_tmp") continue; + if(!item.relative && item.path.size() == 1 && item.path[0] == ".crossarchiveignore") continue; + std::string filename = item.GetFileName(); + bool shallIgnore=false; + for(auto ign : ignored_files) if(ign == filename) {shallIgnore=true; break;} + if(shallIgnore) continue; if(vfs->DirectoryExists(item) || vfs->RegularFileExists(item)) paths.push_back(item.GetFileName()); } @@ -280,7 +304,7 @@ namespace Tesses::CrossLang else{ uint8_t* buffer=new uint8_t[tableLen]; ensure(buffer,tableLen); - delete buffer; + delete[] buffer; } } } @@ -288,4 +312,4 @@ namespace Tesses::CrossLang return std::pair,std::string>(std::pair(name,v2),info); } -} \ No newline at end of file +} diff --git a/src/compiler/lexer.cpp b/src/compiler/lexer.cpp index b93cd1b..57eda66 100644 --- a/src/compiler/lexer.cpp +++ b/src/compiler/lexer.cpp @@ -1,5 +1,6 @@ #include "CrossLang.hpp" #include +#include namespace Tesses::CrossLang { std::string EscapeString(std::string text,bool quote) diff --git a/src/crosslang.cpp b/src/crosslang.cpp index 3e6326e..c71303d 100644 --- a/src/crosslang.cpp +++ b/src/crosslang.cpp @@ -7,61 +7,95 @@ using namespace Tesses::Framework; using namespace Tesses::CrossLang; using namespace Tesses::Framework::Http; +bool Download(Tesses::Framework::Filesystem::VFSPath filename,Tesses::Framework::Filesystem::VFS* vfs) +{ + while(true) + { + std::cout << "File " << filename.ToString() << " not found, do you want to download the installer from: https://downloads.tesses.net/ShellPackage.crvm (this may install other stuff as well) (Y/n)? "; + std::string line; + std::getline(std::cin,line); + if(line == "Y" || line == "y") + { + HttpRequest req; + req.url = "https://downloads.tesses.net/ShellPackage.crvm"; + req.method = "GET"; + HttpResponse resp(req); + if(resp.statusCode == StatusCode::OK) + { + auto strm = resp.ReadAsStream(); + CrossArchiveExtract(strm, vfs); + delete strm; + return true; + } + else + { + std::cout << "Error when fetching the script error: " << std::to_string(resp.statusCode) << " " << HttpUtils::StatusCodeString(resp.statusCode) << std::endl; + return false; + } + } + else if(line == "N" || line == "n") + { + std::cout << "Looks like you will need to install manually" << std::endl; + return false; + } + else + { + std::cout << "Please use Y or N (case insensitive)" << std::endl; + + } + } + return false; +} + int main(int argc, char** argv) { TF_Init(); - Tesses::Framework::Filesystem::VFSPath filename = sago::getConfigHome(); - filename = filename / "Tesses" / "CrossLang" / "Shell" / "Shell.crvm"; + Tesses::Framework::Filesystem::VFSPath dir = sago::getConfigHome(); + dir = dir / "Tesses" / "CrossLang"; + + Tesses::Framework::Filesystem::VFSPath filename = dir / "Shell" / "Shell.crvm"; Tesses::Framework::Filesystem::LocalFilesystem fs; + + auto p = GetRealExecutablePath(fs.SystemToVFSPath(argv[0])).GetParent().GetParent() / "share" / "Tesses" / "CrossLang" / "Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm"; + + if(!fs.RegularFileExists(filename)) + { + Tesses::Framework::Filesystem::SubdirFilesystem subdir(&fs,dir,false); + if(fs.RegularFileExists(p)) + { + std::cout << "Installing " << p.ToString() << " -> " << dir.ToString() << std::endl; + auto strm = fs.OpenFile(p,"rb"); + if(strm != nullptr) + { + CrossArchiveExtract(strm, &subdir); + delete strm; + } + else + { + return 1; + } + } + else + { + if(!Download(filename,&subdir)) return 1; + } + } + + GC gc; gc.Start(); - tryAgain: GCList ls(gc); TRootEnvironment* env = TRootEnvironment::Create(ls, TDictionary::Create(ls)); TStd::RegisterStd(&gc,env); - if(fs.RegularFileExists(filename)) + env->LoadFileWithDependencies(&gc, &fs, filename); - else - { - tryAgainFast: - std::cout << "File " << filename.ToString() << " not found, do you want to download the installer from: https://gitea.site.tesses.net/tesses50/crosslang-libs/raw/branch/master/crosslang-shell-install.tcross (this may install other stuff as well) (Y/n)? "; - std::string line; - std::getline(std::cin,line); - if(line == "Y" || line == "y") - { - HttpRequest req; - req.url = "https://gitea.site.tesses.net/tesses50/crosslang-libs/raw/branch/master/crosslang-shell-install.tcross"; - req.method = "GET"; - HttpResponse resp(req); - if(resp.statusCode == StatusCode::OK) - { - std::string str = resp.ReadAsString(); - env->Eval(ls, str); - goto tryAgain; - } - else - { - std::cout << "Error when fetching the script error: " << std::to_string(resp.statusCode) << " " << HttpUtils::StatusCodeString(resp.statusCode) << std::endl; - return 1; - } - } - else if(line == "N" || line == "n") - { - std::cout << "Looks like you will need to install manually" << std::endl; - return 0; - } - else - { - std::cout << "Please use Y or N (case insensitive)" << std::endl; - goto tryAgainFast; - } - } + TList* args = TList::Create(ls); diff --git a/src/crosslangvm.cpp b/src/crosslangvm.cpp index 76d1140..bad0c12 100644 --- a/src/crosslangvm.cpp +++ b/src/crosslangvm.cpp @@ -1,6 +1,4 @@ #include "CrossLang.hpp" - -#include using namespace Tesses::Framework; using namespace Tesses::CrossLang; int main(int argc, char** argv) diff --git a/src/runtime_methods/console.cpp b/src/runtime_methods/console.cpp index 4d45a44..2c43b7b 100644 --- a/src/runtime_methods/console.cpp +++ b/src/runtime_methods/console.cpp @@ -1,3 +1,4 @@ +#ifndef CROSSLANG_CUSTOM_CONSOLE #include "CrossLang.hpp" #include @@ -13,14 +14,14 @@ namespace Tesses::CrossLang { struct termios orig_termios; static void disableRawMode() { - tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios); + tcsetattr(0, TCSAFLUSH, &orig_termios); } #endif TObject Console_getEcho(GCList& ls, std::vector args) { #ifdef CROSSLANG_ENABLE_TERMIOS struct termios raw; - tcgetattr(STDIN_FILENO, &raw); + tcgetattr(0, &raw); return (raw.c_lflag & ECHO) > 0; #endif @@ -33,7 +34,7 @@ namespace Tesses::CrossLang { bool cooked = std::get(args[0]); #ifdef CROSSLANG_ENABLE_TERMIOS struct termios raw; - tcgetattr(STDIN_FILENO, &raw); + tcgetattr(0, &raw); if(cooked) { raw.c_lflag |= ECHO; @@ -43,7 +44,7 @@ namespace Tesses::CrossLang { raw.c_lflag &= ~(ECHO); } - tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); + tcsetattr(0, TCSAFLUSH, &raw); #endif return cooked; @@ -54,7 +55,7 @@ namespace Tesses::CrossLang { { #ifdef CROSSLANG_ENABLE_TERMIOS struct termios raw; - tcgetattr(STDIN_FILENO, &raw); + tcgetattr(0, &raw); return (raw.c_lflag & ICANON) > 0; #endif @@ -67,7 +68,7 @@ namespace Tesses::CrossLang { bool cooked = std::get(args[0]); #ifdef CROSSLANG_ENABLE_TERMIOS struct termios raw; - tcgetattr(STDIN_FILENO, &raw); + tcgetattr(0, &raw); if(cooked) { raw.c_lflag |= ICANON; @@ -77,7 +78,7 @@ namespace Tesses::CrossLang { raw.c_lflag &= ~(ICANON); } - tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); + tcsetattr(0, TCSAFLUSH, &raw); #endif return cooked; @@ -88,7 +89,7 @@ namespace Tesses::CrossLang { { #ifdef CROSSLANG_ENABLE_TERMIOS struct termios raw; - tcgetattr(STDIN_FILENO, &raw); + tcgetattr(0, &raw); return (raw.c_lflag & ISIG) > 0; #endif @@ -101,7 +102,7 @@ namespace Tesses::CrossLang { bool cooked = std::get(args[0]); #ifdef CROSSLANG_ENABLE_TERMIOS struct termios raw; - tcgetattr(STDIN_FILENO, &raw); + tcgetattr(0, &raw); if(cooked) { raw.c_lflag |= ISIG; @@ -111,7 +112,7 @@ namespace Tesses::CrossLang { raw.c_lflag &= ~(ISIG); } - tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); + tcsetattr(0, TCSAFLUSH, &raw); #endif return cooked; @@ -164,7 +165,7 @@ namespace Tesses::CrossLang { { env->permissions.canRegisterConsole=true; #ifdef CROSSLANG_ENABLE_TERMIOS - tcgetattr(STDIN_FILENO, &orig_termios); + tcgetattr(0, &orig_termios); atexit(disableRawMode); #endif GCList ls(gc); @@ -186,4 +187,5 @@ namespace Tesses::CrossLang { env->DeclareVariable("Console", dict); gc->BarrierEnd(); } -} \ No newline at end of file +} +#endif diff --git a/src/runtime_methods/crypto.cpp b/src/runtime_methods/crypto.cpp index a43e889..b0b2dbb 100644 --- a/src/runtime_methods/crypto.cpp +++ b/src/runtime_methods/crypto.cpp @@ -1,12 +1,13 @@ #include "CrossLang.hpp" -#if defined(CROSSLANG_ENABLE_MBED) +#include +#if defined(TESSESFRAMEWORK_ENABLE_MBED) #include #include #include #include #include - +#include #include #include #include @@ -18,8 +19,94 @@ namespace Tesses::CrossLang { - #if defined(CROSSLANG_ENABLE_MBED) + #if defined(TESSESFRAMEWORK_ENABLE_MBED) + static TObject Crypto_RandomBytes(GCList& ls, std::vector args) + { + int64_t size; + std::string personalStr; + if(GetArgument(args,0,size) && GetArgument(args,1,personalStr)) + { + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + + mbedtls_entropy_init(&entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + + int ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) "personalization_string", strlen("personalization_string")); + if(ret != 0) + { + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + return nullptr; + } + std::vector bytes; + bytes.resize((size_t)size); + ret = mbedtls_ctr_drbg_random(&ctr_drbg, bytes.data(),bytes.size()); + if (ret != 0) + { + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + return nullptr; + } + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + TByteArray* ba = TByteArray::Create(ls); + ba->data = bytes; + return ba; + } + return nullptr; + } + static TObject Crypto_PBKDF2(GCList& ls, std::vector args) + { + std::string pass; + TByteArray* bArraySalt; + int64_t itterations; + int64_t keylength; + int64_t shanum; + if(GetArgument(args,0,pass) && GetArgumentHeap(args,1, bArraySalt) && GetArgument(args,2, itterations) && GetArgument(args,3,keylength) && GetArgument(args,4,shanum)) + { + mbedtls_md_context_t ctx; + mbedtls_md_init(&ctx); + const mbedtls_md_info_t* info = NULL; + switch(shanum) + { + case 1: + info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); + break; + case 224: + info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA224); + break; + case 256: + info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + break; + default: + case 384: + info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384); + break; + case 512: + info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); + break; + } + + + mbedtls_md_setup(&ctx, info, 1); + + std::vector key; + key.resize((size_t)keylength); + if(mbedtls_pkcs5_pbkdf2_hmac(&ctx, (const unsigned char*)pass.c_str(), pass.size(), bArraySalt->data.data(), bArraySalt->data.size(), (int)itterations,(uint32_t)key.size(),key.data()) == 0) + { + auto ba = TByteArray::Create(ls); + ba->data = key; + mbedtls_md_free(&ctx); + return ba; + } + + mbedtls_md_free(&ctx); + } + return nullptr; + } + static TObject Crypto_Sha1(GCList& ls, std::vector args) { @@ -228,9 +315,9 @@ namespace Tesses::CrossLang } - return ""; } + return ""; } static TObject Crypto_Base64Decode(GCList& ls, std::vector args) { @@ -253,58 +340,27 @@ namespace Tesses::CrossLang } + return ""; } #endif void TStd::RegisterCrypto(GC* gc,TRootEnvironment* env) { env->permissions.canRegisterCrypto=true; - #if defined(CROSSLANG_ENABLE_MBED) + #if defined(TESSESFRAMEWORK_ENABLE_MBED) GCList ls(gc); TDictionary* dict = TDictionary::Create(ls); + dict->DeclareFunction(gc, "PBKDF2","Hash passwords with PBKDF2",{"pass","salt","itterations","keylen","shanum"},Crypto_PBKDF2); + dict->DeclareFunction(gc, "RandomBytes","Create bytearray but with random bytes in it instead of zeros (this uses mbedtls by the way)",{"byteCount","personalString"},Crypto_RandomBytes); dict->DeclareFunction(gc, "Sha1","Sha1 Algorithm (needed for WebSocket handshake/BitTorrent etc) (don't use unless you have no other choice)",{},Crypto_Sha1); dict->DeclareFunction(gc, "Sha256","Sha256 Algorithm",{"$is224"},Crypto_Sha256); dict->DeclareFunction(gc, "Sha512","Sha512 Algorithm",{"$is384"},Crypto_Sha512); - dict->DeclareFunction(gc, "Base64Encode","Sha512 Algorithm",{"data"},Crypto_Base64Encode); + dict->DeclareFunction(gc, "Base64Encode","Base64 encode",{"data"},Crypto_Base64Encode); + dict->DeclareFunction(gc, "Base64Decode","Base64 decode",{"str"},Crypto_Base64Decode); gc->BarrierBegin(); env->DeclareVariable("Crypto", dict); gc->BarrierEnd(); - dict = TDictionary::Create(ls); - dict->DeclareFunction(gc, "Encode","Encode Base64",{"buffer","offset","count"},[](GCList& ls,std::vector args)->TObject{ - TByteArray* bArray; - int64_t offset; - int64_t count; - - if(!GetArgumentHeap(args,0,bArray)) - return nullptr; - if(!GetArgument(args,1, offset)) - return nullptr; - if(!GetArgument(args,2, count)) - return nullptr; - - size_t off = (size_t)offset; - size_t len = (size_t)count; - - off = std::min(off, bArray->data.size()); - - len = std::min(len, bArray->data.size()-off); - - size_t outLen = ((4 * len / 3) + 3) & ~3; - - std::string str(outLen,'\0'); - - if(mbedtls_base64_encode((unsigned char*)str.data(),str.size(),&outLen,bArray->data.data(),bArray->data.size()) != 0) - return nullptr; - - str.resize(outLen); - - return str; - - //bArray->data.size(); - - // - }); #endif } diff --git a/src/runtime_methods/env.cpp b/src/runtime_methods/env.cpp index d145530..bcd712d 100644 --- a/src/runtime_methods/env.cpp +++ b/src/runtime_methods/env.cpp @@ -1,15 +1,55 @@ #include "CrossLang.hpp" - +#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) #include "../sago/platform_folders.h" +#endif #if defined(_WIN32) #include #endif namespace Tesses::CrossLang { + #if defined(_WIN32) + static char EnvPathSeperator=';'; + #else + static char EnvPathSeperator=':'; + #endif + + Tesses::Framework::Filesystem::VFSPath GetRealExecutablePath(Tesses::Framework::Filesystem::VFSPath realPath) + { + using namespace Tesses::Framework::Filesystem; + using namespace Tesses::Framework::Http; + LocalFilesystem lfs; + if(!realPath.relative) return realPath; + const char* path = std::getenv("PATH"); + #if defined(_WIN32) + const char* pathext = std::getenv("PATHEXT"); + auto pext = HttpUtils::SplitString(pathext,";"); + pext.push_back({}); + auto pathParts = HttpUtils::SplitString(path,";"); + for(auto item : pathParts) + { + for(auto item2 : pext) + { + auto newPath = (lfs.SystemToVFSPath(item) / realPath) + item2; + if(lfs.FileExists(newPath)) return newPath; + } + } + return realPath.RelativeCurrentDirectory(); + #else + + auto pathParts = HttpUtils::SplitString(path,":"); + for(auto item : pathParts) + { + auto newPath = lfs.SystemToVFSPath(item) / realPath; + if(lfs.FileExists(newPath)) return newPath; + } + return realPath.RelativeCurrentDirectory(); + #endif + } + static std::string GetHomeFolder() { - #if !defined(SAGO_DISABLE) + #if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) return sago::getHomeDir(); #elif defined(__EMSCRIPTEN__) return "/home/web_user"; @@ -98,7 +138,7 @@ namespace Tesses::CrossLang } static TObject Env_getDownloads(GCList& ls, std::vector args) { - #if !defined(SAGO_DISABLE) + #if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) return sago::getDownloadFolder(); #else return GetHomeFolder() + "/Downloads"; @@ -107,7 +147,7 @@ namespace Tesses::CrossLang static TObject Env_getMusic(GCList& ls, std::vector args) { - #if !defined(SAGO_DISABLE) + #if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) return sago::getMusicFolder(); #else return GetHomeFolder() + "/Music"; @@ -115,7 +155,7 @@ namespace Tesses::CrossLang } static TObject Env_getPictures(GCList& ls, std::vector args) { - #if !defined(SAGO_DISABLE) + #if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) return sago::getPicturesFolder(); #else return GetHomeFolder() + "/Pictures"; @@ -123,7 +163,7 @@ namespace Tesses::CrossLang } static TObject Env_getVideos(GCList& ls, std::vector args) { - #if !defined(SAGO_DISABLE) + #if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) return sago::getVideoFolder(); #else return GetHomeFolder() + "/Videos"; @@ -131,7 +171,7 @@ namespace Tesses::CrossLang } static TObject Env_getDocuments(GCList& ls, std::vector args) { - #if !defined(SAGO_DISABLE) + #if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) return sago::getDocumentsFolder(); #else return GetHomeFolder() + "/Documents"; @@ -139,7 +179,7 @@ namespace Tesses::CrossLang } static TObject Env_getConfig(GCList& ls, std::vector args) { - #if !defined(SAGO_DISABLE) + #if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) return sago::getConfigHome(); #else return GetHomeFolder() + "/Config"; @@ -148,7 +188,7 @@ namespace Tesses::CrossLang static TObject Env_getDesktop(GCList& ls, std::vector args) { - #if !defined(SAGO_DISABLE) + #if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) return sago::getDesktopFolder(); #else return GetHomeFolder() + "/Desktop"; @@ -156,7 +196,7 @@ namespace Tesses::CrossLang } static TObject Env_getState(GCList& ls, std::vector args) { - #if !defined(SAGO_DISABLE) + #if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) return sago::getStateDir(); #else return GetHomeFolder() + "/State"; @@ -164,7 +204,7 @@ namespace Tesses::CrossLang } static TObject Env_getCache(GCList& ls, std::vector args) { - #if !defined(SAGO_DISABLE) + #if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) return sago::getCacheDir(); #else return GetHomeFolder() + "/Cache"; @@ -172,7 +212,7 @@ namespace Tesses::CrossLang } static TObject Env_getData(GCList& ls, std::vector args) { - #if !defined(SAGA_DISABLE) + #if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) return sago::getDataHome(); #else return GetHomeFolder() + "/Data"; @@ -182,6 +222,15 @@ namespace Tesses::CrossLang { return GetHomeFolder(); } + static TObject Env_GetRealExecutablePath(GCList& ls, std::vector args) + { + Tesses::Framework::Filesystem::VFSPath p; + if(GetArgumentAsPath(args,0,p)) + { + return GetRealExecutablePath(p); + } + return Tesses::Framework::Filesystem::VFSPath(); + } void TStd::RegisterEnv(GC* gc, TRootEnvironment* env) { @@ -203,9 +252,10 @@ namespace Tesses::CrossLang dict->DeclareFunction(gc,"getData","Get data folder",{},Env_getData); dict->DeclareFunction(gc,"getUser","Get user folder",{},Env_getUser); dict->DeclareFunction(gc,"getPlatform","Get platform name",{},Env_getPlatform); - + dict->DeclareFunction(gc,"GetRealExecutablePath", "Get the absolute path for executable", {"path"},Env_GetRealExecutablePath); gc->BarrierBegin(); + dict->SetValue("EnvPathSeperator",EnvPathSeperator); env->SetVariable("Env", dict); gc->BarrierEnd(); } -} \ No newline at end of file +} diff --git a/src/runtime_methods/io.cpp b/src/runtime_methods/io.cpp index a3f89cb..51d40a7 100644 --- a/src/runtime_methods/io.cpp +++ b/src/runtime_methods/io.cpp @@ -110,6 +110,38 @@ namespace Tesses::CrossLang return nullptr; } + static TObject FS_ReadAllText(GCList& ls, std::vector args) + { + Tesses::Framework::Filesystem::VFSPath path; + + TVFSHeapObject* vfs; + if(GetArgumentHeap(args,0,vfs) && GetArgumentAsPath(args,1,path)) + { + auto txtFile = vfs->vfs->OpenFile(path,"rb"); + if(txtFile == nullptr) return ""; + Tesses::Framework::TextStreams::StreamReader reader(txtFile,true); + return reader.ReadToEnd(); + } + return ""; + } + + static TObject FS_WriteAllText(GCList& ls, std::vector args) + { + Tesses::Framework::Filesystem::VFSPath path; + + TVFSHeapObject* vfs; + + std::string content; + if(GetArgumentHeap(args,0,vfs) && GetArgumentAsPath(args,1,path) && GetArgument(args,2,content)) + { + auto txtFile = vfs->vfs->OpenFile(path,"wb"); + if(txtFile == nullptr) return nullptr; + Tesses::Framework::TextStreams::StreamWriter writer(txtFile,true); + writer.Write(content); + } + return nullptr; + } + void TStd::RegisterIO(GC* gc,TRootEnvironment* env,bool enableLocalFilesystem) { @@ -126,6 +158,9 @@ namespace Tesses::CrossLang dict->SetValue("Local", vfs); dict->DeclareFunction(gc, "MakeFull", "Make absolute path from relative path",{"path"},FS_MakeFull); } + + dict->DeclareFunction(gc, "ReadAllText","Read all text from file", {"fs","filename"},FS_ReadAllText); + dict->DeclareFunction(gc, "WriteAllText","Write all text to file", {"fs","filename","content"},FS_WriteAllText); dict->DeclareFunction(gc, "MountableFilesystem","Create a mountable filesystem",{"root"}, FS_MountableFilesystem); dict->DeclareFunction(gc, "SubdirFilesystem","Create a subdir filesystem",{"fs","subdir"}, FS_SubdirFilesystem); diff --git a/src/runtime_methods/net.cpp b/src/runtime_methods/net.cpp index f2a258f..79059df 100644 --- a/src/runtime_methods/net.cpp +++ b/src/runtime_methods/net.cpp @@ -162,9 +162,9 @@ namespace Tesses::CrossLang return ctx->NeedToParseFormData(); }); - /*dict->DeclareFunction(gc,"ReadString","Read string from request",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector args2)->TObject{ + dict->DeclareFunction(gc,"ReadString","Read string from request",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector args2)->TObject{ return ctx->ReadString(); - });*/ + }); dict->DeclareFunction(gc,"SendText","Send response text",{"text"},[ctx](Tesses::CrossLang::GCList &ls2, std::vector args2)->TObject{ std::string text; @@ -392,7 +392,7 @@ namespace Tesses::CrossLang std::filesystem::path p2 = p.GetFileName(); return HttpUtils::MimeType(p2); } - return "application/octet-stream"; + return std::string("application/octet-stream"); } static TObject Net_Http_MakeRequest(GCList& ls, std::vector args) diff --git a/src/runtime_methods/ogc.cpp b/src/runtime_methods/ogc.cpp index dbc786a..b24f442 100644 --- a/src/runtime_methods/ogc.cpp +++ b/src/runtime_methods/ogc.cpp @@ -1,4 +1,5 @@ #include "CrossLang.hpp" + #if defined(GEKKO) #include #include @@ -9,9 +10,60 @@ #endif namespace Tesses::CrossLang { + #if defined(GEKKO) + #if defined(HW_RVL) + static TObject OGC_WPAD_ScanPads(GCList& ls, std::vector args) + { + return (int64_t)WPAD_ScanPads(); + } + static TObject OGC_WPAD_ButtonsUp(GCList& ls, std::vector args) + { + int64_t chan; + if(GetArgument(args,0,chan)) + return (int64_t)WPAD_ButtonsUp((int)chan); + return 0; + } + static TObject OGC_WPAD_ButtonsDown(GCList& ls, std::vector args) + { + int64_t chan; + if(GetArgument(args,0,chan)) + return (int64_t)WPAD_ButtonsDown((int)chan); + return 0; + } + static TObject OGC_WPAD_ButtonsHeld(GCList& ls, std::vector args) + { + int64_t chan; + if(GetArgument(args,0,chan)) + return (int64_t)WPAD_ButtonsDown((int)chan); + return 0; + } + static TObject OGC_WPAD_BatteryLevel(GCList& ls, std::vector args) + { + int64_t chan; + if(GetArgument(args,0,chan)) + return (int64_t)WPAD_BatteryLevel((int)chan); + return 0; + } + #endif + #endif void TStd::RegisterOGC(GC* gc, TRootEnvironment* env) { + GCList ls(gc); + #if defined(GEKKO) + + + gc->BarrierBegin(); + TDictionary* dict_ogc_pad = TDictionary::Create(ls); + #if defined(HW_RVL) + TDictionary* dict_rvl_wpad = TDictionary::Create(ls); + dict_rvl_wpad->DeclareFunction(gc, "ScanPads","Scan wiimotes",{},OGC_WPAD_ScanPads); + env->DeclareVariable("WPAD", dict_rvl_wpad); + + #endif + env->DeclareVariable("PAD", dict_ogc_pad); + gc->BarrierEnd(); + #endif env->permissions.canRegisterOGC=true; } } \ No newline at end of file diff --git a/src/runtime_methods/process.cpp b/src/runtime_methods/process.cpp index d2505ce..c1f7461 100644 --- a/src/runtime_methods/process.cpp +++ b/src/runtime_methods/process.cpp @@ -20,7 +20,58 @@ namespace Tesses::CrossLang // Environment = [] //}) - + TDictionary* dict; + + if(GetArgumentHeap(args, 0, dict)) + { + auto gc = ls.GetGC(); + gc->BarrierBegin(); + + auto fobj = dict->GetValue("FileName"); + auto myargs = dict->GetValue("Arguments"); + auto env = dict->GetValue("Environment"); + + std::string filename; + TList* _args; + TList* env; + std::vector _args2; + std::vector _env; + + if(GetObject(fobj,filename)) + { + gc->BarrierEnd(); + return nullptr; + } + _args2.push_back(filename); + if(GetObjectHeap(myargs,_args)) + { + for(auto a : _args->items) + { + std::string a2; + if(GetObject(a,a2)) + { + _args2.push_back(a2); + } + } + } + if(GetObjectHeap(myargs,_args)) + { + for(auto a : _args->items) + { + std::string a2; + if(GetObject(a,a2)) + { + _args2.push_back(a2); + } + } + } + + + + gc->BarrierEnd(); + subprocess_create_ex() + } + return nullptr; } //#endif } \ No newline at end of file diff --git a/src/runtime_methods/sdl2.cpp b/src/runtime_methods/sdl2.cpp index ccdd512..02cf978 100644 --- a/src/runtime_methods/sdl2.cpp +++ b/src/runtime_methods/sdl2.cpp @@ -5,6 +5,165 @@ namespace Tesses::CrossLang { #if defined(CROSSLANG_ENABLE_SDL2) + static void TObjectToRect(TDictionary* dict, SDL_Rect& rect) + { + + int64_t number; + auto obj = dict->GetValue("x"); + if(GetObject(obj,number)) rect.x = (int)number; + obj = dict->GetValue("y"); + if(GetObject(obj,number)) rect.y = (int)number; + obj = dict->GetValue("w"); + if(GetObject(obj,number)) rect.w = (int)number; + obj = dict->GetValue("h"); + if(GetObject(obj,number)) rect.h = (int)number; + + } + + static TObject SDL2_RenderDrawRect(GCList& ls, std::vector args) + { + TNative* nat; + TDictionary* dict; + if(GetArgumentHeap(args,0, nat) && GetArgumentHeap(args,1,dict)) + { + SDL_Rect rect; + TObjectToRect(dict,rect); + return (int64_t)SDL_RenderDrawRect((SDL_Renderer*)nat->GetPointer(), &rect); + } + return nullptr; + } + static TObject SDL2_RenderFillRect(GCList& ls, std::vector args) + { + TNative* nat; + TDictionary* dict; + if(GetArgumentHeap(args,0, nat) && GetArgumentHeap(args,1,dict)) + { + SDL_Rect rect; + TObjectToRect(dict,rect); + return (int64_t)SDL_RenderFillRect((SDL_Renderer*)nat->GetPointer(), &rect); + } + return nullptr; + } + static TObject SDL2_PollEvent(GCList& ls, std::vector args) + { + SDL_Event event; + if(SDL_PollEvent(&event)) + { + TDictionary* dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type",(int64_t)event.common.type); + dict->SetValue("Timestamp",(int64_t)event.common.timestamp); + switch(event.type) + { + case SDL_DROPBEGIN: + case SDL_DROPCOMPLETE: + + dict->SetValue("WindowId",(int64_t)event.drop.windowID); + break; + case SDL_DROPFILE: + dict->SetValue("File", Tesses::Framework::Filesystem::VFSPath(std::string(event.drop.file))); + SDL_free(event.drop.file); + break; + case SDL_DROPTEXT: + dict->SetValue("WindowId",(int64_t)event.drop.windowID); + dict->SetValue("Text", std::string(event.drop.file)); + SDL_free(event.drop.file); + break; + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEBUTTONDOWN: + dict->SetValue("WindowId",(int64_t)event.button.windowID); + dict->SetValue("Which",(int64_t)event.button.which); + dict->SetValue("Button",(int64_t)event.button.button); + dict->SetValue("State",(int64_t)event.button.state); + dict->SetValue("Clicks",(int64_t)event.button.clicks); + dict->SetValue("X",(int64_t)event.button.x); + dict->SetValue("Y",(int64_t)event.button.y); + break; + case SDL_MOUSEMOTION: + dict->SetValue("WindowId",(int64_t)event.motion.windowID); + dict->SetValue("Which",(int64_t)event.motion.which); + dict->SetValue("State",(int64_t)event.motion.state); + dict->SetValue("X",(int64_t)event.motion.x); + dict->SetValue("Y",(int64_t)event.motion.y); + dict->SetValue("XRel",(int64_t)event.motion.xrel); + dict->SetValue("YRel",(int64_t)event.motion.yrel); + break; + case SDL_MOUSEWHEEL: + dict->SetValue("Direction", (int64_t)event.wheel.direction); + dict->SetValue("MouseX",(int64_t)event.wheel.mouseX); + dict->SetValue("MouseY",(int64_t)event.wheel.mouseY); + dict->SetValue("PreciseX",(double)event.wheel.preciseX); + dict->SetValue("PreciseY",(double)event.wheel.preciseY); + dict->SetValue("Which",(int64_t)event.wheel.which); + dict->SetValue("WindowId",(int64_t)event.wheel.windowID); + dict->SetValue("X",(int64_t)event.wheel.x); + dict->SetValue("Y",(int64_t)event.wheel.y); + break; + case SDL_KEYUP: + case SDL_KEYDOWN: + dict->SetValue("WindowId",(int64_t)event.key.windowID); + dict->SetValue("Repeat",(int64_t)event.key.repeat); + dict->SetValue("State",(int64_t)event.key.state); + { + TDictionary* dict2=TDictionary::Create(ls); + dict2->SetValue("Mod",(int64_t)event.key.keysym.mod); + dict2->SetValue("Scancode",(int64_t)event.key.keysym.scancode); + dict2->SetValue("Sym",(int64_t)event.key.keysym.sym); + dict->SetValue("Keysym",dict2); + } + break; + case SDL_EventType::SDL_FINGERMOTION: + dict->SetValue("Dx",event.tfinger.dx); + dict->SetValue("Dy",event.tfinger.dy); + //falls into SDL_FINGERUP/DOWN due to having same props + case SDL_EventType::SDL_FINGERUP: + case SDL_EventType::SDL_FINGERDOWN: + dict->SetValue("X",event.tfinger.x); + dict->SetValue("Y",event.tfinger.y); + + dict->SetValue("FingerId",(int64_t)event.tfinger.fingerId); + + dict->SetValue("Pressure",event.tfinger.pressure); + + dict->SetValue("TouchId",(int64_t)event.tfinger.touchId); + + dict->SetValue("WindowId",(int64_t)event.tfinger.windowID); + break; + case SDL_EventType::SDL_TEXTINPUT: + dict->SetValue("Text",event.text.text); + dict->SetValue("WindowId",(int64_t)event.text.windowID); + break; + case SDL_EventType::SDL_TEXTEDITING: + dict->SetValue("Text",event.edit.text); + dict->SetValue("Length",(int64_t)event.edit.length); + dict->SetValue("Start",(int64_t)event.edit.start); + dict->SetValue("WindowId",(int64_t)event.edit.windowID); + break; + case SDL_EventType::SDL_TEXTEDITING_EXT: + { + dict->SetValue("Text",event.editExt.text); + dict->SetValue("Length",(int64_t)event.editExt.length); + dict->SetValue("Start",(int64_t)event.editExt.start); + dict->SetValue("WindowId",(int64_t)event.editExt.windowID); + SDL_free(event.editExt.text); + } + break; + case SDL_EventType::SDL_WINDOWEVENT: + { + dict->SetValue("WindowId",(int64_t)event.window.windowID); + dict->SetValue("Event",(int64_t)event.window.event); + dict->SetValue("Data1",(int64_t)event.window.data1); + dict->SetValue("Data2",(int64_t)event.window.data2); + + } + break; + + } + ls.GetGC()->BarrierEnd(); + return dict; + } + return nullptr; + } static TObject SDL2_RenderPresent(GCList& ls, std::vector args) { TNative* renderer; @@ -36,6 +195,12 @@ namespace Tesses::CrossLang } return Undefined(); } + + static TObject SDL2_Init(GCList& ls, std::vector args) + { + return (int64_t)SDL_Init(SDL_INIT_EVERYTHING); + + } static TObject SDL2_CreateRenderer(GCList& ls, std::vector args) @@ -75,16 +240,42 @@ namespace Tesses::CrossLang #if defined(CROSSLANG_ENABLE_SDL2) GCList ls(gc); TDictionary* dict = TDictionary::Create(ls); - + dict->DeclareFunction(gc, "RenderDrawRect","Draw a rectangle using SDL",{"renderer","dictionary_with_x_y_w_h"}, SDL2_RenderDrawRect); + dict->DeclareFunction(gc, "RenderFillRect","Fill a rectangle using SDL",{"renderer","dictionary_with_x_y_w_h"}, SDL2_RenderFillRect); dict->DeclareFunction(gc, "RenderPresent","Present frame (you are finished with the frame)",{"renderer"},SDL2_RenderPresent); dict->DeclareFunction(gc, "RenderClear","Clear renderer with renderer draw color",{"renderer"},SDL2_RenderClear); dict->DeclareFunction(gc, "SetRenderDrawColor","Set SDL2 Renderer Draw Color",{"renderer","r","g","b","a"},SDL2_SetRenderDrawColor); dict->DeclareFunction(gc, "CreateWindow","Create a SDL2 Window",{"title","x","y","w","h","flags"},SDL2_CreateWindow); - dict->DeclareFunction(gc, "CreateRenderer","Create a SDL2 Renderer",{"window",""},SDL2_CreateRenderer); + dict->DeclareFunction(gc, "CreateRenderer","Create a SDL2 Renderer",{"window",""},SDL2_CreateRenderer); + dict->DeclareFunction(gc, "PollEvent", "Get events",{},SDL2_PollEvent); + dict->DeclareFunction(gc, "Init", "Init SDL2",{},SDL2_Init); + gc->BarrierBegin(); + dict->SetValue("DROPBEGIN",(int64_t)SDL_DROPBEGIN); + dict->SetValue("DROPCOMPLETE",(int64_t)SDL_DROPCOMPLETE); + dict->SetValue("DROPFILE",(int64_t)SDL_DROPFILE); + dict->SetValue("DROPTEXT",(int64_t)SDL_DROPTEXT); + dict->SetValue("MOUSEBUTTONUP",(int64_t)SDL_MOUSEBUTTONUP); + dict->SetValue("MOUSEBUTTONDOWN",(int64_t)SDL_MOUSEBUTTONDOWN); + dict->SetValue("MOUSEMOTION",(int64_t)SDL_MOUSEMOTION); + dict->SetValue("KEYUP",(int64_t)SDL_KEYUP); + dict->SetValue("KEYDOWN",(int64_t)SDL_KEYDOWN); + dict->SetValue("FINGERMOTION",(int64_t)SDL_FINGERMOTION); + dict->SetValue("FINGERUP",(int64_t)SDL_FINGERUP); + dict->SetValue("FINGERDOWN",(int64_t)SDL_FINGERDOWN); + dict->SetValue("TEXTINPUT",(int64_t)SDL_TEXTINPUT); + dict->SetValue("TEXTEDITING",(int64_t)SDL_TEXTEDITING); + dict->SetValue("TEXTEDITING_EXT",(int64_t)SDL_TEXTEDITING_EXT); + dict->SetValue("WINDOWEVENT",(int64_t)SDL_WINDOWEVENT); + dict->SetValue("QUIT",(int64_t)SDL_QUIT); + + dict->SetValue("WINDOW_RESIZABLE",(int64_t)SDL_WINDOW_RESIZABLE); + dict->SetValue("WINDOW_BORDERLESS",(int64_t)SDL_WINDOW_BORDERLESS); + dict->SetValue("WINDOW_FULLSCREEN",(int64_t)SDL_WINDOW_FULLSCREEN); + dict->SetValue("WINDOW_MAXIMIZED",(int64_t)SDL_WINDOW_MAXIMIZED); env->DeclareVariable("SDL2", dict); gc->BarrierEnd(); #endif } -} \ No newline at end of file +} diff --git a/src/types/dictionary.cpp b/src/types/dictionary.cpp index a6afad3..1ea7a53 100644 --- a/src/types/dictionary.cpp +++ b/src/types/dictionary.cpp @@ -68,7 +68,7 @@ namespace Tesses::CrossLang { { if(std::holds_alternative(value)) { - if(this->items.contains(key)) + if(this->items.count(key) > 0) this->items.erase(key); } else @@ -78,7 +78,7 @@ namespace Tesses::CrossLang { } bool TDictionary::HasValue(std::string key) { - return this->items.contains(key); + return this->items.count(key) > 0; } void TDictionary::Mark() { diff --git a/src/types/rootenvironment.cpp b/src/types/rootenvironment.cpp index ebe21f2..2117a2e 100644 --- a/src/types/rootenvironment.cpp +++ b/src/types/rootenvironment.cpp @@ -1,5 +1,6 @@ #include "CrossLang.hpp" #include +#include namespace Tesses::CrossLang { void TRootEnvironment::LoadDependency(GC* gc,Tesses::Framework::Filesystem::VFS* vfs, std::pair dep) { diff --git a/src/vm/filereader.cpp b/src/vm/filereader.cpp index f1d69c6..dc5a02d 100644 --- a/src/vm/filereader.cpp +++ b/src/vm/filereader.cpp @@ -64,7 +64,7 @@ namespace Tesses::CrossLang else{ uint8_t* buffer=new uint8_t[len]; Ensure(stream,buffer,len); - delete buffer; + delete[] buffer; } } void TFile::Ensure(Tesses::Framework::Streams::Stream* stream, uint8_t* buffer,size_t len) @@ -196,4 +196,4 @@ namespace Tesses::CrossLang } -} \ No newline at end of file +} diff --git a/src/vm/gc.cpp b/src/vm/gc.cpp index bbfbc96..68d5e80 100644 --- a/src/vm/gc.cpp +++ b/src/vm/gc.cpp @@ -4,9 +4,13 @@ #include #if defined(CROSSLANG_ENABLE_SQLITE) +extern "C" { #include "../sqlite/sqlite3.h" +} #if defined(GEKKO) -extern sqlite3_vfs *sqlite3_demovfs(void); +extern "C" { + sqlite3_vfs *sqlite3_demovfs(); +} #endif #endif using namespace Tesses::Framework::Threading; @@ -24,7 +28,7 @@ namespace Tesses::CrossLang GC::GC() { #if defined(CROSSLANG_ENABLE_SQLITE) - sqlite3_initialize(); + sqlite3_initialize(); #if defined(GEKKO) sqlite3_vfs_register(sqlite3_demovfs(),1); #endif @@ -104,15 +108,16 @@ namespace Tesses::CrossLang this_frame = system_clock::now(); if((this_frame - last_frame) > 10s) { + + last_frame = this_frame; this->Collect(); usleep(1000000); - } - + usleep(10000); } GC::Collect(); }); @@ -245,4 +250,4 @@ namespace Tesses::CrossLang this->BarrierEnd(); } -}; \ No newline at end of file +}; diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index 1bb8e23..2fd07cc 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace Tesses::CrossLang { thread_local CallStackEntry* current_function=nullptr; @@ -156,7 +157,9 @@ namespace Tesses::CrossLang { } return true; } - + else { + this->call_stack_entries.back()->Push(ls.GetGC(),Undefined()); + } } return false; } @@ -1318,7 +1321,7 @@ namespace Tesses::CrossLang { } if(key == "ToLongBits") { - cse.back()->Push(gc, std::bit_cast(number)); + cse.back()->Push(gc, *(int64_t*)&number); return false; } if(key == "Floor") @@ -1468,7 +1471,7 @@ namespace Tesses::CrossLang { } if(key == "ToDoubleBits") { - cse.back()->Push(gc,std::bit_cast(number)); + cse.back()->Push(gc,*(double*)&number); return false; } @@ -1523,6 +1526,26 @@ namespace Tesses::CrossLang { cse.back()->Push(gc, path.GetFileName()); return false; } + if(key == "GetExtension") + { + cse.back()->Push(gc, path.GetExtension()); + return false; + } + if(key == "ChangeExtension") + { + Tesses::Framework::Filesystem::VFSPath newPath = path; + std::string ext; + if(GetArgument(args,0, ext)) + { + newPath.ChangeExtension(ext); + } + else + { + newPath.RemoveExtension(); + } + cse.back()->Push(gc, newPath); + return false; + } if(key == "CollapseRelativeParents") { cse.back()->Push(gc, path.CollapseRelativeParents()); @@ -1655,21 +1678,21 @@ namespace Tesses::CrossLang { std::string oldStr; std::string newStr; - std::string str={}; + std::string _str={}; if(GetArgument(args,0,oldStr) && GetArgument(args,1,newStr)) { bool first=true; for(auto txt : Tesses::Framework::Http::HttpUtils::SplitString(str,oldStr)) { - if(!first) str.append(newStr); + if(!first) _str.append(newStr); first=false; - str.append(txt); + _str.append(txt); } } - cse.back()->Push(gc,str); + cse.back()->Push(gc,_str); return false; } @@ -1777,7 +1800,7 @@ namespace Tesses::CrossLang { TStd::RegisterDictionary(gc, rootEnv); if(myEnv->permissions.canRegisterEnv && !rootEnv->permissions.locked) - TStd::RegisterDictionary(gc, rootEnv); + TStd::RegisterEnv(gc, rootEnv); if(myEnv->permissions.canRegisterIO && !rootEnv->permissions.locked) diff --git a/winicon.ico b/winicon.ico new file mode 100755 index 0000000000000000000000000000000000000000..3fd66aed3ac39aa76f8981b19628b487e76ca6f8 GIT binary patch literal 46215 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