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 2b568df..0000000 Binary files a/icon.png and /dev/null differ 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 0000000..3fd66ae Binary files /dev/null and b/winicon.ico differ diff --git a/winicon.rc b/winicon.rc new file mode 100644 index 0000000..9ee7621 --- /dev/null +++ b/winicon.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "winicon.ico"