├── .gitignore ├── AppVeyorBuild.bat ├── AppVeyorInstall.bat ├── BUILD.txt ├── CMakeLists.txt ├── LICENSE.txt ├── README.md ├── appveyor.yml ├── src ├── duk_config.h ├── duktape.c ├── duktape.h └── main.c └── tests ├── Demo.class └── Demo.java /.gitignore: -------------------------------------------------------------------------------- 1 | /CMakeLists.txt.user 2 | /build/ 3 | -------------------------------------------------------------------------------- /AppVeyorBuild.bat: -------------------------------------------------------------------------------- 1 | echo on 2 | 3 | rem This script is used by AppVeyor to build the project. 4 | 5 | set initial_path=%path% 6 | 7 | where appveyor 8 | where cmake 9 | 10 | set version=%APPVEYOR_BUILD_VERSION:~0,-3% 11 | 12 | SET NPACKD_CL=C:\Program Files\NpackdCL 13 | 14 | set where=c:\Builds\exe-proxy-32-minsizerel 15 | mkdir %where% 16 | cd %where% 17 | set path=C:\msys64\mingw32\bin;C:\Program Files (x86)\CMake\bin 18 | cmake C:\projects\exe-proxy -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=MinSizeRel -DWITH_JAVASCRIPT=OFF 19 | if %errorlevel% neq 0 exit /b %errorlevel% 20 | mingw32-make.exe -j 2 21 | if %errorlevel% neq 0 exit /b %errorlevel% 22 | C:\msys64\mingw32\bin\strip exeproxy.exe 23 | if %errorlevel% neq 0 exit /b %errorlevel% 24 | 25 | set where=c:\Builds\exe-proxy-32-minsizerel-js 26 | mkdir %where% 27 | cd %where% 28 | set path=C:\msys64\mingw32\bin;C:\Program Files (x86)\CMake\bin 29 | cmake C:\projects\exe-proxy -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=MinSizeRel -DWITH_JAVASCRIPT=ON 30 | if %errorlevel% neq 0 exit /b %errorlevel% 31 | mingw32-make.exe -j 2 32 | if %errorlevel% neq 0 exit /b %errorlevel% 33 | C:\msys64\mingw32\bin\strip exeproxy.exe 34 | if %errorlevel% neq 0 exit /b %errorlevel% 35 | 36 | set where=c:\Builds\exe-proxy-64-minsizerel 37 | mkdir %where% 38 | cd %where% 39 | set path=C:\msys64\mingw64\bin;C:\Program Files (x86)\CMake\bin 40 | cmake C:\projects\exe-proxy -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=MinSizeRel -DWITH_JAVASCRIPT=OFF 41 | if %errorlevel% neq 0 exit /b %errorlevel% 42 | mingw32-make.exe -j 2 43 | if %errorlevel% neq 0 exit /b %errorlevel% 44 | C:\msys64\mingw64\bin\strip exeproxy.exe 45 | if %errorlevel% neq 0 exit /b %errorlevel% 46 | 47 | set where=c:\Builds\exe-proxy-64-minsizerel-js 48 | mkdir %where% 49 | cd %where% 50 | set path=C:\msys64\mingw64\bin;C:\Program Files (x86)\CMake\bin 51 | cmake C:\projects\exe-proxy -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=MinSizeRel -DWITH_JAVASCRIPT=ON 52 | if %errorlevel% neq 0 exit /b %errorlevel% 53 | mingw32-make.exe -j 2 54 | if %errorlevel% neq 0 exit /b %errorlevel% 55 | C:\msys64\mingw64\bin\strip exeproxy.exe 56 | if %errorlevel% neq 0 exit /b %errorlevel% 57 | 58 | set where=c:\release 59 | mkdir %where% 60 | cd %where% 61 | copy c:\Builds\exe-proxy-32-minsizerel\exeproxy.exe exeproxy.exe 62 | if %errorlevel% neq 0 exit /b %errorlevel% 63 | copy c:\Builds\exe-proxy-32-minsizerel-js\exeproxy.exe exeproxy-js.exe 64 | if %errorlevel% neq 0 exit /b %errorlevel% 65 | copy c:\Builds\exe-proxy-64-minsizerel\exeproxy.exe exeproxy64.exe 66 | if %errorlevel% neq 0 exit /b %errorlevel% 67 | copy c:\Builds\exe-proxy-64-minsizerel-js\exeproxy.exe exeproxy-js64.exe 68 | if %errorlevel% neq 0 exit /b %errorlevel% 69 | copy "C:\projects\exe-proxy\README.md" . 70 | if %errorlevel% neq 0 exit /b %errorlevel% 71 | copy "C:\projects\exe-proxy\LICENSE.txt" . 72 | if %errorlevel% neq 0 exit /b %errorlevel% 73 | mkdir C:\Artifacts 74 | if %errorlevel% neq 0 exit /b %errorlevel% 75 | set path=%initial_path% 76 | 7z a C:\Artifacts\exeproxy-%version%.zip * -mx9 77 | if %errorlevel% neq 0 exit /b %errorlevel% 78 | 79 | appveyor PushArtifact C:\Artifacts\exeproxy-%version%.zip 80 | if %errorlevel% neq 0 exit /b %errorlevel% 81 | 82 | 83 | -------------------------------------------------------------------------------- /AppVeyorInstall.bat: -------------------------------------------------------------------------------- 1 | 2 | echo on 3 | 4 | rem This script is used by AppVeyor automatic builds to install the necessary 5 | rem software dependencies. 6 | 7 | msiexec.exe /qn /i https://github.com/tim-lebedkov/npackd-cpp/releases/download/version_1.25/NpackdCL64-1.25.0.msi 8 | if %errorlevel% neq 0 exit /b %errorlevel% 9 | 10 | SET NPACKD_CL=C:\Program Files\NpackdCL 11 | "%npackd_cl%\ncl" set-repo -u https://www.npackd.org/rep/recent-xml -u https://www.npackd.org/rep/xml?tag=stable -u https://www.npackd.org/rep/xml?tag=stable64 -u https://www.npackd.org/rep/xml?tag=libs 12 | if %errorlevel% neq 0 exit /b %errorlevel% 13 | 14 | "%npackd_cl%\ncl" detect 15 | if %errorlevel% neq 0 exit /b %errorlevel% 16 | 17 | "%npackd_cl%\ncl" set-install-dir -f "C:\Program Files" 18 | if %errorlevel% neq 0 exit /b %errorlevel% 19 | 20 | rem Python will be detected, but needs NpackdCL 21 | "%npackd_cl%\ncl" add -p com.googlecode.windows-package-manager.NpackdCL 22 | if %errorlevel% neq 0 exit /b %errorlevel% 23 | 24 | "%npackd_cl%\ncl" add -p com.oracle.JDK64 -p org.7-zip.SevenZIP -r [9,20) 25 | if %errorlevel% neq 0 exit /b %errorlevel% 26 | 27 | rem update all packages to the newest versions 28 | rem MSYS2 repositories are currently not available 29 | rem C:\msys64\usr\bin\pacman -Syu --noconfirm 30 | rem C:\msys64\usr\bin\pacman -Syu --noconfirm 31 | 32 | -------------------------------------------------------------------------------- /BUILD.txt: -------------------------------------------------------------------------------- 1 | How to build 2 | ============ 3 | 4 | - install https://npackd.appspot.com/p/npackd-dev-i686-w64 for 32 bit builds or 5 | https://npackd.appspot.com/p/npackd-dev-x86_64-w64 for 64 bit builds from 6 | the libraries repository (see http://code.google.com/p/windows-package-manager/wiki/LibrariesRepository) 7 | 8 | - cd wpmcpp 9 | - mkdir build 10 | - cd build 11 | - set path=C:\Program Files\MinGW-w64_x86_64_SEH_POSIX_threads\bin;C:\Program Files\CMake\bin 12 | - set cmake_prefix_path=C:\Program Files\MinGW-w64_x86_64_SEH_POSIX_threads\x86_64-w64-mingw32 13 | - cmake -G "MinGW Makefiles" ..\ -DCMAKE_INSTALL_PREFIX=C:\Users\username\Documents\npackd-cpp\wpmcpp\install 14 | - mingw32-make.exe 15 | 16 | 17 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.7 FATAL_ERROR) 2 | 3 | project(exeproxy C) 4 | 5 | option(WITH_JAVASCRIPT "Build with JavaScript support" ON) 6 | 7 | if(WITH_JAVASCRIPT) 8 | add_definitions(-DWITH_JAVASCRIPT) 9 | endif() 10 | 11 | set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) 12 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/../cmake/") 13 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mconsole -static -municode") 14 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map,${PROJECT_NAME}.map") 15 | 16 | if(WIN32) 17 | set(CMAKE_USE_RELATIVE_PATHS true) 18 | set(CMAKE_SUPPRESS_REGENERATION true) 19 | endif() 20 | 21 | include(CheckTypeSize) 22 | CHECK_TYPE_SIZE("void*" OSMSCOUT_PTR_SIZE BUILTIN_TYPES_ONLY) 23 | if(OSMSCOUT_PTR_SIZE EQUAL 8) 24 | set(NPACKD_PLATFORM_X64 TRUE) 25 | set(BITS 64) 26 | else() 27 | set(NPACKD_PLATFORM_X64 FALSE) 28 | set(BITS 32) 29 | endif() 30 | 31 | add_definitions(-DUNICODE -D_UNICODE) 32 | 33 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static-libgcc -g -Os" ) 34 | 35 | include(CheckCXXCompilerFlag) 36 | 37 | # compiler warnings 38 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX OR CMAKE_COMPILER_IS_GNUCC) 39 | set(NPACKD_WARNING_FLAGS "-Wall -Winit-self -Wwrite-strings -Wextra -Wno-long-long -Wno-overloaded-virtual -Wno-missing-field-initializers -Wno-unused-parameter -Wno-unknown-pragmas") 40 | if(EMSCRIPTEN) 41 | set(NPACKD_WARNING_FLAGS "${NPACKD_WARNING_FLAGS} -Wno-warn-absolute-paths") 42 | elseif(NOT APPLE) 43 | set(NPACKD_WARNING_FLAGS "${NPACKD_WARNING_FLAGS} -Wno-unused-but-set-parameter") 44 | endif() 45 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${NPACKD_WARNING_FLAGS}") 46 | endif() 47 | 48 | # Reads the version number from Version.txt 49 | # 50 | # txt: path to the Version.txt 51 | macro(readVersion txt) 52 | file(STRINGS ${txt} READ_BUILD_NUMBER REGEX "version:.+" LIMIT_COUNT 1) 53 | 54 | message(STATUS "Read build number ${READ_BUILD_NUMBER}") 55 | 56 | string(REGEX MATCHALL "[0-9]+" _versionComponents "${READ_BUILD_NUMBER}") 57 | list(LENGTH _versionComponents _len) 58 | if (${_len} GREATER 0) 59 | list(GET _versionComponents 0 NPACKD_VERSION_MAJOR) 60 | else() 61 | set(NPACKD_VERSION_MAJOR 0) 62 | endif() 63 | if (${_len} GREATER 1) 64 | list(GET _versionComponents 1 NPACKD_VERSION_MINOR) 65 | else() 66 | set(NPACKD_VERSION_MINOR 0) 67 | endif() 68 | if (${_len} GREATER 2) 69 | list(GET _versionComponents 2 NPACKD_VERSION_PATCH) 70 | else() 71 | set(NPACKD_VERSION_PATCH 0) 72 | endif() 73 | if (${_len} GREATER 3) 74 | list(GET _versionComponents 3 NPACKD_VERSION_TWEAK) 75 | else() 76 | set(NPACKD_VERSION_TWEAK 0) 77 | endif() 78 | 79 | set(NPACKD_VERSION "${NPACKD_VERSION_MAJOR}.${NPACKD_VERSION_MINOR}.${NPACKD_VERSION_PATCH}.${NPACKD_VERSION_TWEAK}") 80 | 81 | message(STATUS "Build npackd v${NPACKD_VERSION}") 82 | endmacro(readVersion) 83 | 84 | if(MSVC) 85 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:fast /wd4251") 86 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Oi") 87 | if(CMAKE_CL_64) 88 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj") 89 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /bigobj") 90 | endif() 91 | if(MSVC_VERSION GREATER 1500 OR MSVC_VERSION EQUAL 1500) 92 | option(NPACKD_BUILD_MSVC_MP "Enable build with multiple processes in Visual Studio" TRUE) 93 | else() 94 | set(NPACKD_BUILD_MSVC_MP FALSE CACHE BOOL "Compiler option /MP requires at least Visual Studio 2008 (VS9) or newer" FORCE) 95 | endif() 96 | if(NPACKD_BUILD_MSVC_MP) 97 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") 98 | endif() 99 | add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DDLL_EXPORT -DUNICODE -D_UNICODE) 100 | endif() 101 | 102 | # Vista 103 | add_definitions(-D_WIN32_WINNT=0x0600) 104 | add_definitions(-DWINVER=0x0600) 105 | 106 | if(MINGW) 107 | if(NOT NPACKD_PLATFORM_X64) 108 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686") 109 | endif () 110 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -fno-tree-slp-vectorize -Wno-error=cast-qual -Wno-unused-local-typedefs") 111 | endif() 112 | 113 | if((CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX OR CMAKE_COMPILER_IS_GNUCC) AND NOT MINGW) 114 | add_definitions( -Wall -pedantic -fPIC ) 115 | check_cxx_compiler_flag(-fvisibility=hidden NPACKD_GCC_VISIBILITY) 116 | if(NPACKD_GCC_VISIBILITY) 117 | execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE NPACKD_GCC_VERSION) 118 | message(STATUS "Detected g++ ${NPACKD_GCC_VERSION}") 119 | message(STATUS "Enabling GCC visibility flags") 120 | set(NPACKD_GCC_VISIBILITY_FLAGS "-fvisibility=hidden") 121 | set(XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "YES") 122 | string(TOLOWER "${CMAKE_BUILD_TYPE}" NPACKD_BUILD_TYPE) 123 | if(NPACKD_BUILD_TYPE STREQUAL "debug" AND NPACKD_GCC_VERSION VERSION_LESS "4.2") 124 | message(STATUS "Skipping -fvisibility-inlines-hidden due to possible bug in g++ < 4.2") 125 | else() 126 | if(APPLE) 127 | message(STATUS "Skipping -fvisibility-inlines-hidden due to linker issues") 128 | set(XCODE_ATTRIBUTE_GCC_INLINES_ARE_PRIVATE_EXTERN[arch=x86_64] "YES") 129 | else() 130 | set(NPACKD_VISIBILITY_FLAGS "${NPACKD_GCC_VISIBILITY_FLAGS} -fvisibility-inlines-hidden") 131 | set(XCODE_ATTRIBUTE_GCC_INLINES_ARE_PRIVATE_EXTERN "YES") 132 | endif() 133 | endif() 134 | endif() 135 | if(NPACKD_PLATFORM_X64 AND NOT APPLE) 136 | add_definitions(-fPIC) 137 | endif() 138 | endif() 139 | 140 | # prefer static libraries if making import tool 141 | if(BUILD_IMPORT_TOOL_FOR_DISTRIBUTION AND (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX OR CMAKE_COMPILER_IS_GNUCC)) 142 | SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) 143 | endif() 144 | 145 | # postfix for debug builds 146 | if(NOT APPLE) 147 | set(CMAKE_DEBUG_POSTFIX "d") 148 | endif () 149 | 150 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 151 | 152 | if(WITH_JAVASCRIPT) 153 | set(EXEPROXY_SOURCES 154 | src/main.c 155 | src/duktape.c 156 | ) 157 | set(EXEPROXY_HEADERS 158 | src/duk_config.h 159 | src/duktape.h 160 | ) 161 | else() 162 | set(EXEPROXY_SOURCES 163 | src/main.c 164 | ) 165 | set(EXEPROXY_HEADERS "") 166 | endif() 167 | 168 | 169 | set(OUTPUT_FILE_NAME "exeproxy.exe") 170 | 171 | add_executable(exeproxy ${EXEPROXY_SOURCES}) 172 | 173 | set_property(TARGET exeproxy PROPERTY C_STANDARD 11) 174 | 175 | target_link_libraries(exeproxy shell32) 176 | target_include_directories(exeproxy PRIVATE "C:/Program Files/JDK_64_bit/include" "C:/Program Files/JDK_64_bit/include/win32") 177 | 178 | target_compile_definitions(exeproxy PRIVATE -D NPACKD_VERSION="${NPACKD_VERSION}") 179 | 180 | install(TARGETS exeproxy DESTINATION ${CMAKE_INSTALL_PREFIX}) 181 | install(FILES LICENSE.txt DESTINATION ${CMAKE_INSTALL_PREFIX}) 182 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EXE Proxy 2 | 3 | This program serves as a proxy for another command line program. There 4 | are two versions of the program available: 5 | - simple (20 KB binary) 6 | - with JavaScript (270 KB binary) 7 | 8 | EXE Proxy uses semantic versioning (http://semver.org/). The versions before 9 | 1.0 will change the interface incompatibly so please use an exact version 10 | number as dependency. 11 | 12 | Usage scenarios: 13 | - enable access to a command line program under another (possibly shorter) name. 14 | - store many copies of EXE proxy in one directory pointing to command line 15 | utilities on the computer and 16 | adding only this directory to the PATH environment variable. This would avoid 17 | reaching the maximum length for PATH (2048 characters) and making it very 18 | complicated while still be able to run all programs without specifying the 19 | directory where they reside. 20 | - make a GUI executable usable from the command line too. 21 | Normally cmd.exe does not wait for 22 | GUI executables to end but returns immediately. EXE Proxy does not differentiate 23 | between GUI and non-GUI programs and always waits for the target process to end. 24 | - launcher for Java or other programming languages that do not create executables 25 | by default. 26 | - writing Windows service in Java 27 | 28 | 1. The simple version passes all arguments as-is to the target program. 29 | The return code of the target program will be returned as exit code by EXE Proxy. 30 | The path and file name of the target executable are 31 | stored directly as a resource in a copy of the EXE Proxy. During the start 32 | EXE Proxy reads the resource string and uses it to find the target executable. 33 | The resource string can either contain an absolute file name or a file name 34 | without slashes or backslashes. In the latter case the target executable should 35 | reside in the same directory as the EXE Proxy itself. 36 | 37 | In order to change the target executable resource entry you could start the EXE 38 | Proxy with the parameter "exeproxy-copy": 39 | 40 | ```bat 41 | exeproxy.exe exeproxy-copy [--copy-icons] [--copy-version] [--copy-manifest] 42 | ``` 43 | 44 | The second parameter should be the name of the output exe file where a copy of 45 | the EXE Proxy will be stored. The third parameter should either contain an 46 | absolute path to the target executable or the name of the target executable 47 | without slashes or backslashes if the target executable resides in the same 48 | directory as the EXE Proxy. 49 | 50 | If the parameter --copy-icons is present, all icons and icon groups are copied 51 | making the executable icon look exactly as in the target executable. 52 | 53 | If the parameter --copy-version is present, the version information is copied. 54 | 55 | If the parameter --copy-manifest is present, the application XML manifest is copied. 56 | 57 | 2. The second version reads the JavaScript from the file with the same name as 58 | the executable and the extension .js and executes it using the Duktape library 59 | (https://duktape.org/). 60 | 61 | You can still use the "exeproxy-copy" command from 62 | above to embedd the icons and version information from the target executable, 63 | but it is not executed automatically (if not specified in the JavaScript). 64 | 65 | You can create a Java based Windows service using JNA. See 66 | https://github.com/java-native-access/jna/tree/master/contrib/ntservice for 67 | more details. The Windows command line utility "sc.exe" can be used to register 68 | and unregister the service. 69 | 70 | In the JavaScript code are also defined: 71 | - os.totalmem() - total physical system memory in bytes 72 | - process.argv - executable parameters as an array of strings. The value at the index 0 is the name of the executable used on the command line. 73 | - process.argv0 - executable name including path 74 | - child_process.execSync(command) - executes a program and returns the exit code 75 | - process.exit(ec) - exits the program with the specified exit code 76 | - process.loadJVM(options) - start Java Virtual Machine in the current process 77 | - options.jvmDLL - path to the jvm.dll 78 | - options.jvmOptions - JVM options (the same as arguments for java.exe) as an array of strings 79 | See https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/invocation.html for more details. 80 | - process.javaCallMain(className, args) - execute "main" method in the specified Java class. The JVM must be loaded first. 81 | - className - name of the main class 82 | - args - argument for "public static void main(String[])" as an array of strings 83 | 84 | Example JavaScript file: 85 | 86 | ```JavaScript 87 | console.log('os.totalmem = ' + os.totalmem()); 88 | console.log('exe = ' + process.argv0); 89 | 90 | console.log(process.argv.length); 91 | for (var i = 0; i < process.argv.length; i++) { 92 | console.log("JS argument " + i + " = " + process.argv[i]); 93 | } 94 | 95 | process.loadJVM({ 96 | jvmDLL: "C:\\Program Files (x86)\\Java\\jre7\\bin\\client\\jvm.dll", 97 | jvmOptions: ["-Djava.class.path=C:\\Users\\IEUser\\Documents\\exe-proxy"], 98 | }); 99 | 100 | process.javaCallMain("tests.Demo", ["first", "second"]); 101 | 102 | var ec = child_process.execSync("C:\\msys64\\mingw32\\bin\\addr2line.exe params"); 103 | console.log('exit code = ' + ec); 104 | 105 | process.exit(200); 106 | ``` 107 | 108 | 109 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 0.5.{build} 2 | install: 3 | - cmd.exe /C AppVeyorInstall.bat 4 | build_script: 5 | - cmd.exe /C AppVeyorBuild.bat 6 | deploy: 7 | description: 'Automated release' 8 | provider: GitHub 9 | auth_token: 10 | secure: TZRXNYgUHwdfwkAfUimkaegIlCs5+UrAKl484ZCxAgvT5TmqA8TKd9nadxXHXDA0 11 | draft: true 12 | on: 13 | appveyor_repo_tag: true 14 | -------------------------------------------------------------------------------- /src/duktape.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Duktape public API for Duktape 2.5.0. 3 | * 4 | * See the API reference for documentation on call semantics. The exposed, 5 | * supported API is between the "BEGIN PUBLIC API" and "END PUBLIC API" 6 | * comments. Other parts of the header are Duktape internal and related to 7 | * e.g. platform/compiler/feature detection. 8 | * 9 | * Git commit 6001888049cb42656f8649db020e804bcdeca6a7 (v2.5.0). 10 | * Git branch master. 11 | * 12 | * See Duktape AUTHORS.rst and LICENSE.txt for copyright and 13 | * licensing information. 14 | */ 15 | 16 | /* LICENSE.txt */ 17 | /* 18 | * =============== 19 | * Duktape license 20 | * =============== 21 | * 22 | * (http://opensource.org/licenses/MIT) 23 | * 24 | * Copyright (c) 2013-2019 by Duktape authors (see AUTHORS.rst) 25 | * 26 | * Permission is hereby granted, free of charge, to any person obtaining a copy 27 | * of this software and associated documentation files (the "Software"), to deal 28 | * in the Software without restriction, including without limitation the rights 29 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 30 | * copies of the Software, and to permit persons to whom the Software is 31 | * furnished to do so, subject to the following conditions: 32 | * 33 | * The above copyright notice and this permission notice shall be included in 34 | * all copies or substantial portions of the Software. 35 | * 36 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 37 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 38 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 39 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 40 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 41 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 42 | * THE SOFTWARE. 43 | */ 44 | 45 | /* AUTHORS.rst */ 46 | /* 47 | * =============== 48 | * Duktape authors 49 | * =============== 50 | * 51 | * Copyright 52 | * ========= 53 | * 54 | * Duktape copyrights are held by its authors. Each author has a copyright 55 | * to their contribution, and agrees to irrevocably license the contribution 56 | * under the Duktape ``LICENSE.txt``. 57 | * 58 | * Authors 59 | * ======= 60 | * 61 | * Please include an e-mail address, a link to your GitHub profile, or something 62 | * similar to allow your contribution to be identified accurately. 63 | * 64 | * The following people have contributed code, website contents, or Wiki contents, 65 | * and agreed to irrevocably license their contributions under the Duktape 66 | * ``LICENSE.txt`` (in order of appearance): 67 | * 68 | * * Sami Vaarala 69 | * * Niki Dobrev 70 | * * Andreas \u00d6man 71 | * * L\u00e1szl\u00f3 Lang\u00f3 72 | * * Legimet 73 | * * Karl Skomski 74 | * * Bruce Pascoe 75 | * * Ren\u00e9 Hollander 76 | * * Julien Hamaide (https://github.com/crazyjul) 77 | * * Sebastian G\u00f6tte (https://github.com/jaseg) 78 | * * Tomasz Magulski (https://github.com/magul) 79 | * * \D. Bohdan (https://github.com/dbohdan) 80 | * * Ond\u0159ej Jirman (https://github.com/megous) 81 | * * Sa\u00fal Ibarra Corretg\u00e9 82 | * * Jeremy HU 83 | * * Ole Andr\u00e9 Vadla Ravn\u00e5s (https://github.com/oleavr) 84 | * * Harold Brenes (https://github.com/harold-b) 85 | * * Oliver Crow (https://github.com/ocrow) 86 | * * Jakub Ch\u0142api\u0144ski (https://github.com/jchlapinski) 87 | * * Brett Vickers (https://github.com/beevik) 88 | * * Dominik Okwieka (https://github.com/okitec) 89 | * * Remko Tron\u00e7on (https://el-tramo.be) 90 | * * Romero Malaquias (rbsm@ic.ufal.br) 91 | * * Michael Drake 92 | * * Steven Don (https://github.com/shdon) 93 | * * Simon Stone (https://github.com/sstone1) 94 | * * \J. McC. (https://github.com/jmhmccr) 95 | * * Jakub Nowakowski (https://github.com/jimvonmoon) 96 | * * Tommy Nguyen (https://github.com/tn0502) 97 | * * Fabrice Fontaine (https://github.com/ffontaine) 98 | * * Christopher Hiller (https://github.com/boneskull) 99 | * * Gonzalo Diethelm (https://github.com/gonzus) 100 | * * Michal Kasperek (https://github.com/michalkas) 101 | * * Andrew Janke (https://github.com/apjanke) 102 | * * Steve Fan (https://github.com/stevefan1999) 103 | * * Edward Betts (https://github.com/edwardbetts) 104 | * * Ozhan Duz (https://github.com/webfolderio) 105 | * * Akos Kiss (https://github.com/akosthekiss) 106 | * * TheBrokenRail (https://github.com/TheBrokenRail) 107 | * * Jesse Doyle (https://github.com/jessedoyle) 108 | * * Gero Kuehn (https://github.com/dc6jgk) 109 | * * James Swift (https://github.com/phraemer) 110 | * * Luis de Bethencourt (https://github.com/luisbg) 111 | * * Ian Whyman (https://github.com/v00d00) 112 | * * Rick Sayre (https://github.com/whorfin) 113 | * 114 | * Other contributions 115 | * =================== 116 | * 117 | * The following people have contributed something other than code (e.g. reported 118 | * bugs, provided ideas, etc; roughly in order of appearance): 119 | * 120 | * * Greg Burns 121 | * * Anthony Rabine 122 | * * Carlos Costa 123 | * * Aur\u00e9lien Bouilland 124 | * * Preet Desai (Pris Matic) 125 | * * judofyr (http://www.reddit.com/user/judofyr) 126 | * * Jason Woofenden 127 | * * Micha\u0142 Przyby\u015b 128 | * * Anthony Howe 129 | * * Conrad Pankoff 130 | * * Jim Schimpf 131 | * * Rajaran Gaunker (https://github.com/zimbabao) 132 | * * Andreas \u00d6man 133 | * * Doug Sanden 134 | * * Josh Engebretson (https://github.com/JoshEngebretson) 135 | * * Remo Eichenberger (https://github.com/remoe) 136 | * * Mamod Mehyar (https://github.com/mamod) 137 | * * David Demelier (https://github.com/markand) 138 | * * Tim Caswell (https://github.com/creationix) 139 | * * Mitchell Blank Jr (https://github.com/mitchblank) 140 | * * https://github.com/yushli 141 | * * Seo Sanghyeon (https://github.com/sanxiyn) 142 | * * Han ChoongWoo (https://github.com/tunz) 143 | * * Joshua Peek (https://github.com/josh) 144 | * * Bruce E. Pascoe (https://github.com/fatcerberus) 145 | * * https://github.com/Kelledin 146 | * * https://github.com/sstruchtrup 147 | * * Michael Drake (https://github.com/tlsa) 148 | * * https://github.com/chris-y 149 | * * Laurent Zubiaur (https://github.com/lzubiaur) 150 | * * Neil Kolban (https://github.com/nkolban) 151 | * * Wilhelm Wanecek (https://github.com/wanecek) 152 | * * Andrew Janke (https://github.com/apjanke) 153 | * * Unamer (https://github.com/unamer) 154 | * * Karl Dahlke (eklhad@gmail.com) 155 | * 156 | * If you are accidentally missing from this list, send me an e-mail 157 | * (``sami.vaarala@iki.fi``) and I'll fix the omission. 158 | */ 159 | 160 | #if !defined(DUKTAPE_H_INCLUDED) 161 | #define DUKTAPE_H_INCLUDED 162 | 163 | #define DUK_SINGLE_FILE 164 | 165 | /* 166 | * BEGIN PUBLIC API 167 | */ 168 | 169 | /* 170 | * Version and Git commit identification 171 | */ 172 | 173 | /* Duktape version, (major * 10000) + (minor * 100) + patch. Allows C code 174 | * to #if (DUK_VERSION >= NNN) against Duktape API version. The same value 175 | * is also available to ECMAScript code in Duktape.version. Unofficial 176 | * development snapshots have 99 for patch level (e.g. 0.10.99 would be a 177 | * development version after 0.10.0 but before the next official release). 178 | */ 179 | #define DUK_VERSION 20500L 180 | 181 | /* Git commit, describe, and branch for Duktape build. Useful for 182 | * non-official snapshot builds so that application code can easily log 183 | * which Duktape snapshot was used. Not available in the ECMAScript 184 | * environment. 185 | */ 186 | #define DUK_GIT_COMMIT "6001888049cb42656f8649db020e804bcdeca6a7" 187 | #define DUK_GIT_DESCRIBE "v2.5.0" 188 | #define DUK_GIT_BRANCH "master" 189 | 190 | /* External duk_config.h provides platform/compiler/OS dependent 191 | * typedefs and macros, and DUK_USE_xxx config options so that 192 | * the rest of Duktape doesn't need to do any feature detection. 193 | * DUK_VERSION is defined before including so that configuration 194 | * snippets can react to it. 195 | */ 196 | #include "duk_config.h" 197 | 198 | /* 199 | * Avoid C++ name mangling 200 | */ 201 | 202 | #if defined(__cplusplus) 203 | extern "C" { 204 | #endif 205 | 206 | /* 207 | * Some defines forwarded from feature detection 208 | */ 209 | 210 | #undef DUK_API_VARIADIC_MACROS 211 | #if defined(DUK_USE_VARIADIC_MACROS) 212 | #define DUK_API_VARIADIC_MACROS 213 | #endif 214 | 215 | #define DUK_API_NORETURN(decl) DUK_NORETURN(decl) 216 | 217 | /* 218 | * Public API specific typedefs 219 | * 220 | * Many types are wrapped by Duktape for portability to rare platforms 221 | * where e.g. 'int' is a 16-bit type. See practical typing discussion 222 | * in Duktape web documentation. 223 | */ 224 | 225 | struct duk_thread_state; 226 | struct duk_memory_functions; 227 | struct duk_function_list_entry; 228 | struct duk_number_list_entry; 229 | struct duk_time_components; 230 | 231 | /* duk_context is now defined in duk_config.h because it may also be 232 | * referenced there by prototypes. 233 | */ 234 | typedef struct duk_thread_state duk_thread_state; 235 | typedef struct duk_memory_functions duk_memory_functions; 236 | typedef struct duk_function_list_entry duk_function_list_entry; 237 | typedef struct duk_number_list_entry duk_number_list_entry; 238 | typedef struct duk_time_components duk_time_components; 239 | 240 | typedef duk_ret_t (*duk_c_function)(duk_context *ctx); 241 | typedef void *(*duk_alloc_function) (void *udata, duk_size_t size); 242 | typedef void *(*duk_realloc_function) (void *udata, void *ptr, duk_size_t size); 243 | typedef void (*duk_free_function) (void *udata, void *ptr); 244 | typedef void (*duk_fatal_function) (void *udata, const char *msg); 245 | typedef void (*duk_decode_char_function) (void *udata, duk_codepoint_t codepoint); 246 | typedef duk_codepoint_t (*duk_map_char_function) (void *udata, duk_codepoint_t codepoint); 247 | typedef duk_ret_t (*duk_safe_call_function) (duk_context *ctx, void *udata); 248 | typedef duk_size_t (*duk_debug_read_function) (void *udata, char *buffer, duk_size_t length); 249 | typedef duk_size_t (*duk_debug_write_function) (void *udata, const char *buffer, duk_size_t length); 250 | typedef duk_size_t (*duk_debug_peek_function) (void *udata); 251 | typedef void (*duk_debug_read_flush_function) (void *udata); 252 | typedef void (*duk_debug_write_flush_function) (void *udata); 253 | typedef duk_idx_t (*duk_debug_request_function) (duk_context *ctx, void *udata, duk_idx_t nvalues); 254 | typedef void (*duk_debug_detached_function) (duk_context *ctx, void *udata); 255 | 256 | struct duk_thread_state { 257 | /* XXX: Enough space to hold internal suspend/resume structure. 258 | * This is rather awkward and to be fixed when the internal 259 | * structure is visible for the public API header. 260 | */ 261 | char data[128]; 262 | }; 263 | 264 | struct duk_memory_functions { 265 | duk_alloc_function alloc_func; 266 | duk_realloc_function realloc_func; 267 | duk_free_function free_func; 268 | void *udata; 269 | }; 270 | 271 | struct duk_function_list_entry { 272 | const char *key; 273 | duk_c_function value; 274 | duk_idx_t nargs; 275 | }; 276 | 277 | struct duk_number_list_entry { 278 | const char *key; 279 | duk_double_t value; 280 | }; 281 | 282 | struct duk_time_components { 283 | duk_double_t year; /* year, e.g. 2016, ECMAScript year range */ 284 | duk_double_t month; /* month: 1-12 */ 285 | duk_double_t day; /* day: 1-31 */ 286 | duk_double_t hours; /* hour: 0-59 */ 287 | duk_double_t minutes; /* minute: 0-59 */ 288 | duk_double_t seconds; /* second: 0-59 (in POSIX time no leap second) */ 289 | duk_double_t milliseconds; /* may contain sub-millisecond fractions */ 290 | duk_double_t weekday; /* weekday: 0-6, 0=Sunday, 1=Monday, ..., 6=Saturday */ 291 | }; 292 | 293 | /* 294 | * Constants 295 | */ 296 | 297 | /* Duktape debug protocol version used by this build. */ 298 | #define DUK_DEBUG_PROTOCOL_VERSION 2 299 | 300 | /* Used to represent invalid index; if caller uses this without checking, 301 | * this index will map to a non-existent stack entry. Also used in some 302 | * API calls as a marker to denote "no value". 303 | */ 304 | #define DUK_INVALID_INDEX DUK_IDX_MIN 305 | 306 | /* Indicates that a native function does not have a fixed number of args, 307 | * and the argument stack should not be capped/extended at all. 308 | */ 309 | #define DUK_VARARGS ((duk_int_t) (-1)) 310 | 311 | /* Number of value stack entries (in addition to actual call arguments) 312 | * guaranteed to be allocated on entry to a Duktape/C function. 313 | */ 314 | #define DUK_API_ENTRY_STACK 64U 315 | 316 | /* Value types, used by e.g. duk_get_type() */ 317 | #define DUK_TYPE_MIN 0U 318 | #define DUK_TYPE_NONE 0U /* no value, e.g. invalid index */ 319 | #define DUK_TYPE_UNDEFINED 1U /* ECMAScript undefined */ 320 | #define DUK_TYPE_NULL 2U /* ECMAScript null */ 321 | #define DUK_TYPE_BOOLEAN 3U /* ECMAScript boolean: 0 or 1 */ 322 | #define DUK_TYPE_NUMBER 4U /* ECMAScript number: double */ 323 | #define DUK_TYPE_STRING 5U /* ECMAScript string: CESU-8 / extended UTF-8 encoded */ 324 | #define DUK_TYPE_OBJECT 6U /* ECMAScript object: includes objects, arrays, functions, threads */ 325 | #define DUK_TYPE_BUFFER 7U /* fixed or dynamic, garbage collected byte buffer */ 326 | #define DUK_TYPE_POINTER 8U /* raw void pointer */ 327 | #define DUK_TYPE_LIGHTFUNC 9U /* lightweight function pointer */ 328 | #define DUK_TYPE_MAX 9U 329 | 330 | /* Value mask types, used by e.g. duk_get_type_mask() */ 331 | #define DUK_TYPE_MASK_NONE (1U << DUK_TYPE_NONE) 332 | #define DUK_TYPE_MASK_UNDEFINED (1U << DUK_TYPE_UNDEFINED) 333 | #define DUK_TYPE_MASK_NULL (1U << DUK_TYPE_NULL) 334 | #define DUK_TYPE_MASK_BOOLEAN (1U << DUK_TYPE_BOOLEAN) 335 | #define DUK_TYPE_MASK_NUMBER (1U << DUK_TYPE_NUMBER) 336 | #define DUK_TYPE_MASK_STRING (1U << DUK_TYPE_STRING) 337 | #define DUK_TYPE_MASK_OBJECT (1U << DUK_TYPE_OBJECT) 338 | #define DUK_TYPE_MASK_BUFFER (1U << DUK_TYPE_BUFFER) 339 | #define DUK_TYPE_MASK_POINTER (1U << DUK_TYPE_POINTER) 340 | #define DUK_TYPE_MASK_LIGHTFUNC (1U << DUK_TYPE_LIGHTFUNC) 341 | #define DUK_TYPE_MASK_THROW (1U << 10) /* internal flag value: throw if mask doesn't match */ 342 | #define DUK_TYPE_MASK_PROMOTE (1U << 11) /* internal flag value: promote to object if mask matches */ 343 | 344 | /* Coercion hints */ 345 | #define DUK_HINT_NONE 0 /* prefer number, unless input is a Date, in which 346 | * case prefer string (E5 Section 8.12.8) 347 | */ 348 | #define DUK_HINT_STRING 1 /* prefer string */ 349 | #define DUK_HINT_NUMBER 2 /* prefer number */ 350 | 351 | /* Enumeration flags for duk_enum() */ 352 | #define DUK_ENUM_INCLUDE_NONENUMERABLE (1U << 0) /* enumerate non-numerable properties in addition to enumerable */ 353 | #define DUK_ENUM_INCLUDE_HIDDEN (1U << 1) /* enumerate hidden symbols too (in Duktape 1.x called internal properties) */ 354 | #define DUK_ENUM_INCLUDE_SYMBOLS (1U << 2) /* enumerate symbols */ 355 | #define DUK_ENUM_EXCLUDE_STRINGS (1U << 3) /* exclude strings */ 356 | #define DUK_ENUM_OWN_PROPERTIES_ONLY (1U << 4) /* don't walk prototype chain, only check own properties */ 357 | #define DUK_ENUM_ARRAY_INDICES_ONLY (1U << 5) /* only enumerate array indices */ 358 | /* XXX: misleading name */ 359 | #define DUK_ENUM_SORT_ARRAY_INDICES (1U << 6) /* sort array indices (applied to full enumeration result, including inherited array indices); XXX: misleading name */ 360 | #define DUK_ENUM_NO_PROXY_BEHAVIOR (1U << 7) /* enumerate a proxy object itself without invoking proxy behavior */ 361 | 362 | /* Compilation flags for duk_compile() and duk_eval() */ 363 | /* DUK_COMPILE_xxx bits 0-2 are reserved for an internal 'nargs' argument. 364 | */ 365 | #define DUK_COMPILE_EVAL (1U << 3) /* compile eval code (instead of global code) */ 366 | #define DUK_COMPILE_FUNCTION (1U << 4) /* compile function code (instead of global code) */ 367 | #define DUK_COMPILE_STRICT (1U << 5) /* use strict (outer) context for global, eval, or function code */ 368 | #define DUK_COMPILE_SHEBANG (1U << 6) /* allow shebang ('#! ...') comment on first line of source */ 369 | #define DUK_COMPILE_SAFE (1U << 7) /* (internal) catch compilation errors */ 370 | #define DUK_COMPILE_NORESULT (1U << 8) /* (internal) omit eval result */ 371 | #define DUK_COMPILE_NOSOURCE (1U << 9) /* (internal) no source string on stack */ 372 | #define DUK_COMPILE_STRLEN (1U << 10) /* (internal) take strlen() of src_buffer (avoids double evaluation in macro) */ 373 | #define DUK_COMPILE_NOFILENAME (1U << 11) /* (internal) no filename on stack */ 374 | #define DUK_COMPILE_FUNCEXPR (1U << 12) /* (internal) source is a function expression (used for Function constructor) */ 375 | 376 | /* Flags for duk_def_prop() and its variants; base flags + a lot of convenience shorthands */ 377 | #define DUK_DEFPROP_WRITABLE (1U << 0) /* set writable (effective if DUK_DEFPROP_HAVE_WRITABLE set) */ 378 | #define DUK_DEFPROP_ENUMERABLE (1U << 1) /* set enumerable (effective if DUK_DEFPROP_HAVE_ENUMERABLE set) */ 379 | #define DUK_DEFPROP_CONFIGURABLE (1U << 2) /* set configurable (effective if DUK_DEFPROP_HAVE_CONFIGURABLE set) */ 380 | #define DUK_DEFPROP_HAVE_WRITABLE (1U << 3) /* set/clear writable */ 381 | #define DUK_DEFPROP_HAVE_ENUMERABLE (1U << 4) /* set/clear enumerable */ 382 | #define DUK_DEFPROP_HAVE_CONFIGURABLE (1U << 5) /* set/clear configurable */ 383 | #define DUK_DEFPROP_HAVE_VALUE (1U << 6) /* set value (given on value stack) */ 384 | #define DUK_DEFPROP_HAVE_GETTER (1U << 7) /* set getter (given on value stack) */ 385 | #define DUK_DEFPROP_HAVE_SETTER (1U << 8) /* set setter (given on value stack) */ 386 | #define DUK_DEFPROP_FORCE (1U << 9) /* force change if possible, may still fail for e.g. virtual properties */ 387 | #define DUK_DEFPROP_SET_WRITABLE (DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE) 388 | #define DUK_DEFPROP_CLEAR_WRITABLE DUK_DEFPROP_HAVE_WRITABLE 389 | #define DUK_DEFPROP_SET_ENUMERABLE (DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE) 390 | #define DUK_DEFPROP_CLEAR_ENUMERABLE DUK_DEFPROP_HAVE_ENUMERABLE 391 | #define DUK_DEFPROP_SET_CONFIGURABLE (DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE) 392 | #define DUK_DEFPROP_CLEAR_CONFIGURABLE DUK_DEFPROP_HAVE_CONFIGURABLE 393 | #define DUK_DEFPROP_W DUK_DEFPROP_WRITABLE 394 | #define DUK_DEFPROP_E DUK_DEFPROP_ENUMERABLE 395 | #define DUK_DEFPROP_C DUK_DEFPROP_CONFIGURABLE 396 | #define DUK_DEFPROP_WE (DUK_DEFPROP_WRITABLE | DUK_DEFPROP_ENUMERABLE) 397 | #define DUK_DEFPROP_WC (DUK_DEFPROP_WRITABLE | DUK_DEFPROP_CONFIGURABLE) 398 | #define DUK_DEFPROP_EC (DUK_DEFPROP_ENUMERABLE | DUK_DEFPROP_CONFIGURABLE) 399 | #define DUK_DEFPROP_WEC (DUK_DEFPROP_WRITABLE | DUK_DEFPROP_ENUMERABLE | DUK_DEFPROP_CONFIGURABLE) 400 | #define DUK_DEFPROP_HAVE_W DUK_DEFPROP_HAVE_WRITABLE 401 | #define DUK_DEFPROP_HAVE_E DUK_DEFPROP_HAVE_ENUMERABLE 402 | #define DUK_DEFPROP_HAVE_C DUK_DEFPROP_HAVE_CONFIGURABLE 403 | #define DUK_DEFPROP_HAVE_WE (DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_HAVE_ENUMERABLE) 404 | #define DUK_DEFPROP_HAVE_WC (DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_HAVE_CONFIGURABLE) 405 | #define DUK_DEFPROP_HAVE_EC (DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE) 406 | #define DUK_DEFPROP_HAVE_WEC (DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE) 407 | #define DUK_DEFPROP_SET_W DUK_DEFPROP_SET_WRITABLE 408 | #define DUK_DEFPROP_SET_E DUK_DEFPROP_SET_ENUMERABLE 409 | #define DUK_DEFPROP_SET_C DUK_DEFPROP_SET_CONFIGURABLE 410 | #define DUK_DEFPROP_SET_WE (DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_ENUMERABLE) 411 | #define DUK_DEFPROP_SET_WC (DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_CONFIGURABLE) 412 | #define DUK_DEFPROP_SET_EC (DUK_DEFPROP_SET_ENUMERABLE | DUK_DEFPROP_SET_CONFIGURABLE) 413 | #define DUK_DEFPROP_SET_WEC (DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_ENUMERABLE | DUK_DEFPROP_SET_CONFIGURABLE) 414 | #define DUK_DEFPROP_CLEAR_W DUK_DEFPROP_CLEAR_WRITABLE 415 | #define DUK_DEFPROP_CLEAR_E DUK_DEFPROP_CLEAR_ENUMERABLE 416 | #define DUK_DEFPROP_CLEAR_C DUK_DEFPROP_CLEAR_CONFIGURABLE 417 | #define DUK_DEFPROP_CLEAR_WE (DUK_DEFPROP_CLEAR_WRITABLE | DUK_DEFPROP_CLEAR_ENUMERABLE) 418 | #define DUK_DEFPROP_CLEAR_WC (DUK_DEFPROP_CLEAR_WRITABLE | DUK_DEFPROP_CLEAR_CONFIGURABLE) 419 | #define DUK_DEFPROP_CLEAR_EC (DUK_DEFPROP_CLEAR_ENUMERABLE | DUK_DEFPROP_CLEAR_CONFIGURABLE) 420 | #define DUK_DEFPROP_CLEAR_WEC (DUK_DEFPROP_CLEAR_WRITABLE | DUK_DEFPROP_CLEAR_ENUMERABLE | DUK_DEFPROP_CLEAR_CONFIGURABLE) 421 | #define DUK_DEFPROP_ATTR_W (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_W) 422 | #define DUK_DEFPROP_ATTR_E (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_E) 423 | #define DUK_DEFPROP_ATTR_C (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_C) 424 | #define DUK_DEFPROP_ATTR_WE (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_WE) 425 | #define DUK_DEFPROP_ATTR_WC (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_WC) 426 | #define DUK_DEFPROP_ATTR_EC (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_EC) 427 | #define DUK_DEFPROP_ATTR_WEC (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_WEC) 428 | 429 | /* Flags for duk_push_thread_raw() */ 430 | #define DUK_THREAD_NEW_GLOBAL_ENV (1U << 0) /* create a new global environment */ 431 | 432 | /* Flags for duk_gc() */ 433 | #define DUK_GC_COMPACT (1U << 0) /* compact heap objects */ 434 | 435 | /* Error codes (must be 8 bits at most, see duk_error.h) */ 436 | #define DUK_ERR_NONE 0 /* no error (e.g. from duk_get_error_code()) */ 437 | #define DUK_ERR_ERROR 1 /* Error */ 438 | #define DUK_ERR_EVAL_ERROR 2 /* EvalError */ 439 | #define DUK_ERR_RANGE_ERROR 3 /* RangeError */ 440 | #define DUK_ERR_REFERENCE_ERROR 4 /* ReferenceError */ 441 | #define DUK_ERR_SYNTAX_ERROR 5 /* SyntaxError */ 442 | #define DUK_ERR_TYPE_ERROR 6 /* TypeError */ 443 | #define DUK_ERR_URI_ERROR 7 /* URIError */ 444 | 445 | /* Return codes for C functions (shortcut for throwing an error) */ 446 | #define DUK_RET_ERROR (-DUK_ERR_ERROR) 447 | #define DUK_RET_EVAL_ERROR (-DUK_ERR_EVAL_ERROR) 448 | #define DUK_RET_RANGE_ERROR (-DUK_ERR_RANGE_ERROR) 449 | #define DUK_RET_REFERENCE_ERROR (-DUK_ERR_REFERENCE_ERROR) 450 | #define DUK_RET_SYNTAX_ERROR (-DUK_ERR_SYNTAX_ERROR) 451 | #define DUK_RET_TYPE_ERROR (-DUK_ERR_TYPE_ERROR) 452 | #define DUK_RET_URI_ERROR (-DUK_ERR_URI_ERROR) 453 | 454 | /* Return codes for protected calls (duk_safe_call(), duk_pcall()) */ 455 | #define DUK_EXEC_SUCCESS 0 456 | #define DUK_EXEC_ERROR 1 457 | 458 | /* Debug levels for DUK_USE_DEBUG_WRITE(). */ 459 | #define DUK_LEVEL_DEBUG 0 460 | #define DUK_LEVEL_DDEBUG 1 461 | #define DUK_LEVEL_DDDEBUG 2 462 | 463 | /* 464 | * Macros to create Symbols as C statically constructed strings. 465 | * 466 | * Call e.g. as DUK_HIDDEN_SYMBOL("myProperty") <=> ("\xFF" "myProperty"). 467 | * 468 | * Local symbols have a unique suffix, caller should take care to avoid 469 | * conflicting with the Duktape internal representation by e.g. prepending 470 | * a '!' character: DUK_LOCAL_SYMBOL("myLocal", "!123"). 471 | * 472 | * Note that these can only be used for string constants, not dynamically 473 | * created strings. 474 | * 475 | * You shouldn't normally use DUK_INTERNAL_SYMBOL() at all. It is reserved 476 | * for Duktape internal symbols only. There are no versioning guarantees 477 | * for internal symbols. 478 | */ 479 | 480 | #define DUK_HIDDEN_SYMBOL(x) ("\xFF" x) 481 | #define DUK_GLOBAL_SYMBOL(x) ("\x80" x) 482 | #define DUK_LOCAL_SYMBOL(x,uniq) ("\x81" x "\xff" uniq) 483 | #define DUK_WELLKNOWN_SYMBOL(x) ("\x81" x "\xff") 484 | #define DUK_INTERNAL_SYMBOL(x) ("\x82" x) 485 | 486 | /* 487 | * If no variadic macros, __FILE__ and __LINE__ are passed through globals 488 | * which is ugly and not thread safe. 489 | */ 490 | 491 | #if !defined(DUK_API_VARIADIC_MACROS) 492 | DUK_EXTERNAL_DECL const char *duk_api_global_filename; 493 | DUK_EXTERNAL_DECL duk_int_t duk_api_global_line; 494 | #endif 495 | 496 | /* 497 | * Context management 498 | */ 499 | 500 | DUK_EXTERNAL_DECL 501 | duk_context *duk_create_heap(duk_alloc_function alloc_func, 502 | duk_realloc_function realloc_func, 503 | duk_free_function free_func, 504 | void *heap_udata, 505 | duk_fatal_function fatal_handler); 506 | DUK_EXTERNAL_DECL void duk_destroy_heap(duk_context *ctx); 507 | 508 | DUK_EXTERNAL_DECL void duk_suspend(duk_context *ctx, duk_thread_state *state); 509 | DUK_EXTERNAL_DECL void duk_resume(duk_context *ctx, const duk_thread_state *state); 510 | 511 | #define duk_create_heap_default() \ 512 | duk_create_heap(NULL, NULL, NULL, NULL, NULL) 513 | 514 | /* 515 | * Memory management 516 | * 517 | * Raw functions have no side effects (cannot trigger GC). 518 | */ 519 | 520 | DUK_EXTERNAL_DECL void *duk_alloc_raw(duk_context *ctx, duk_size_t size); 521 | DUK_EXTERNAL_DECL void duk_free_raw(duk_context *ctx, void *ptr); 522 | DUK_EXTERNAL_DECL void *duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size); 523 | DUK_EXTERNAL_DECL void *duk_alloc(duk_context *ctx, duk_size_t size); 524 | DUK_EXTERNAL_DECL void duk_free(duk_context *ctx, void *ptr); 525 | DUK_EXTERNAL_DECL void *duk_realloc(duk_context *ctx, void *ptr, duk_size_t size); 526 | DUK_EXTERNAL_DECL void duk_get_memory_functions(duk_context *ctx, duk_memory_functions *out_funcs); 527 | DUK_EXTERNAL_DECL void duk_gc(duk_context *ctx, duk_uint_t flags); 528 | 529 | /* 530 | * Error handling 531 | */ 532 | 533 | DUK_API_NORETURN(DUK_EXTERNAL_DECL void duk_throw_raw(duk_context *ctx)); 534 | #define duk_throw(ctx) \ 535 | (duk_throw_raw((ctx)), (duk_ret_t) 0) 536 | DUK_API_NORETURN(DUK_EXTERNAL_DECL void duk_fatal_raw(duk_context *ctx, const char *err_msg)); 537 | #define duk_fatal(ctx,err_msg) \ 538 | (duk_fatal_raw((ctx), (err_msg)), (duk_ret_t) 0) 539 | DUK_API_NORETURN(DUK_EXTERNAL_DECL void duk_error_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...)); 540 | 541 | #if defined(DUK_API_VARIADIC_MACROS) 542 | #define duk_error(ctx,err_code,...) \ 543 | (duk_error_raw((ctx), (duk_errcode_t) (err_code), (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0) 544 | #define duk_generic_error(ctx,...) \ 545 | (duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0) 546 | #define duk_eval_error(ctx,...) \ 547 | (duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_EVAL_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0) 548 | #define duk_range_error(ctx,...) \ 549 | (duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_RANGE_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0) 550 | #define duk_reference_error(ctx,...) \ 551 | (duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_REFERENCE_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0) 552 | #define duk_syntax_error(ctx,...) \ 553 | (duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_SYNTAX_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0) 554 | #define duk_type_error(ctx,...) \ 555 | (duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_TYPE_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0) 556 | #define duk_uri_error(ctx,...) \ 557 | (duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_URI_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0) 558 | #else /* DUK_API_VARIADIC_MACROS */ 559 | /* For legacy compilers without variadic macros a macro hack is used to allow 560 | * variable arguments. While the macro allows "return duk_error(...)", it 561 | * will fail with e.g. "(void) duk_error(...)". The calls are noreturn but 562 | * with a return value to allow the "return duk_error(...)" idiom. This may 563 | * cause some compiler warnings, but without noreturn the generated code is 564 | * often worse. The same approach as with variadic macros (using 565 | * "(duk_error(...), 0)") won't work due to the macro hack structure. 566 | */ 567 | DUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_error_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...)); 568 | DUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_generic_error_stash(duk_context *ctx, const char *fmt, ...)); 569 | DUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_eval_error_stash(duk_context *ctx, const char *fmt, ...)); 570 | DUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_range_error_stash(duk_context *ctx, const char *fmt, ...)); 571 | DUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_reference_error_stash(duk_context *ctx, const char *fmt, ...)); 572 | DUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_syntax_error_stash(duk_context *ctx, const char *fmt, ...)); 573 | DUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_type_error_stash(duk_context *ctx, const char *fmt, ...)); 574 | DUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_uri_error_stash(duk_context *ctx, const char *fmt, ...)); 575 | #define duk_error \ 576 | (duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \ 577 | duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \ 578 | duk_error_stash) /* last value is func pointer, arguments follow in parens */ 579 | #define duk_generic_error \ 580 | (duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \ 581 | duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \ 582 | duk_generic_error_stash) 583 | #define duk_eval_error \ 584 | (duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \ 585 | duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \ 586 | duk_eval_error_stash) 587 | #define duk_range_error \ 588 | (duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \ 589 | duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \ 590 | duk_range_error_stash) 591 | #define duk_reference_error \ 592 | (duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \ 593 | duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \ 594 | duk_reference_error_stash) 595 | #define duk_syntax_error \ 596 | (duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \ 597 | duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \ 598 | duk_syntax_error_stash) 599 | #define duk_type_error \ 600 | (duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \ 601 | duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \ 602 | duk_type_error_stash) 603 | #define duk_uri_error \ 604 | (duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \ 605 | duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \ 606 | duk_uri_error_stash) 607 | #endif /* DUK_API_VARIADIC_MACROS */ 608 | 609 | DUK_API_NORETURN(DUK_EXTERNAL_DECL void duk_error_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap)); 610 | 611 | #define duk_error_va(ctx,err_code,fmt,ap) \ 612 | (duk_error_va_raw((ctx), (duk_errcode_t) (err_code), (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0) 613 | #define duk_generic_error_va(ctx,fmt,ap) \ 614 | (duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0) 615 | #define duk_eval_error_va(ctx,fmt,ap) \ 616 | (duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_EVAL_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0) 617 | #define duk_range_error_va(ctx,fmt,ap) \ 618 | (duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_RANGE_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0) 619 | #define duk_reference_error_va(ctx,fmt,ap) \ 620 | (duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_REFERENCE_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0) 621 | #define duk_syntax_error_va(ctx,fmt,ap) \ 622 | (duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_SYNTAX_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0) 623 | #define duk_type_error_va(ctx,fmt,ap) \ 624 | (duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_TYPE_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0) 625 | #define duk_uri_error_va(ctx,fmt,ap) \ 626 | (duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_URI_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0) 627 | 628 | /* 629 | * Other state related functions 630 | */ 631 | 632 | DUK_EXTERNAL_DECL duk_bool_t duk_is_strict_call(duk_context *ctx); 633 | DUK_EXTERNAL_DECL duk_bool_t duk_is_constructor_call(duk_context *ctx); 634 | 635 | /* 636 | * Stack management 637 | */ 638 | 639 | DUK_EXTERNAL_DECL duk_idx_t duk_normalize_index(duk_context *ctx, duk_idx_t idx); 640 | DUK_EXTERNAL_DECL duk_idx_t duk_require_normalize_index(duk_context *ctx, duk_idx_t idx); 641 | DUK_EXTERNAL_DECL duk_bool_t duk_is_valid_index(duk_context *ctx, duk_idx_t idx); 642 | DUK_EXTERNAL_DECL void duk_require_valid_index(duk_context *ctx, duk_idx_t idx); 643 | 644 | DUK_EXTERNAL_DECL duk_idx_t duk_get_top(duk_context *ctx); 645 | DUK_EXTERNAL_DECL void duk_set_top(duk_context *ctx, duk_idx_t idx); 646 | DUK_EXTERNAL_DECL duk_idx_t duk_get_top_index(duk_context *ctx); 647 | DUK_EXTERNAL_DECL duk_idx_t duk_require_top_index(duk_context *ctx); 648 | 649 | /* Although extra/top could be an unsigned type here, using a signed type 650 | * makes the API more robust to calling code calculation errors or corner 651 | * cases (where caller might occasionally come up with negative values). 652 | * Negative values are treated as zero, which is better than casting them 653 | * to a large unsigned number. (This principle is used elsewhere in the 654 | * API too.) 655 | */ 656 | DUK_EXTERNAL_DECL duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra); 657 | DUK_EXTERNAL_DECL void duk_require_stack(duk_context *ctx, duk_idx_t extra); 658 | DUK_EXTERNAL_DECL duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top); 659 | DUK_EXTERNAL_DECL void duk_require_stack_top(duk_context *ctx, duk_idx_t top); 660 | 661 | /* 662 | * Stack manipulation (other than push/pop) 663 | */ 664 | 665 | DUK_EXTERNAL_DECL void duk_swap(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2); 666 | DUK_EXTERNAL_DECL void duk_swap_top(duk_context *ctx, duk_idx_t idx); 667 | DUK_EXTERNAL_DECL void duk_dup(duk_context *ctx, duk_idx_t from_idx); 668 | DUK_EXTERNAL_DECL void duk_dup_top(duk_context *ctx); 669 | DUK_EXTERNAL_DECL void duk_insert(duk_context *ctx, duk_idx_t to_idx); 670 | DUK_EXTERNAL_DECL void duk_pull(duk_context *ctx, duk_idx_t from_idx); 671 | DUK_EXTERNAL_DECL void duk_replace(duk_context *ctx, duk_idx_t to_idx); 672 | DUK_EXTERNAL_DECL void duk_copy(duk_context *ctx, duk_idx_t from_idx, duk_idx_t to_idx); 673 | DUK_EXTERNAL_DECL void duk_remove(duk_context *ctx, duk_idx_t idx); 674 | DUK_EXTERNAL_DECL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, duk_idx_t count, duk_bool_t is_copy); 675 | 676 | #define duk_xmove_top(to_ctx,from_ctx,count) \ 677 | duk_xcopymove_raw((to_ctx), (from_ctx), (count), 0 /*is_copy*/) 678 | #define duk_xcopy_top(to_ctx,from_ctx,count) \ 679 | duk_xcopymove_raw((to_ctx), (from_ctx), (count), 1 /*is_copy*/) 680 | 681 | /* 682 | * Push operations 683 | * 684 | * Push functions return the absolute (relative to bottom of frame) 685 | * position of the pushed value for convenience. 686 | * 687 | * Note: duk_dup() is technically a push. 688 | */ 689 | 690 | DUK_EXTERNAL_DECL void duk_push_undefined(duk_context *ctx); 691 | DUK_EXTERNAL_DECL void duk_push_null(duk_context *ctx); 692 | DUK_EXTERNAL_DECL void duk_push_boolean(duk_context *ctx, duk_bool_t val); 693 | DUK_EXTERNAL_DECL void duk_push_true(duk_context *ctx); 694 | DUK_EXTERNAL_DECL void duk_push_false(duk_context *ctx); 695 | DUK_EXTERNAL_DECL void duk_push_number(duk_context *ctx, duk_double_t val); 696 | DUK_EXTERNAL_DECL void duk_push_nan(duk_context *ctx); 697 | DUK_EXTERNAL_DECL void duk_push_int(duk_context *ctx, duk_int_t val); 698 | DUK_EXTERNAL_DECL void duk_push_uint(duk_context *ctx, duk_uint_t val); 699 | DUK_EXTERNAL_DECL const char *duk_push_string(duk_context *ctx, const char *str); 700 | DUK_EXTERNAL_DECL const char *duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len); 701 | DUK_EXTERNAL_DECL void duk_push_pointer(duk_context *ctx, void *p); 702 | DUK_EXTERNAL_DECL const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...); 703 | DUK_EXTERNAL_DECL const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap); 704 | 705 | /* duk_push_literal() may evaluate its argument (a C string literal) more than 706 | * once on purpose. When speed is preferred, sizeof() avoids an unnecessary 707 | * strlen() at runtime. Sizeof("foo") == 4, so subtract 1. The argument 708 | * must be non-NULL and should not contain internal NUL characters as the 709 | * behavior will then depend on config options. 710 | */ 711 | #if defined(DUK_USE_PREFER_SIZE) 712 | #define duk_push_literal(ctx,cstring) duk_push_string((ctx), (cstring)) 713 | #else 714 | DUK_EXTERNAL_DECL const char *duk_push_literal_raw(duk_context *ctx, const char *str, duk_size_t len); 715 | #define duk_push_literal(ctx,cstring) duk_push_literal_raw((ctx), (cstring), sizeof((cstring)) - 1U) 716 | #endif 717 | 718 | DUK_EXTERNAL_DECL void duk_push_this(duk_context *ctx); 719 | DUK_EXTERNAL_DECL void duk_push_new_target(duk_context *ctx); 720 | DUK_EXTERNAL_DECL void duk_push_current_function(duk_context *ctx); 721 | DUK_EXTERNAL_DECL void duk_push_current_thread(duk_context *ctx); 722 | DUK_EXTERNAL_DECL void duk_push_global_object(duk_context *ctx); 723 | DUK_EXTERNAL_DECL void duk_push_heap_stash(duk_context *ctx); 724 | DUK_EXTERNAL_DECL void duk_push_global_stash(duk_context *ctx); 725 | DUK_EXTERNAL_DECL void duk_push_thread_stash(duk_context *ctx, duk_context *target_ctx); 726 | 727 | DUK_EXTERNAL_DECL duk_idx_t duk_push_object(duk_context *ctx); 728 | DUK_EXTERNAL_DECL duk_idx_t duk_push_bare_object(duk_context *ctx); 729 | DUK_EXTERNAL_DECL duk_idx_t duk_push_array(duk_context *ctx); 730 | DUK_EXTERNAL_DECL duk_idx_t duk_push_bare_array(duk_context *ctx); 731 | DUK_EXTERNAL_DECL duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_idx_t nargs); 732 | DUK_EXTERNAL_DECL duk_idx_t duk_push_c_lightfunc(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic); 733 | DUK_EXTERNAL_DECL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags); 734 | DUK_EXTERNAL_DECL duk_idx_t duk_push_proxy(duk_context *ctx, duk_uint_t proxy_flags); 735 | 736 | #define duk_push_thread(ctx) \ 737 | duk_push_thread_raw((ctx), 0 /*flags*/) 738 | 739 | #define duk_push_thread_new_globalenv(ctx) \ 740 | duk_push_thread_raw((ctx), DUK_THREAD_NEW_GLOBAL_ENV /*flags*/) 741 | 742 | DUK_EXTERNAL_DECL duk_idx_t duk_push_error_object_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...); 743 | 744 | #if defined(DUK_API_VARIADIC_MACROS) 745 | #define duk_push_error_object(ctx,err_code,...) \ 746 | duk_push_error_object_raw((ctx), (err_code), (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__) 747 | #else 748 | DUK_EXTERNAL_DECL duk_idx_t duk_push_error_object_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...); 749 | /* Note: parentheses are required so that the comma expression works in assignments. */ 750 | #define duk_push_error_object \ 751 | (duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \ 752 | duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \ 753 | duk_push_error_object_stash) /* last value is func pointer, arguments follow in parens */ 754 | #endif 755 | 756 | DUK_EXTERNAL_DECL duk_idx_t duk_push_error_object_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap); 757 | #define duk_push_error_object_va(ctx,err_code,fmt,ap) \ 758 | duk_push_error_object_va_raw((ctx), (err_code), (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)) 759 | 760 | #define DUK_BUF_FLAG_DYNAMIC (1 << 0) /* internal flag: dynamic buffer */ 761 | #define DUK_BUF_FLAG_EXTERNAL (1 << 1) /* internal flag: external buffer */ 762 | #define DUK_BUF_FLAG_NOZERO (1 << 2) /* internal flag: don't zero allocated buffer */ 763 | 764 | DUK_EXTERNAL_DECL void *duk_push_buffer_raw(duk_context *ctx, duk_size_t size, duk_small_uint_t flags); 765 | 766 | #define duk_push_buffer(ctx,size,dynamic) \ 767 | duk_push_buffer_raw((ctx), (size), (dynamic) ? DUK_BUF_FLAG_DYNAMIC : 0) 768 | #define duk_push_fixed_buffer(ctx,size) \ 769 | duk_push_buffer_raw((ctx), (size), 0 /*flags*/) 770 | #define duk_push_dynamic_buffer(ctx,size) \ 771 | duk_push_buffer_raw((ctx), (size), DUK_BUF_FLAG_DYNAMIC /*flags*/) 772 | #define duk_push_external_buffer(ctx) \ 773 | ((void) duk_push_buffer_raw((ctx), 0, DUK_BUF_FLAG_DYNAMIC | DUK_BUF_FLAG_EXTERNAL)) 774 | 775 | #define DUK_BUFOBJ_ARRAYBUFFER 0 776 | #define DUK_BUFOBJ_NODEJS_BUFFER 1 777 | #define DUK_BUFOBJ_DATAVIEW 2 778 | #define DUK_BUFOBJ_INT8ARRAY 3 779 | #define DUK_BUFOBJ_UINT8ARRAY 4 780 | #define DUK_BUFOBJ_UINT8CLAMPEDARRAY 5 781 | #define DUK_BUFOBJ_INT16ARRAY 6 782 | #define DUK_BUFOBJ_UINT16ARRAY 7 783 | #define DUK_BUFOBJ_INT32ARRAY 8 784 | #define DUK_BUFOBJ_UINT32ARRAY 9 785 | #define DUK_BUFOBJ_FLOAT32ARRAY 10 786 | #define DUK_BUFOBJ_FLOAT64ARRAY 11 787 | 788 | DUK_EXTERNAL_DECL void duk_push_buffer_object(duk_context *ctx, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags); 789 | 790 | DUK_EXTERNAL_DECL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr); 791 | 792 | /* 793 | * Pop operations 794 | */ 795 | 796 | DUK_EXTERNAL_DECL void duk_pop(duk_context *ctx); 797 | DUK_EXTERNAL_DECL void duk_pop_n(duk_context *ctx, duk_idx_t count); 798 | DUK_EXTERNAL_DECL void duk_pop_2(duk_context *ctx); 799 | DUK_EXTERNAL_DECL void duk_pop_3(duk_context *ctx); 800 | 801 | /* 802 | * Type checks 803 | * 804 | * duk_is_none(), which would indicate whether index it outside of stack, 805 | * is not needed; duk_is_valid_index() gives the same information. 806 | */ 807 | 808 | DUK_EXTERNAL_DECL duk_int_t duk_get_type(duk_context *ctx, duk_idx_t idx); 809 | DUK_EXTERNAL_DECL duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t idx, duk_int_t type); 810 | DUK_EXTERNAL_DECL duk_uint_t duk_get_type_mask(duk_context *ctx, duk_idx_t idx); 811 | DUK_EXTERNAL_DECL duk_bool_t duk_check_type_mask(duk_context *ctx, duk_idx_t idx, duk_uint_t mask); 812 | 813 | DUK_EXTERNAL_DECL duk_bool_t duk_is_undefined(duk_context *ctx, duk_idx_t idx); 814 | DUK_EXTERNAL_DECL duk_bool_t duk_is_null(duk_context *ctx, duk_idx_t idx); 815 | #define duk_is_null_or_undefined(ctx, idx) \ 816 | ((duk_get_type_mask((ctx), (idx)) & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) ? 1 : 0) 817 | 818 | DUK_EXTERNAL_DECL duk_bool_t duk_is_boolean(duk_context *ctx, duk_idx_t idx); 819 | DUK_EXTERNAL_DECL duk_bool_t duk_is_number(duk_context *ctx, duk_idx_t idx); 820 | DUK_EXTERNAL_DECL duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t idx); 821 | DUK_EXTERNAL_DECL duk_bool_t duk_is_string(duk_context *ctx, duk_idx_t idx); 822 | DUK_EXTERNAL_DECL duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t idx); 823 | DUK_EXTERNAL_DECL duk_bool_t duk_is_buffer(duk_context *ctx, duk_idx_t idx); 824 | DUK_EXTERNAL_DECL duk_bool_t duk_is_buffer_data(duk_context *ctx, duk_idx_t idx); 825 | DUK_EXTERNAL_DECL duk_bool_t duk_is_pointer(duk_context *ctx, duk_idx_t idx); 826 | DUK_EXTERNAL_DECL duk_bool_t duk_is_lightfunc(duk_context *ctx, duk_idx_t idx); 827 | 828 | DUK_EXTERNAL_DECL duk_bool_t duk_is_symbol(duk_context *ctx, duk_idx_t idx); 829 | DUK_EXTERNAL_DECL duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t idx); 830 | DUK_EXTERNAL_DECL duk_bool_t duk_is_function(duk_context *ctx, duk_idx_t idx); 831 | DUK_EXTERNAL_DECL duk_bool_t duk_is_c_function(duk_context *ctx, duk_idx_t idx); 832 | DUK_EXTERNAL_DECL duk_bool_t duk_is_ecmascript_function(duk_context *ctx, duk_idx_t idx); 833 | DUK_EXTERNAL_DECL duk_bool_t duk_is_bound_function(duk_context *ctx, duk_idx_t idx); 834 | DUK_EXTERNAL_DECL duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t idx); 835 | 836 | #define duk_is_callable(ctx,idx) \ 837 | duk_is_function((ctx), (idx)) 838 | DUK_EXTERNAL_DECL duk_bool_t duk_is_constructable(duk_context *ctx, duk_idx_t idx); 839 | 840 | DUK_EXTERNAL_DECL duk_bool_t duk_is_dynamic_buffer(duk_context *ctx, duk_idx_t idx); 841 | DUK_EXTERNAL_DECL duk_bool_t duk_is_fixed_buffer(duk_context *ctx, duk_idx_t idx); 842 | DUK_EXTERNAL_DECL duk_bool_t duk_is_external_buffer(duk_context *ctx, duk_idx_t idx); 843 | 844 | /* Buffers and lightfuncs are not considered primitive because they mimic 845 | * objects and e.g. duk_to_primitive() will coerce them instead of returning 846 | * them as is. Symbols are represented as strings internally. 847 | */ 848 | #define duk_is_primitive(ctx,idx) \ 849 | duk_check_type_mask((ctx), (idx), DUK_TYPE_MASK_UNDEFINED | \ 850 | DUK_TYPE_MASK_NULL | \ 851 | DUK_TYPE_MASK_BOOLEAN | \ 852 | DUK_TYPE_MASK_NUMBER | \ 853 | DUK_TYPE_MASK_STRING | \ 854 | DUK_TYPE_MASK_POINTER) 855 | 856 | /* Symbols are object coercible, covered by DUK_TYPE_MASK_STRING. */ 857 | #define duk_is_object_coercible(ctx,idx) \ 858 | duk_check_type_mask((ctx), (idx), DUK_TYPE_MASK_BOOLEAN | \ 859 | DUK_TYPE_MASK_NUMBER | \ 860 | DUK_TYPE_MASK_STRING | \ 861 | DUK_TYPE_MASK_OBJECT | \ 862 | DUK_TYPE_MASK_BUFFER | \ 863 | DUK_TYPE_MASK_POINTER | \ 864 | DUK_TYPE_MASK_LIGHTFUNC) 865 | 866 | DUK_EXTERNAL_DECL duk_errcode_t duk_get_error_code(duk_context *ctx, duk_idx_t idx); 867 | #define duk_is_error(ctx,idx) \ 868 | (duk_get_error_code((ctx), (idx)) != 0) 869 | #define duk_is_eval_error(ctx,idx) \ 870 | (duk_get_error_code((ctx), (idx)) == DUK_ERR_EVAL_ERROR) 871 | #define duk_is_range_error(ctx,idx) \ 872 | (duk_get_error_code((ctx), (idx)) == DUK_ERR_RANGE_ERROR) 873 | #define duk_is_reference_error(ctx,idx) \ 874 | (duk_get_error_code((ctx), (idx)) == DUK_ERR_REFERENCE_ERROR) 875 | #define duk_is_syntax_error(ctx,idx) \ 876 | (duk_get_error_code((ctx), (idx)) == DUK_ERR_SYNTAX_ERROR) 877 | #define duk_is_type_error(ctx,idx) \ 878 | (duk_get_error_code((ctx), (idx)) == DUK_ERR_TYPE_ERROR) 879 | #define duk_is_uri_error(ctx,idx) \ 880 | (duk_get_error_code((ctx), (idx)) == DUK_ERR_URI_ERROR) 881 | 882 | /* 883 | * Get operations: no coercion, returns default value for invalid 884 | * indices and invalid value types. 885 | * 886 | * duk_get_undefined() and duk_get_null() would be pointless and 887 | * are not included. 888 | */ 889 | 890 | DUK_EXTERNAL_DECL duk_bool_t duk_get_boolean(duk_context *ctx, duk_idx_t idx); 891 | DUK_EXTERNAL_DECL duk_double_t duk_get_number(duk_context *ctx, duk_idx_t idx); 892 | DUK_EXTERNAL_DECL duk_int_t duk_get_int(duk_context *ctx, duk_idx_t idx); 893 | DUK_EXTERNAL_DECL duk_uint_t duk_get_uint(duk_context *ctx, duk_idx_t idx); 894 | DUK_EXTERNAL_DECL const char *duk_get_string(duk_context *ctx, duk_idx_t idx); 895 | DUK_EXTERNAL_DECL const char *duk_get_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len); 896 | DUK_EXTERNAL_DECL void *duk_get_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size); 897 | DUK_EXTERNAL_DECL void *duk_get_buffer_data(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size); 898 | DUK_EXTERNAL_DECL void *duk_get_pointer(duk_context *ctx, duk_idx_t idx); 899 | DUK_EXTERNAL_DECL duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t idx); 900 | DUK_EXTERNAL_DECL duk_context *duk_get_context(duk_context *ctx, duk_idx_t idx); 901 | DUK_EXTERNAL_DECL void *duk_get_heapptr(duk_context *ctx, duk_idx_t idx); 902 | 903 | /* 904 | * Get-with-explicit default operations: like get operations but with an 905 | * explicit default value. 906 | */ 907 | 908 | DUK_EXTERNAL_DECL duk_bool_t duk_get_boolean_default(duk_context *ctx, duk_idx_t idx, duk_bool_t def_value); 909 | DUK_EXTERNAL_DECL duk_double_t duk_get_number_default(duk_context *ctx, duk_idx_t idx, duk_double_t def_value); 910 | DUK_EXTERNAL_DECL duk_int_t duk_get_int_default(duk_context *ctx, duk_idx_t idx, duk_int_t def_value); 911 | DUK_EXTERNAL_DECL duk_uint_t duk_get_uint_default(duk_context *ctx, duk_idx_t idx, duk_uint_t def_value); 912 | DUK_EXTERNAL_DECL const char *duk_get_string_default(duk_context *ctx, duk_idx_t idx, const char *def_value); 913 | DUK_EXTERNAL_DECL const char *duk_get_lstring_default(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len); 914 | DUK_EXTERNAL_DECL void *duk_get_buffer_default(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len); 915 | DUK_EXTERNAL_DECL void *duk_get_buffer_data_default(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len); 916 | DUK_EXTERNAL_DECL void *duk_get_pointer_default(duk_context *ctx, duk_idx_t idx, void *def_value); 917 | DUK_EXTERNAL_DECL duk_c_function duk_get_c_function_default(duk_context *ctx, duk_idx_t idx, duk_c_function def_value); 918 | DUK_EXTERNAL_DECL duk_context *duk_get_context_default(duk_context *ctx, duk_idx_t idx, duk_context *def_value); 919 | DUK_EXTERNAL_DECL void *duk_get_heapptr_default(duk_context *ctx, duk_idx_t idx, void *def_value); 920 | 921 | /* 922 | * Opt operations: like require operations but with an explicit default value 923 | * when value is undefined or index is invalid, null and non-matching types 924 | * cause a TypeError. 925 | */ 926 | 927 | DUK_EXTERNAL_DECL duk_bool_t duk_opt_boolean(duk_context *ctx, duk_idx_t idx, duk_bool_t def_value); 928 | DUK_EXTERNAL_DECL duk_double_t duk_opt_number(duk_context *ctx, duk_idx_t idx, duk_double_t def_value); 929 | DUK_EXTERNAL_DECL duk_int_t duk_opt_int(duk_context *ctx, duk_idx_t idx, duk_int_t def_value); 930 | DUK_EXTERNAL_DECL duk_uint_t duk_opt_uint(duk_context *ctx, duk_idx_t idx, duk_uint_t def_value); 931 | DUK_EXTERNAL_DECL const char *duk_opt_string(duk_context *ctx, duk_idx_t idx, const char *def_ptr); 932 | DUK_EXTERNAL_DECL const char *duk_opt_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len); 933 | DUK_EXTERNAL_DECL void *duk_opt_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size); 934 | DUK_EXTERNAL_DECL void *duk_opt_buffer_data(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size); 935 | DUK_EXTERNAL_DECL void *duk_opt_pointer(duk_context *ctx, duk_idx_t idx, void *def_value); 936 | DUK_EXTERNAL_DECL duk_c_function duk_opt_c_function(duk_context *ctx, duk_idx_t idx, duk_c_function def_value); 937 | DUK_EXTERNAL_DECL duk_context *duk_opt_context(duk_context *ctx, duk_idx_t idx, duk_context *def_value); 938 | DUK_EXTERNAL_DECL void *duk_opt_heapptr(duk_context *ctx, duk_idx_t idx, void *def_value); 939 | 940 | /* 941 | * Require operations: no coercion, throw error if index or type 942 | * is incorrect. No defaulting. 943 | */ 944 | 945 | #define duk_require_type_mask(ctx,idx,mask) \ 946 | ((void) duk_check_type_mask((ctx), (idx), (mask) | DUK_TYPE_MASK_THROW)) 947 | 948 | DUK_EXTERNAL_DECL void duk_require_undefined(duk_context *ctx, duk_idx_t idx); 949 | DUK_EXTERNAL_DECL void duk_require_null(duk_context *ctx, duk_idx_t idx); 950 | DUK_EXTERNAL_DECL duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t idx); 951 | DUK_EXTERNAL_DECL duk_double_t duk_require_number(duk_context *ctx, duk_idx_t idx); 952 | DUK_EXTERNAL_DECL duk_int_t duk_require_int(duk_context *ctx, duk_idx_t idx); 953 | DUK_EXTERNAL_DECL duk_uint_t duk_require_uint(duk_context *ctx, duk_idx_t idx); 954 | DUK_EXTERNAL_DECL const char *duk_require_string(duk_context *ctx, duk_idx_t idx); 955 | DUK_EXTERNAL_DECL const char *duk_require_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len); 956 | DUK_EXTERNAL_DECL void duk_require_object(duk_context *ctx, duk_idx_t idx); 957 | DUK_EXTERNAL_DECL void *duk_require_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size); 958 | DUK_EXTERNAL_DECL void *duk_require_buffer_data(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size); 959 | DUK_EXTERNAL_DECL void *duk_require_pointer(duk_context *ctx, duk_idx_t idx); 960 | DUK_EXTERNAL_DECL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t idx); 961 | DUK_EXTERNAL_DECL duk_context *duk_require_context(duk_context *ctx, duk_idx_t idx); 962 | DUK_EXTERNAL_DECL void duk_require_function(duk_context *ctx, duk_idx_t idx); 963 | #define duk_require_callable(ctx,idx) \ 964 | duk_require_function((ctx), (idx)) 965 | DUK_EXTERNAL_DECL void duk_require_constructor_call(duk_context *ctx); 966 | DUK_EXTERNAL_DECL void duk_require_constructable(duk_context *ctx, duk_idx_t idx); 967 | DUK_EXTERNAL_DECL void *duk_require_heapptr(duk_context *ctx, duk_idx_t idx); 968 | 969 | /* Symbols are object coercible and covered by DUK_TYPE_MASK_STRING. */ 970 | #define duk_require_object_coercible(ctx,idx) \ 971 | ((void) duk_check_type_mask((ctx), (idx), DUK_TYPE_MASK_BOOLEAN | \ 972 | DUK_TYPE_MASK_NUMBER | \ 973 | DUK_TYPE_MASK_STRING | \ 974 | DUK_TYPE_MASK_OBJECT | \ 975 | DUK_TYPE_MASK_BUFFER | \ 976 | DUK_TYPE_MASK_POINTER | \ 977 | DUK_TYPE_MASK_LIGHTFUNC | \ 978 | DUK_TYPE_MASK_THROW)) 979 | 980 | /* 981 | * Coercion operations: in-place coercion, return coerced value where 982 | * applicable. If index is invalid, throw error. Some coercions may 983 | * throw an expected error (e.g. from a toString() or valueOf() call) 984 | * or an internal error (e.g. from out of memory). 985 | */ 986 | 987 | DUK_EXTERNAL_DECL void duk_to_undefined(duk_context *ctx, duk_idx_t idx); 988 | DUK_EXTERNAL_DECL void duk_to_null(duk_context *ctx, duk_idx_t idx); 989 | DUK_EXTERNAL_DECL duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t idx); 990 | DUK_EXTERNAL_DECL duk_double_t duk_to_number(duk_context *ctx, duk_idx_t idx); 991 | DUK_EXTERNAL_DECL duk_int_t duk_to_int(duk_context *ctx, duk_idx_t idx); 992 | DUK_EXTERNAL_DECL duk_uint_t duk_to_uint(duk_context *ctx, duk_idx_t idx); 993 | DUK_EXTERNAL_DECL duk_int32_t duk_to_int32(duk_context *ctx, duk_idx_t idx); 994 | DUK_EXTERNAL_DECL duk_uint32_t duk_to_uint32(duk_context *ctx, duk_idx_t idx); 995 | DUK_EXTERNAL_DECL duk_uint16_t duk_to_uint16(duk_context *ctx, duk_idx_t idx); 996 | DUK_EXTERNAL_DECL const char *duk_to_string(duk_context *ctx, duk_idx_t idx); 997 | DUK_EXTERNAL_DECL const char *duk_to_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len); 998 | DUK_EXTERNAL_DECL void *duk_to_buffer_raw(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, duk_uint_t flags); 999 | DUK_EXTERNAL_DECL void *duk_to_pointer(duk_context *ctx, duk_idx_t idx); 1000 | DUK_EXTERNAL_DECL void duk_to_object(duk_context *ctx, duk_idx_t idx); 1001 | DUK_EXTERNAL_DECL void duk_to_primitive(duk_context *ctx, duk_idx_t idx, duk_int_t hint); 1002 | 1003 | #define DUK_BUF_MODE_FIXED 0 /* internal: request fixed buffer result */ 1004 | #define DUK_BUF_MODE_DYNAMIC 1 /* internal: request dynamic buffer result */ 1005 | #define DUK_BUF_MODE_DONTCARE 2 /* internal: don't care about fixed/dynamic nature */ 1006 | 1007 | #define duk_to_buffer(ctx,idx,out_size) \ 1008 | duk_to_buffer_raw((ctx), (idx), (out_size), DUK_BUF_MODE_DONTCARE) 1009 | #define duk_to_fixed_buffer(ctx,idx,out_size) \ 1010 | duk_to_buffer_raw((ctx), (idx), (out_size), DUK_BUF_MODE_FIXED) 1011 | #define duk_to_dynamic_buffer(ctx,idx,out_size) \ 1012 | duk_to_buffer_raw((ctx), (idx), (out_size), DUK_BUF_MODE_DYNAMIC) 1013 | 1014 | /* safe variants of a few coercion operations */ 1015 | DUK_EXTERNAL_DECL const char *duk_safe_to_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len); 1016 | DUK_EXTERNAL_DECL const char *duk_to_stacktrace(duk_context *ctx, duk_idx_t idx); 1017 | DUK_EXTERNAL_DECL const char *duk_safe_to_stacktrace(duk_context *ctx, duk_idx_t idx); 1018 | #define duk_safe_to_string(ctx,idx) \ 1019 | duk_safe_to_lstring((ctx), (idx), NULL) 1020 | 1021 | /* 1022 | * Value length 1023 | */ 1024 | 1025 | DUK_EXTERNAL_DECL duk_size_t duk_get_length(duk_context *ctx, duk_idx_t idx); 1026 | DUK_EXTERNAL_DECL void duk_set_length(duk_context *ctx, duk_idx_t idx, duk_size_t len); 1027 | #if 0 1028 | /* duk_require_length()? */ 1029 | /* duk_opt_length()? */ 1030 | #endif 1031 | 1032 | /* 1033 | * Misc conversion 1034 | */ 1035 | 1036 | DUK_EXTERNAL_DECL const char *duk_base64_encode(duk_context *ctx, duk_idx_t idx); 1037 | DUK_EXTERNAL_DECL void duk_base64_decode(duk_context *ctx, duk_idx_t idx); 1038 | DUK_EXTERNAL_DECL const char *duk_hex_encode(duk_context *ctx, duk_idx_t idx); 1039 | DUK_EXTERNAL_DECL void duk_hex_decode(duk_context *ctx, duk_idx_t idx); 1040 | DUK_EXTERNAL_DECL const char *duk_json_encode(duk_context *ctx, duk_idx_t idx); 1041 | DUK_EXTERNAL_DECL void duk_json_decode(duk_context *ctx, duk_idx_t idx); 1042 | DUK_EXTERNAL_DECL void duk_cbor_encode(duk_context *ctx, duk_idx_t idx, duk_uint_t encode_flags); 1043 | DUK_EXTERNAL_DECL void duk_cbor_decode(duk_context *ctx, duk_idx_t idx, duk_uint_t decode_flags); 1044 | 1045 | DUK_EXTERNAL_DECL const char *duk_buffer_to_string(duk_context *ctx, duk_idx_t idx); 1046 | 1047 | /* 1048 | * Buffer 1049 | */ 1050 | 1051 | DUK_EXTERNAL_DECL void *duk_resize_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t new_size); 1052 | DUK_EXTERNAL_DECL void *duk_steal_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size); 1053 | DUK_EXTERNAL_DECL void duk_config_buffer(duk_context *ctx, duk_idx_t idx, void *ptr, duk_size_t len); 1054 | 1055 | /* 1056 | * Property access 1057 | * 1058 | * The basic function assumes key is on stack. The _(l)string variant takes 1059 | * a C string as a property name; the _literal variant takes a C literal. 1060 | * The _index variant takes an array index as a property name (e.g. 123 is 1061 | * equivalent to the key "123"). The _heapptr variant takes a raw, borrowed 1062 | * heap pointer. 1063 | */ 1064 | 1065 | DUK_EXTERNAL_DECL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_idx); 1066 | DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key); 1067 | DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); 1068 | #if defined(DUK_USE_PREFER_SIZE) 1069 | #define duk_get_prop_literal(ctx,obj_idx,key) duk_get_prop_string((ctx), (obj_idx), (key)) 1070 | #else 1071 | DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_literal_raw(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); 1072 | #define duk_get_prop_literal(ctx,obj_idx,key) duk_get_prop_literal_raw((ctx), (obj_idx), (key), sizeof((key)) - 1U) 1073 | #endif 1074 | DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx); 1075 | DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr); 1076 | DUK_EXTERNAL_DECL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_idx); 1077 | DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key); 1078 | DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); 1079 | #if defined(DUK_USE_PREFER_SIZE) 1080 | #define duk_put_prop_literal(ctx,obj_idx,key) duk_put_prop_string((ctx), (obj_idx), (key)) 1081 | #else 1082 | DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_literal_raw(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); 1083 | #define duk_put_prop_literal(ctx,obj_idx,key) duk_put_prop_literal_raw((ctx), (obj_idx), (key), sizeof((key)) - 1U) 1084 | #endif 1085 | DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx); 1086 | DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr); 1087 | DUK_EXTERNAL_DECL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_idx); 1088 | DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key); 1089 | DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); 1090 | #if defined(DUK_USE_PREFER_SIZE) 1091 | #define duk_del_prop_literal(ctx,obj_idx,key) duk_del_prop_string((ctx), (obj_idx), (key)) 1092 | #else 1093 | DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_literal_raw(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); 1094 | #define duk_del_prop_literal(ctx,obj_idx,key) duk_del_prop_literal_raw((ctx), (obj_idx), (key), sizeof((key)) - 1U) 1095 | #endif 1096 | DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx); 1097 | DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr); 1098 | DUK_EXTERNAL_DECL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_idx); 1099 | DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key); 1100 | DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); 1101 | #if defined(DUK_USE_PREFER_SIZE) 1102 | #define duk_has_prop_literal(ctx,obj_idx,key) duk_has_prop_string((ctx), (obj_idx), (key)) 1103 | #else 1104 | DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_literal_raw(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); 1105 | #define duk_has_prop_literal(ctx,obj_idx,key) duk_has_prop_literal_raw((ctx), (obj_idx), (key), sizeof((key)) - 1U) 1106 | #endif 1107 | DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx); 1108 | DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr); 1109 | 1110 | DUK_EXTERNAL_DECL void duk_get_prop_desc(duk_context *ctx, duk_idx_t obj_idx, duk_uint_t flags); 1111 | DUK_EXTERNAL_DECL void duk_def_prop(duk_context *ctx, duk_idx_t obj_idx, duk_uint_t flags); 1112 | 1113 | DUK_EXTERNAL_DECL duk_bool_t duk_get_global_string(duk_context *ctx, const char *key); 1114 | DUK_EXTERNAL_DECL duk_bool_t duk_get_global_lstring(duk_context *ctx, const char *key, duk_size_t key_len); 1115 | #if defined(DUK_USE_PREFER_SIZE) 1116 | #define duk_get_global_literal(ctx,key) duk_get_global_string((ctx), (key)) 1117 | #else 1118 | DUK_EXTERNAL_DECL duk_bool_t duk_get_global_literal_raw(duk_context *ctx, const char *key, duk_size_t key_len); 1119 | #define duk_get_global_literal(ctx,key) duk_get_global_literal_raw((ctx), (key), sizeof((key)) - 1U) 1120 | #endif 1121 | DUK_EXTERNAL_DECL duk_bool_t duk_get_global_heapptr(duk_context *ctx, void *ptr); 1122 | DUK_EXTERNAL_DECL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key); 1123 | DUK_EXTERNAL_DECL duk_bool_t duk_put_global_lstring(duk_context *ctx, const char *key, duk_size_t key_len); 1124 | #if defined(DUK_USE_PREFER_SIZE) 1125 | #define duk_put_global_literal(ctx,key) duk_put_global_string((ctx), (key)) 1126 | #else 1127 | DUK_EXTERNAL_DECL duk_bool_t duk_put_global_literal_raw(duk_context *ctx, const char *key, duk_size_t key_len); 1128 | #define duk_put_global_literal(ctx,key) duk_put_global_literal_raw((ctx), (key), sizeof((key)) - 1U) 1129 | #endif 1130 | DUK_EXTERNAL_DECL duk_bool_t duk_put_global_heapptr(duk_context *ctx, void *ptr); 1131 | 1132 | /* 1133 | * Inspection 1134 | */ 1135 | 1136 | DUK_EXTERNAL_DECL void duk_inspect_value(duk_context *ctx, duk_idx_t idx); 1137 | DUK_EXTERNAL_DECL void duk_inspect_callstack_entry(duk_context *ctx, duk_int_t level); 1138 | 1139 | /* 1140 | * Object prototype 1141 | */ 1142 | 1143 | DUK_EXTERNAL_DECL void duk_get_prototype(duk_context *ctx, duk_idx_t idx); 1144 | DUK_EXTERNAL_DECL void duk_set_prototype(duk_context *ctx, duk_idx_t idx); 1145 | 1146 | /* 1147 | * Object finalizer 1148 | */ 1149 | 1150 | DUK_EXTERNAL_DECL void duk_get_finalizer(duk_context *ctx, duk_idx_t idx); 1151 | DUK_EXTERNAL_DECL void duk_set_finalizer(duk_context *ctx, duk_idx_t idx); 1152 | 1153 | /* 1154 | * Global object 1155 | */ 1156 | 1157 | DUK_EXTERNAL_DECL void duk_set_global_object(duk_context *ctx); 1158 | 1159 | /* 1160 | * Duktape/C function magic value 1161 | */ 1162 | 1163 | DUK_EXTERNAL_DECL duk_int_t duk_get_magic(duk_context *ctx, duk_idx_t idx); 1164 | DUK_EXTERNAL_DECL void duk_set_magic(duk_context *ctx, duk_idx_t idx, duk_int_t magic); 1165 | DUK_EXTERNAL_DECL duk_int_t duk_get_current_magic(duk_context *ctx); 1166 | 1167 | /* 1168 | * Module helpers: put multiple function or constant properties 1169 | */ 1170 | 1171 | DUK_EXTERNAL_DECL void duk_put_function_list(duk_context *ctx, duk_idx_t obj_idx, const duk_function_list_entry *funcs); 1172 | DUK_EXTERNAL_DECL void duk_put_number_list(duk_context *ctx, duk_idx_t obj_idx, const duk_number_list_entry *numbers); 1173 | 1174 | /* 1175 | * Object operations 1176 | */ 1177 | 1178 | DUK_EXTERNAL_DECL void duk_compact(duk_context *ctx, duk_idx_t obj_idx); 1179 | DUK_EXTERNAL_DECL void duk_enum(duk_context *ctx, duk_idx_t obj_idx, duk_uint_t enum_flags); 1180 | DUK_EXTERNAL_DECL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_idx, duk_bool_t get_value); 1181 | DUK_EXTERNAL_DECL void duk_seal(duk_context *ctx, duk_idx_t obj_idx); 1182 | DUK_EXTERNAL_DECL void duk_freeze(duk_context *ctx, duk_idx_t obj_idx); 1183 | 1184 | /* 1185 | * String manipulation 1186 | */ 1187 | 1188 | DUK_EXTERNAL_DECL void duk_concat(duk_context *ctx, duk_idx_t count); 1189 | DUK_EXTERNAL_DECL void duk_join(duk_context *ctx, duk_idx_t count); 1190 | DUK_EXTERNAL_DECL void duk_decode_string(duk_context *ctx, duk_idx_t idx, duk_decode_char_function callback, void *udata); 1191 | DUK_EXTERNAL_DECL void duk_map_string(duk_context *ctx, duk_idx_t idx, duk_map_char_function callback, void *udata); 1192 | DUK_EXTERNAL_DECL void duk_substring(duk_context *ctx, duk_idx_t idx, duk_size_t start_char_offset, duk_size_t end_char_offset); 1193 | DUK_EXTERNAL_DECL void duk_trim(duk_context *ctx, duk_idx_t idx); 1194 | DUK_EXTERNAL_DECL duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t idx, duk_size_t char_offset); 1195 | 1196 | /* 1197 | * ECMAScript operators 1198 | */ 1199 | 1200 | DUK_EXTERNAL_DECL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2); 1201 | DUK_EXTERNAL_DECL duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2); 1202 | DUK_EXTERNAL_DECL duk_bool_t duk_samevalue(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2); 1203 | DUK_EXTERNAL_DECL duk_bool_t duk_instanceof(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2); 1204 | 1205 | /* 1206 | * Random 1207 | */ 1208 | 1209 | DUK_EXTERNAL_DECL duk_double_t duk_random(duk_context *ctx); 1210 | 1211 | /* 1212 | * Function (method) calls 1213 | */ 1214 | 1215 | DUK_EXTERNAL_DECL void duk_call(duk_context *ctx, duk_idx_t nargs); 1216 | DUK_EXTERNAL_DECL void duk_call_method(duk_context *ctx, duk_idx_t nargs); 1217 | DUK_EXTERNAL_DECL void duk_call_prop(duk_context *ctx, duk_idx_t obj_idx, duk_idx_t nargs); 1218 | DUK_EXTERNAL_DECL duk_int_t duk_pcall(duk_context *ctx, duk_idx_t nargs); 1219 | DUK_EXTERNAL_DECL duk_int_t duk_pcall_method(duk_context *ctx, duk_idx_t nargs); 1220 | DUK_EXTERNAL_DECL duk_int_t duk_pcall_prop(duk_context *ctx, duk_idx_t obj_idx, duk_idx_t nargs); 1221 | DUK_EXTERNAL_DECL void duk_new(duk_context *ctx, duk_idx_t nargs); 1222 | DUK_EXTERNAL_DECL duk_int_t duk_pnew(duk_context *ctx, duk_idx_t nargs); 1223 | DUK_EXTERNAL_DECL duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, void *udata, duk_idx_t nargs, duk_idx_t nrets); 1224 | 1225 | /* 1226 | * Thread management 1227 | */ 1228 | 1229 | /* There are currently no native functions to yield/resume, due to the internal 1230 | * limitations on coroutine handling. These will be added later. 1231 | */ 1232 | 1233 | /* 1234 | * Compilation and evaluation 1235 | */ 1236 | 1237 | DUK_EXTERNAL_DECL duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags); 1238 | DUK_EXTERNAL_DECL duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags); 1239 | 1240 | /* plain */ 1241 | #define duk_eval(ctx) \ 1242 | ((void) duk_eval_raw((ctx), NULL, 0, 1 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOFILENAME)) 1243 | 1244 | #define duk_eval_noresult(ctx) \ 1245 | ((void) duk_eval_raw((ctx), NULL, 0, 1 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME)) 1246 | 1247 | #define duk_peval(ctx) \ 1248 | (duk_eval_raw((ctx), NULL, 0, 1 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOFILENAME)) 1249 | 1250 | #define duk_peval_noresult(ctx) \ 1251 | (duk_eval_raw((ctx), NULL, 0, 1 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME)) 1252 | 1253 | #define duk_compile(ctx,flags) \ 1254 | ((void) duk_compile_raw((ctx), NULL, 0, 2 /*args*/ | (flags))) 1255 | 1256 | #define duk_pcompile(ctx,flags) \ 1257 | (duk_compile_raw((ctx), NULL, 0, 2 /*args*/ | (flags) | DUK_COMPILE_SAFE)) 1258 | 1259 | /* string */ 1260 | #define duk_eval_string(ctx,src) \ 1261 | ((void) duk_eval_raw((ctx), (src), 0, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NOFILENAME)) 1262 | 1263 | #define duk_eval_string_noresult(ctx,src) \ 1264 | ((void) duk_eval_raw((ctx), (src), 0, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME)) 1265 | 1266 | #define duk_peval_string(ctx,src) \ 1267 | (duk_eval_raw((ctx), (src), 0, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NOFILENAME)) 1268 | 1269 | #define duk_peval_string_noresult(ctx,src) \ 1270 | (duk_eval_raw((ctx), (src), 0, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME)) 1271 | 1272 | #define duk_compile_string(ctx,flags,src) \ 1273 | ((void) duk_compile_raw((ctx), (src), 0, 0 /*args*/ | (flags) | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NOFILENAME)) 1274 | 1275 | #define duk_compile_string_filename(ctx,flags,src) \ 1276 | ((void) duk_compile_raw((ctx), (src), 0, 1 /*args*/ | (flags) | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN)) 1277 | 1278 | #define duk_pcompile_string(ctx,flags,src) \ 1279 | (duk_compile_raw((ctx), (src), 0, 0 /*args*/ | (flags) | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NOFILENAME)) 1280 | 1281 | #define duk_pcompile_string_filename(ctx,flags,src) \ 1282 | (duk_compile_raw((ctx), (src), 0, 1 /*args*/ | (flags) | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN)) 1283 | 1284 | /* lstring */ 1285 | #define duk_eval_lstring(ctx,buf,len) \ 1286 | ((void) duk_eval_raw((ctx), buf, len, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_NOFILENAME)) 1287 | 1288 | #define duk_eval_lstring_noresult(ctx,buf,len) \ 1289 | ((void) duk_eval_raw((ctx), buf, len, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME)) 1290 | 1291 | #define duk_peval_lstring(ctx,buf,len) \ 1292 | (duk_eval_raw((ctx), buf, len, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_SAFE | DUK_COMPILE_NOFILENAME)) 1293 | 1294 | #define duk_peval_lstring_noresult(ctx,buf,len) \ 1295 | (duk_eval_raw((ctx), buf, len, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME)) 1296 | 1297 | #define duk_compile_lstring(ctx,flags,buf,len) \ 1298 | ((void) duk_compile_raw((ctx), buf, len, 0 /*args*/ | (flags) | DUK_COMPILE_NOSOURCE | DUK_COMPILE_NOFILENAME)) 1299 | 1300 | #define duk_compile_lstring_filename(ctx,flags,buf,len) \ 1301 | ((void) duk_compile_raw((ctx), buf, len, 1 /*args*/ | (flags) | DUK_COMPILE_NOSOURCE)) 1302 | 1303 | #define duk_pcompile_lstring(ctx,flags,buf,len) \ 1304 | (duk_compile_raw((ctx), buf, len, 0 /*args*/ | (flags) | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_NOFILENAME)) 1305 | 1306 | #define duk_pcompile_lstring_filename(ctx,flags,buf,len) \ 1307 | (duk_compile_raw((ctx), buf, len, 1 /*args*/ | (flags) | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE)) 1308 | 1309 | /* 1310 | * Bytecode load/dump 1311 | */ 1312 | 1313 | DUK_EXTERNAL_DECL void duk_dump_function(duk_context *ctx); 1314 | DUK_EXTERNAL_DECL void duk_load_function(duk_context *ctx); 1315 | 1316 | /* 1317 | * Debugging 1318 | */ 1319 | 1320 | DUK_EXTERNAL_DECL void duk_push_context_dump(duk_context *ctx); 1321 | 1322 | /* 1323 | * Debugger (debug protocol) 1324 | */ 1325 | 1326 | DUK_EXTERNAL_DECL void duk_debugger_attach(duk_context *ctx, 1327 | duk_debug_read_function read_cb, 1328 | duk_debug_write_function write_cb, 1329 | duk_debug_peek_function peek_cb, 1330 | duk_debug_read_flush_function read_flush_cb, 1331 | duk_debug_write_flush_function write_flush_cb, 1332 | duk_debug_request_function request_cb, 1333 | duk_debug_detached_function detached_cb, 1334 | void *udata); 1335 | DUK_EXTERNAL_DECL void duk_debugger_detach(duk_context *ctx); 1336 | DUK_EXTERNAL_DECL void duk_debugger_cooperate(duk_context *ctx); 1337 | DUK_EXTERNAL_DECL duk_bool_t duk_debugger_notify(duk_context *ctx, duk_idx_t nvalues); 1338 | DUK_EXTERNAL_DECL void duk_debugger_pause(duk_context *ctx); 1339 | 1340 | /* 1341 | * Time handling 1342 | */ 1343 | 1344 | DUK_EXTERNAL_DECL duk_double_t duk_get_now(duk_context *ctx); 1345 | DUK_EXTERNAL_DECL void duk_time_to_components(duk_context *ctx, duk_double_t timeval, duk_time_components *comp); 1346 | DUK_EXTERNAL_DECL duk_double_t duk_components_to_time(duk_context *ctx, duk_time_components *comp); 1347 | 1348 | /* 1349 | * Date provider related constants 1350 | * 1351 | * NOTE: These are "semi public" - you should only use these if you write 1352 | * your own platform specific Date provider, see doc/datetime.rst. 1353 | */ 1354 | 1355 | /* Millisecond count constants. */ 1356 | #define DUK_DATE_MSEC_SECOND 1000L 1357 | #define DUK_DATE_MSEC_MINUTE (60L * 1000L) 1358 | #define DUK_DATE_MSEC_HOUR (60L * 60L * 1000L) 1359 | #define DUK_DATE_MSEC_DAY (24L * 60L * 60L * 1000L) 1360 | 1361 | /* ECMAScript date range is 100 million days from Epoch: 1362 | * > 100e6 * 24 * 60 * 60 * 1000 // 100M days in millisecs 1363 | * 8640000000000000 1364 | * (= 8.64e15) 1365 | */ 1366 | #define DUK_DATE_MSEC_100M_DAYS (8.64e15) 1367 | #define DUK_DATE_MSEC_100M_DAYS_LEEWAY (8.64e15 + 24 * 3600e3) 1368 | 1369 | /* ECMAScript year range: 1370 | * > new Date(100e6 * 24 * 3600e3).toISOString() 1371 | * '+275760-09-13T00:00:00.000Z' 1372 | * > new Date(-100e6 * 24 * 3600e3).toISOString() 1373 | * '-271821-04-20T00:00:00.000Z' 1374 | */ 1375 | #define DUK_DATE_MIN_ECMA_YEAR (-271821L) 1376 | #define DUK_DATE_MAX_ECMA_YEAR 275760L 1377 | 1378 | /* Part indices for internal breakdowns. Part order from DUK_DATE_IDX_YEAR 1379 | * to DUK_DATE_IDX_MILLISECOND matches argument ordering of ECMAScript API 1380 | * calls (like Date constructor call). Some functions in duk_bi_date.c 1381 | * depend on the specific ordering, so change with care. 16 bits are not 1382 | * enough for all parts (year, specifically). 1383 | * 1384 | * Must be in-sync with genbuiltins.py. 1385 | */ 1386 | #define DUK_DATE_IDX_YEAR 0 /* year */ 1387 | #define DUK_DATE_IDX_MONTH 1 /* month: 0 to 11 */ 1388 | #define DUK_DATE_IDX_DAY 2 /* day within month: 0 to 30 */ 1389 | #define DUK_DATE_IDX_HOUR 3 1390 | #define DUK_DATE_IDX_MINUTE 4 1391 | #define DUK_DATE_IDX_SECOND 5 1392 | #define DUK_DATE_IDX_MILLISECOND 6 1393 | #define DUK_DATE_IDX_WEEKDAY 7 /* weekday: 0 to 6, 0=sunday, 1=monday, etc */ 1394 | #define DUK_DATE_IDX_NUM_PARTS 8 1395 | 1396 | /* Internal API call flags, used for various functions in duk_bi_date.c. 1397 | * Certain flags are used by only certain functions, but since the flags 1398 | * don't overlap, a single flags value can be passed around to multiple 1399 | * functions. 1400 | * 1401 | * The unused top bits of the flags field are also used to pass values 1402 | * to helpers (duk__get_part_helper() and duk__set_part_helper()). 1403 | * 1404 | * Must be in-sync with genbuiltins.py. 1405 | */ 1406 | 1407 | /* NOTE: when writing a Date provider you only need a few specific 1408 | * flags from here, the rest are internal. Avoid using anything you 1409 | * don't need. 1410 | */ 1411 | 1412 | #define DUK_DATE_FLAG_NAN_TO_ZERO (1 << 0) /* timeval breakdown: internal time value NaN -> zero */ 1413 | #define DUK_DATE_FLAG_NAN_TO_RANGE_ERROR (1 << 1) /* timeval breakdown: internal time value NaN -> RangeError (toISOString) */ 1414 | #define DUK_DATE_FLAG_ONEBASED (1 << 2) /* timeval breakdown: convert month and day-of-month parts to one-based (default is zero-based) */ 1415 | #define DUK_DATE_FLAG_EQUIVYEAR (1 << 3) /* timeval breakdown: replace year with equivalent year in the [1971,2037] range for DST calculations */ 1416 | #define DUK_DATE_FLAG_LOCALTIME (1 << 4) /* convert time value to local time */ 1417 | #define DUK_DATE_FLAG_SUB1900 (1 << 5) /* getter: subtract 1900 from year when getting year part */ 1418 | #define DUK_DATE_FLAG_TOSTRING_DATE (1 << 6) /* include date part in string conversion result */ 1419 | #define DUK_DATE_FLAG_TOSTRING_TIME (1 << 7) /* include time part in string conversion result */ 1420 | #define DUK_DATE_FLAG_TOSTRING_LOCALE (1 << 8) /* use locale specific formatting if available */ 1421 | #define DUK_DATE_FLAG_TIMESETTER (1 << 9) /* setter: call is a time setter (affects hour, min, sec, ms); otherwise date setter (affects year, month, day-in-month) */ 1422 | #define DUK_DATE_FLAG_YEAR_FIXUP (1 << 10) /* setter: perform 2-digit year fixup (00...99 -> 1900...1999) */ 1423 | #define DUK_DATE_FLAG_SEP_T (1 << 11) /* string conversion: use 'T' instead of ' ' as a separator */ 1424 | #define DUK_DATE_FLAG_VALUE_SHIFT 12 /* additional values begin at bit 12 */ 1425 | 1426 | /* 1427 | * ROM pointer compression 1428 | */ 1429 | 1430 | /* Support array for ROM pointer compression. Only declared when ROM 1431 | * pointer compression is active. 1432 | */ 1433 | #if defined(DUK_USE_ROM_OBJECTS) && defined(DUK_USE_HEAPPTR16) 1434 | DUK_EXTERNAL_DECL const void * const duk_rom_compressed_pointers[]; 1435 | #endif 1436 | 1437 | /* 1438 | * C++ name mangling 1439 | */ 1440 | 1441 | #if defined(__cplusplus) 1442 | /* end 'extern "C"' wrapper */ 1443 | } 1444 | #endif 1445 | 1446 | /* 1447 | * END PUBLIC API 1448 | */ 1449 | 1450 | #endif /* DUKTAPE_H_INCLUDED */ 1451 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | // should the JavaScript be supported? 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef WITH_JAVASCRIPT 10 | #include "duktape.h" 11 | #endif 12 | 13 | #define ERROR_EXIT_CODE 20000 14 | 15 | #define TARGET_EXE_RESOURCE 1 16 | 17 | #ifdef WITH_JAVASCRIPT 18 | static JavaVM *javaVM = 0; 19 | static JNIEnv *jniEnv = 0; 20 | #endif 21 | 22 | /** 23 | * @brief converts a string to UTF-16 24 | * @param s UTF-8 25 | * @return new UTF-16 string 26 | */ 27 | static wchar_t* toUTF16(const char* s) 28 | { 29 | int n = strlen(s); 30 | 31 | int sz = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s, n, NULL, 0); 32 | wchar_t* r = malloc(sz * sizeof(wchar_t)); 33 | sz = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s, n, r, sz); 34 | *(r + sz) = 0; 35 | 36 | return r; 37 | } 38 | 39 | /** 40 | * @brief prints an error message 41 | * @param msg message, e.g. "failed to start the target process" 42 | * @param err error code returned by GetLastError() 43 | */ 44 | static void printError(const char* msg, DWORD err) { 45 | HLOCAL pBuffer; 46 | DWORD n; 47 | 48 | /*if (err >= INTERNET_ERROR_BASE && err <= INTERNET_ERROR_LAST) { 49 | // wininet.dll-errors 50 | n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | 51 | FORMAT_MESSAGE_FROM_HMODULE, 52 | GetModuleHandle(L"wininet.dll"), 53 | err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 54 | (LPTSTR)&pBuffer, 0, nullptr); 55 | } else */{ 56 | n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | 57 | FORMAT_MESSAGE_FROM_SYSTEM, 58 | NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 59 | (LPTSTR)&pBuffer, 0, NULL); 60 | } 61 | wchar_t* wmsg = toUTF16(msg); 62 | if (n == 0) 63 | wprintf(L"Error %d: %ls\n", err, wmsg); 64 | else { 65 | wprintf(L"Error %d: %ls: %ls\n", err, wmsg, pBuffer); 66 | LocalFree(pBuffer); 67 | } 68 | free(wmsg); 69 | } 70 | 71 | 72 | /** 73 | * @brief full path to the current exe file 74 | * @return path that must be freed later or 0 if an error occures 75 | */ 76 | static wchar_t* getExePath() 77 | { 78 | // get our executable name 79 | DWORD sz = MAX_PATH; 80 | LPTSTR exe; 81 | while (true) { 82 | exe = malloc(sz * sizeof(TCHAR)); 83 | if (GetModuleFileName(0, exe, sz) != sz) 84 | break; 85 | 86 | free(exe); 87 | sz = sz * 2; 88 | } 89 | 90 | return exe; 91 | } 92 | 93 | typedef struct { 94 | HANDLE hUpdateRes; 95 | } EnumResourcesData; 96 | 97 | static WINBOOL CALLBACK enumResources(HMODULE hModule, LPCWSTR lpType, LPWSTR lpName, 98 | LONG_PTR lParam) 99 | { 100 | EnumResourcesData* data = (EnumResourcesData*) lParam; 101 | 102 | HRSRC hRes = FindResource(hModule, lpName, lpType); 103 | 104 | HRSRC hResLoad = NULL; 105 | if (hRes != NULL) { 106 | //wprintf(L"Loading the icon resource\n"); 107 | 108 | // Load the ICON into global memory. 109 | hResLoad = (HRSRC)LoadResource(hModule, hRes); 110 | } 111 | 112 | // pointer to resource data 113 | char *lpResLock = 0; 114 | if (hResLoad != NULL) { 115 | //wprintf(L"Locking the icon resource\n"); 116 | 117 | // Lock the ICON into global memory. 118 | lpResLock = (char*)LockResource(hResLoad); 119 | } 120 | 121 | if (lpResLock) { 122 | //wprintf(L"Updating the icon resource\n"); 123 | 124 | if (!UpdateResource(data->hUpdateRes, 125 | lpType, 126 | lpName, 127 | MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 128 | lpResLock, 129 | SizeofResource(hModule, hRes))) { 130 | printError("failed to update the resource", GetLastError()); 131 | } 132 | } 133 | 134 | return TRUE; 135 | } 136 | 137 | /** 138 | * @brief copies the icon from one file to another 139 | * 140 | * @param hUpdateRes result of BeginUpdateResource 141 | * @param lpszSourceFile file with the icon 142 | * @param copyIcon should the icons and icon groups be copied 143 | * @param copyVersion should the version information be copied 144 | * @param copyManifest should the executable manifest be copied 145 | */ 146 | static void copyResources(HANDLE hUpdateRes, LPCWSTR lpszSourceFile, bool copyIcon, 147 | bool copyVersion, bool copyManifest) 148 | { 149 | //wprintf(L"Copying the icon\n"); 150 | //wprintf(lpszSourceFile); 151 | 152 | // Load the source exe from where we need the icon 153 | HMODULE hSrcExe = LoadLibraryEx(lpszSourceFile, NULL, 154 | LOAD_LIBRARY_AS_IMAGE_RESOURCE); 155 | 156 | DWORD err = GetLastError(); 157 | if (err) { 158 | printError("failed to load the executable as a resource", err); 159 | } 160 | 161 | if (hSrcExe != NULL) { 162 | // wprintf(L"Searching for the icon\n"); 163 | 164 | EnumResourcesData data = {0}; 165 | data.hUpdateRes = hUpdateRes; 166 | 167 | if (copyIcon) { 168 | EnumResourceNames(hSrcExe, MAKEINTRESOURCE(RT_ICON), enumResources, 169 | (LONG_PTR) &data); 170 | EnumResourceNames(hSrcExe, MAKEINTRESOURCE(RT_GROUP_ICON), 171 | enumResources, (LONG_PTR) &data); 172 | } 173 | if (copyVersion) { 174 | EnumResourceNames(hSrcExe, MAKEINTRESOURCE(RT_VERSION), 175 | enumResources, (LONG_PTR) &data); 176 | } 177 | if (copyManifest) { 178 | EnumResourceNames(hSrcExe, MAKEINTRESOURCE(RT_MANIFEST), 179 | enumResources, (LONG_PTR) &data); 180 | } 181 | } 182 | 183 | if (hSrcExe != NULL) { 184 | FreeLibrary(hSrcExe); 185 | } 186 | } 187 | 188 | static int copyExe(wchar_t* exeProxy, wchar_t* target, bool copyIcon, 189 | bool copyVersion, bool copyManifest) 190 | { 191 | int ret = 0; 192 | 193 | wchar_t* exe = getExePath(); 194 | if (!exe) { 195 | ret = ERROR_EXIT_CODE; 196 | printf("Cannot determine the name of this executable\n"); 197 | } 198 | 199 | if (!ret) { 200 | if (!CopyFile(exe, exeProxy, TRUE)) { 201 | ret = ERROR_EXIT_CODE; 202 | printError("Copying the executable failed", GetLastError()); 203 | } 204 | } 205 | 206 | free(exe); 207 | 208 | HANDLE hUpdateRes = 0; 209 | if (!ret) { 210 | hUpdateRes = BeginUpdateResource(exeProxy, TRUE); 211 | if (!hUpdateRes) { 212 | ret = ERROR_EXIT_CODE; 213 | printError("BeginUpdateResource failed", GetLastError()); 214 | } 215 | } 216 | 217 | // set the path to the target .exe file in the resource string 218 | if (!ret) { 219 | // Resource strings are stored in groups of 16. 220 | // Each string is preceeded by its size. 221 | size_t targetLen = wcslen(target); 222 | size_t bufSize = (targetLen + 16) * sizeof(wchar_t); 223 | wchar_t* buf = malloc(bufSize); 224 | memset(buf, 0, bufSize); 225 | buf[1] = targetLen; 226 | wcscpy(buf + 2, target); 227 | 228 | if (!UpdateResource(hUpdateRes, 229 | RT_STRING, 230 | MAKEINTRESOURCE(TARGET_EXE_RESOURCE), 231 | MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), 232 | buf, 233 | bufSize)) { 234 | ret = ERROR_EXIT_CODE; 235 | printError("UpdateResource failed", GetLastError()); 236 | } 237 | } 238 | 239 | if (!ret) { 240 | copyResources(hUpdateRes, target, copyIcon, copyVersion, copyManifest); 241 | } 242 | 243 | if (!ret) { 244 | if (!EndUpdateResource(hUpdateRes, FALSE)) { 245 | ret = ERROR_EXIT_CODE; 246 | printError("EndUpdateResource failed", GetLastError()); 247 | } 248 | } 249 | 250 | return ret; 251 | } 252 | 253 | PROCESS_INFORMATION pinfo; 254 | 255 | static BOOL WINAPI ctrlHandler(DWORD fdwCtrlType) 256 | { 257 | //wprintf(L"ctrlHandler\n"); 258 | switch (fdwCtrlType) { 259 | case CTRL_C_EVENT: 260 | GenerateConsoleCtrlEvent(CTRL_C_EVENT, pinfo.dwProcessId); 261 | break; 262 | case CTRL_CLOSE_EVENT: 263 | case CTRL_BREAK_EVENT: 264 | case CTRL_LOGOFF_EVENT: 265 | case CTRL_SHUTDOWN_EVENT: 266 | GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pinfo.dwProcessId); 267 | break; 268 | } 269 | 270 | WaitForSingleObject(pinfo.hProcess, 1000); 271 | 272 | DWORD ec; 273 | if (GetExitCodeProcess(pinfo.hProcess, &ec) && (ec == STILL_ACTIVE)) { 274 | TerminateProcess(pinfo.hProcess, 1); 275 | } 276 | 277 | return FALSE; 278 | } 279 | 280 | /** 281 | * @brief executes a program 282 | * @param cmdLine command line 283 | * @return exit code 284 | */ 285 | static int exec(wchar_t* cmdLine) 286 | { 287 | int ret = 0; 288 | 289 | int numArgs; 290 | LPWSTR* args = CommandLineToArgvW(cmdLine, &numArgs); 291 | 292 | STARTUPINFOW startupInfo = { 293 | sizeof(STARTUPINFO), 0, 0, 0, 294 | (DWORD) CW_USEDEFAULT, (DWORD) CW_USEDEFAULT, 295 | (DWORD) CW_USEDEFAULT, (DWORD) CW_USEDEFAULT, 296 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 297 | }; 298 | WINBOOL success = CreateProcess( 299 | numArgs > 0 ? args[0] : L"", 300 | cmdLine, 301 | 0, 0, TRUE, 302 | CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_PROCESS_GROUP, 0, 303 | 0, &startupInfo, &pinfo); 304 | 305 | 306 | if (success) { 307 | SetConsoleCtrlHandler(ctrlHandler, TRUE); 308 | 309 | WaitForSingleObject(pinfo.hProcess, INFINITE); 310 | DWORD ec; 311 | if (GetExitCodeProcess(pinfo.hProcess, &ec)) 312 | ret = ec; 313 | else 314 | ret = ERROR_EXIT_CODE; 315 | CloseHandle(pinfo.hThread); 316 | CloseHandle(pinfo.hProcess); 317 | } else { 318 | printError("error starting the target program", GetLastError()); 319 | wprintf(L"Error starting %ls\n", cmdLine); 320 | ret = ERROR_EXIT_CODE; 321 | } 322 | 323 | LocalFree(args); 324 | 325 | return ret; 326 | } 327 | 328 | #ifdef WITH_JAVASCRIPT 329 | 330 | static char* replaceChar(char* str, char find, char replace){ 331 | char *current_pos = strchr(str, find); 332 | while (current_pos) { 333 | *current_pos = replace; 334 | current_pos = strchr(current_pos + 1, find); 335 | } 336 | return str; 337 | } 338 | 339 | static duk_ret_t native_execSync(duk_context *ctx) 340 | { 341 | const char* cmdLine = duk_safe_to_string(ctx, 0); 342 | 343 | wchar_t* wcmdLine = toUTF16(cmdLine); 344 | 345 | int ec = exec(wcmdLine); 346 | 347 | free(wcmdLine); 348 | 349 | duk_push_number(ctx, ec); 350 | 351 | return 1; /* one return value */ 352 | } 353 | 354 | static duk_ret_t native_log(duk_context *ctx) 355 | { 356 | printf("%s\n", duk_safe_to_string(ctx, 0)); 357 | 358 | return 0; 359 | } 360 | 361 | static duk_ret_t native_exit(duk_context *ctx) 362 | { 363 | int ec = duk_to_int(ctx, 0); 364 | 365 | exit(ec); 366 | } 367 | 368 | static duk_ret_t native_totalmem(duk_context *ctx) 369 | { 370 | MEMORYSTATUSEX statex; 371 | 372 | statex.dwLength = sizeof(statex); 373 | 374 | GlobalMemoryStatusEx(&statex); 375 | 376 | duk_push_number(ctx, statex.ullTotalPhys); 377 | 378 | return 1; 379 | } 380 | 381 | static duk_ret_t native_javaCallMain(duk_context* ctx) 382 | { 383 | bool err = false; 384 | 385 | const char* class = duk_safe_to_string(ctx, 0); 386 | 387 | jclass jcls; 388 | if (!err) { 389 | char* classSlashes = strdup(class); 390 | replaceChar(classSlashes, '.' , '/'); 391 | jcls = (*jniEnv)->FindClass(jniEnv, classSlashes); 392 | if (jcls == NULL) { 393 | (*jniEnv)->ExceptionDescribe(jniEnv); 394 | err = true; 395 | } 396 | free(classSlashes); 397 | } 398 | 399 | jmethodID methodId; 400 | if (!err) { 401 | methodId = (*jniEnv)->GetStaticMethodID(jniEnv, jcls, 402 | "main", "([Ljava/lang/String;)V"); 403 | if (methodId == NULL) { 404 | printf("Cannot find the main() method.\n"); 405 | err = true; 406 | } 407 | } 408 | 409 | jclass stringClass; 410 | if (!err) { 411 | stringClass = (*jniEnv)->FindClass(jniEnv, "java/lang/String"); 412 | if(stringClass == NULL) { 413 | printf("Could not find String class\n"); 414 | err = true; 415 | } 416 | } 417 | 418 | if (!err) { 419 | // Create the run args 420 | int argc = duk_get_length(ctx, 1); 421 | jobjectArray args = (*jniEnv)->NewObjectArray(jniEnv, argc, stringClass, NULL); 422 | for(int i = 0; i < argc; i++) { 423 | duk_get_prop_index(ctx, 1, i); 424 | const char* val = duk_safe_to_string(ctx, -1); 425 | duk_pop(ctx); 426 | (*jniEnv)->SetObjectArrayElement(jniEnv, args, i, (*jniEnv)->NewStringUTF(jniEnv, val)); 427 | } 428 | 429 | (*jniEnv)->CallStaticVoidMethod(jniEnv, jcls, methodId, args); 430 | if ((*jniEnv)->ExceptionCheck(jniEnv)) { 431 | (*jniEnv)->ExceptionDescribe(jniEnv); 432 | (*jniEnv)->ExceptionClear(jniEnv); 433 | } 434 | } 435 | 436 | return 0; 437 | } 438 | 439 | static duk_ret_t native_jvm(duk_context *ctx) 440 | { 441 | bool err = false; 442 | 443 | duk_get_prop_string(ctx, 0, "jvmDLL"); 444 | const char* dll = duk_safe_to_string(ctx, -1); 445 | duk_pop(ctx); 446 | 447 | wchar_t* wdll = toUTF16(dll); 448 | 449 | HMODULE m = LoadLibrary(wdll); 450 | if (m == NULL) { 451 | printError("failed to load the JVM DLL", GetLastError()); 452 | err = true; 453 | } 454 | 455 | typedef jint (JNICALL *JNI_createJavaVM)(JavaVM **pvm, JNIEnv **env, void *args); 456 | JNI_createJavaVM createJavaVM; 457 | if (!err) { 458 | createJavaVM = (JNI_createJavaVM) GetProcAddress(m, "JNI_CreateJavaVM"); 459 | if (createJavaVM == NULL) { 460 | printError("failed to find the procedure JNI_CreateJavaVM in the DLL", GetLastError()); 461 | } 462 | } 463 | 464 | if (!err) { 465 | // Create the JVM options 466 | duk_get_prop_string(ctx, 0, "jvmOptions"); 467 | int argc = duk_get_length(ctx, -1); 468 | JavaVMOption* jvmopt = malloc(argc * sizeof(JavaVMOption)); 469 | for(int i = 0; i < argc; i++) { 470 | duk_get_prop_index(ctx, -1, i); 471 | const char* val = duk_safe_to_string(ctx, -1); 472 | duk_pop(ctx); 473 | jvmopt[i].optionString = (char*) val; 474 | jvmopt[i].extraInfo = 0; 475 | } 476 | 477 | JavaVMInitArgs vmArgs; 478 | vmArgs.version = JNI_VERSION_1_2; 479 | vmArgs.nOptions = 1; 480 | vmArgs.options = jvmopt; 481 | vmArgs.ignoreUnrecognized = JNI_TRUE; 482 | 483 | // Create the JVM 484 | long flag = createJavaVM(&javaVM, &jniEnv, &vmArgs); 485 | if (flag == JNI_ERR) { 486 | printf("Error creating VM.\n"); 487 | err = true; 488 | } 489 | 490 | free(jvmopt); 491 | } 492 | 493 | free(wdll); 494 | 495 | return 0; 496 | } 497 | 498 | /** 499 | * @brief converts a string to UTF-8 500 | * @param s UTF-16 501 | * @return new UTF-8 string 502 | */ 503 | static char* toUTF8(wchar_t* s) 504 | { 505 | int n = wcslen(s); 506 | 507 | int sz = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS | WC_NO_BEST_FIT_CHARS, s, n, NULL, 0, NULL, NULL); 508 | char* r = malloc(sz); 509 | sz = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS | WC_NO_BEST_FIT_CHARS, s, n, r, sz, NULL, NULL); 510 | *(r + sz) = 0; 511 | 512 | return r; 513 | } 514 | 515 | /** 516 | * @brief executes JavaScript 517 | * @param js JavaScript as UTF-8 518 | * @param executable path to this executable as UTF-8 519 | * @return error code or 0 520 | */ 521 | static int executeJS(char* js, char* executable) 522 | { 523 | //wprintf(L"executeJS()"); 524 | 525 | int ret = 0; 526 | 527 | duk_context *ctx = duk_create_heap_default(); 528 | 529 | { 530 | // process 531 | duk_push_object(ctx); /* push object which will become "process" */ 532 | 533 | duk_push_c_function(ctx, native_exit, 1); 534 | duk_put_prop_string(ctx, -2, "exit"); 535 | 536 | duk_push_c_function(ctx, native_jvm, 1); 537 | duk_put_prop_string(ctx, -2, "loadJVM"); 538 | 539 | duk_push_c_function(ctx, native_javaCallMain, 2); 540 | duk_put_prop_string(ctx, -2, "javaCallMain"); 541 | 542 | duk_push_string(ctx, "argv0"); 543 | duk_push_string(ctx, executable); 544 | duk_put_prop(ctx, -3); 545 | 546 | int numArgs; 547 | LPTSTR cmdLine = GetCommandLine(); 548 | LPWSTR* args = CommandLineToArgvW(cmdLine, &numArgs); 549 | duk_push_string(ctx, "argv"); 550 | duk_idx_t arr_idx = duk_push_array(ctx); 551 | for (int i = 0; i < numArgs; i++) { 552 | char* val = toUTF8(args[i]); 553 | duk_push_string(ctx, val); 554 | duk_put_prop_index(ctx, arr_idx, i); 555 | free(val); 556 | } 557 | duk_put_prop(ctx, -3); 558 | LocalFree(args); 559 | 560 | duk_put_global_string(ctx, "process"); /* set "process" into the global object */ 561 | } 562 | 563 | { 564 | // child_process 565 | duk_push_object(ctx); 566 | 567 | duk_push_c_function(ctx, native_execSync, 1); 568 | duk_put_prop_string(ctx, -2, "execSync"); 569 | 570 | duk_put_global_string(ctx, "child_process"); 571 | } 572 | 573 | { 574 | // os 575 | duk_push_object(ctx); 576 | 577 | duk_push_c_function(ctx, native_totalmem, 0); 578 | duk_put_prop_string(ctx, -2, "totalmem"); 579 | 580 | duk_put_global_string(ctx, "os"); 581 | } 582 | 583 | { 584 | // console 585 | duk_push_object(ctx); 586 | 587 | duk_push_c_function(ctx, native_log, 1); 588 | duk_put_prop_string(ctx, -2, "log"); 589 | 590 | duk_put_global_string(ctx, "console"); 591 | } 592 | 593 | duk_int_t rc = duk_peval_string(ctx, js); 594 | if (rc != 0) { 595 | printf("JavaScript evaluation failed: %s\n", duk_safe_to_string(ctx, -1)); 596 | ret = 1; 597 | } 598 | 599 | duk_pop(ctx); /* pop eval result */ 600 | 601 | duk_destroy_heap(ctx); 602 | 603 | return ret; 604 | } 605 | 606 | /** 607 | * @brief reads a JavaScript file 608 | * @param filename ".js" 609 | * @param js the source as UTF-8 will be stored here 610 | * @return error code or 0 611 | */ 612 | static int readJS(wchar_t* filename, char** js) 613 | { 614 | //wprintf(L"readJS()"); 615 | 616 | *js = 0; 617 | 618 | int err = 0; 619 | 620 | HANDLE f = CreateFile(filename, GENERIC_READ, 621 | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 622 | if (f == INVALID_HANDLE_VALUE) { 623 | err = 1; 624 | printError("failed accessing the JavaScript file", GetLastError()); 625 | } 626 | 627 | LARGE_INTEGER sz; 628 | if (!err) { 629 | if (!GetFileSizeEx(f, &sz)) { 630 | err = 1; 631 | printError("failed getting the size of the JavaScript file", GetLastError()); 632 | } 633 | } 634 | 635 | if (!err) { 636 | if (sz.HighPart > 0 || sz.LowPart > 100 * 1024 * 1024) { 637 | err = 1; 638 | printf("JavaScript file is too big\n"); 639 | } 640 | } 641 | 642 | if (!err) { 643 | *js = malloc(sz.LowPart + 1); 644 | 645 | DWORD read; 646 | if (!ReadFile(f, *js, sz.LowPart, &read, NULL)) { 647 | err = 1; 648 | printError("failed reading the JavaScript file", GetLastError()); 649 | } else { 650 | *(*js + read) = 0; 651 | } 652 | } 653 | 654 | if (err) { 655 | free(*js); 656 | *js = 0; 657 | } 658 | 659 | if (f != INVALID_HANDLE_VALUE) 660 | CloseHandle(f); 661 | 662 | return err; 663 | } 664 | 665 | #endif 666 | 667 | BOOL fileExists(LPCTSTR szPath) 668 | { 669 | DWORD dwAttrib = GetFileAttributes(szPath); 670 | 671 | return (dwAttrib != INVALID_FILE_ATTRIBUTES && 672 | !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); 673 | } 674 | 675 | int wmain(int argc, wchar_t **argv) 676 | { 677 | //wprintf(L"main()"); 678 | 679 | int ret = 0; 680 | 681 | if (argc >= 4 && wcscmp(argv[1], L"exeproxy-copy") == 0) { 682 | bool copyIcon = false; 683 | bool copyVersion = false; 684 | bool copyManifest = false; 685 | for (int i = 4; i < argc; i++) { 686 | if (wcscmp(argv[i], L"--copy-icons") == 0) 687 | copyIcon = true; 688 | else if (wcscmp(argv[i], L"--copy-version") == 0) 689 | copyVersion = true; 690 | else if (wcscmp(argv[i], L"--copy-manifest") == 0) 691 | copyManifest = true; 692 | } 693 | ret = copyExe(argv[2], argv[3], copyIcon, copyVersion, copyManifest); 694 | return ret; 695 | } 696 | 697 | wchar_t* exe = getExePath(); 698 | if (!exe) { 699 | ret = ERROR_EXIT_CODE; 700 | printf("Cannot determine the name of this executable\n"); 701 | } 702 | 703 | // extract parameters 704 | LPTSTR cl = GetCommandLine(); 705 | LPTSTR args = 0; 706 | if (!ret) { 707 | if (*cl == L'"') { 708 | LPTSTR second = wcschr(cl + 1, '"'); 709 | if (!second) { 710 | args = wcschr(cl, L' '); 711 | if (!args) 712 | args = wcsdup(L""); 713 | else 714 | args = wcsdup(args + 1); 715 | } else { 716 | args = wcsdup(second + 1); 717 | } 718 | } else { 719 | args = wcschr(cl, L' '); 720 | if (!args) 721 | args = wcsdup(L""); 722 | else 723 | args = wcsdup(args + 1); 724 | } 725 | } 726 | 727 | #ifdef WITH_JAVASCRIPT 728 | // find the name of the .js file 729 | wchar_t* javaScript = 0; 730 | if (!ret) { 731 | javaScript = wcsdup(exe); 732 | _wcslwr(javaScript); 733 | int len = wcslen(javaScript); 734 | if (len > 4 && wcscmp(L".exe", javaScript + len - 4) == 0) { 735 | wchar_t* p = javaScript + len - 3; 736 | *p = 'j'; 737 | p++; 738 | *p = 's'; 739 | p++; 740 | *p = 0; 741 | } else { 742 | ret = ERROR_EXIT_CODE; 743 | printf("Program name does not end with .exe\n"); 744 | } 745 | } 746 | 747 | if (!ret) { 748 | if (fileExists(javaScript)) { 749 | char* js = 0; 750 | //wprintf(L"Reading %s", javaScript); 751 | if (readJS(javaScript, &js) != 0) { 752 | ret = 1; 753 | } 754 | 755 | if (!ret) { 756 | char* exeUTF8 = toUTF8(exe); 757 | // wprintf(L"Executing %s", javaScript); 758 | if (executeJS(js, exeUTF8) != 0) { 759 | ret = ERROR_EXIT_CODE; 760 | } 761 | free(exeUTF8); 762 | } 763 | free(js); 764 | } 765 | } 766 | 767 | free(javaScript); 768 | 769 | //wprintf(L"Done"); 770 | 771 | if (javaVM) 772 | (*javaVM)->DestroyJavaVM(javaVM); 773 | 774 | #else 775 | wchar_t* target = 0; 776 | 777 | if (!ret) { 778 | target = malloc(MAX_PATH * sizeof(TCHAR)); 779 | if (LoadString(0, (TARGET_EXE_RESOURCE - 1) * 16 + 1, 780 | target, MAX_PATH) == 0) { 781 | ret = ERROR_EXIT_CODE; 782 | printf("Cannot load the target executable path from the resource\n"); 783 | } 784 | } 785 | 786 | // find the name of the target executable 787 | wchar_t* newExe = 0; 788 | if (!ret) { 789 | // is full path to the target executable available? 790 | if (wcschr(target, L'\\') || wcschr(target, L'/')) { 791 | newExe = wcsdup(target); 792 | } else { 793 | wchar_t* p1 = wcsrchr(exe, L'\\'); 794 | wchar_t* p2 = wcsrchr(exe, L'/'); 795 | wchar_t* p = exe; 796 | if (p1 < p2) 797 | p = p2 + 1; 798 | else if (p1 > p2) 799 | p = p1 + 1; 800 | else 801 | p = exe; 802 | 803 | size_t n = p - exe; 804 | newExe = malloc((n + wcslen(target) + 1) * sizeof(wchar_t)); 805 | wcsncpy(newExe, exe, n); 806 | *(newExe + n) = 0; 807 | 808 | wcscat(newExe, target); 809 | } 810 | } 811 | 812 | free(target); 813 | 814 | wchar_t* cmdLine = 0; 815 | if (!ret) { 816 | cmdLine = malloc((wcslen(newExe) + wcslen(args) + 4) * sizeof(wchar_t)); 817 | wcscpy(cmdLine, L"\""); 818 | wcscat(cmdLine, newExe); 819 | wcscat(cmdLine, L"\""); 820 | if (wcslen(args) > 0) { 821 | wcscat(cmdLine, L" "); 822 | wcscat(cmdLine, args); 823 | } 824 | } 825 | 826 | if (!ret) { 827 | ret = exec(cmdLine); 828 | } 829 | 830 | free(cmdLine); 831 | free(newExe); 832 | #endif 833 | 834 | free(exe); 835 | free(args); 836 | 837 | return ret; 838 | } 839 | 840 | -------------------------------------------------------------------------------- /tests/Demo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tim-lebedkov/exe-proxy/003426af06f96b84e78e2045e26eaa73e9d58ad2/tests/Demo.class -------------------------------------------------------------------------------- /tests/Demo.java: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | public class Demo { 4 | public static void main(String[] args) { 5 | for (int i = 0; i < args.length; i++) { 6 | System.out.println("Argument " + i + ": " + args[i]); 7 | } 8 | } 9 | } --------------------------------------------------------------------------------