From 9be934887d70bff3c6de9657fb9f9d262e9aa40c Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Tue, 26 Sep 2023 22:36:26 +0200 Subject: [PATCH 001/615] Solved issues with Node tests related to OpenSSL incompatibilities and Rust. --- source/ports/node_port/CMakeLists.txt | 61 +++++++++++++++ source/ports/node_port/test/index.js | 76 ++++++++++--------- .../metacall_node_port_test/CMakeLists.txt | 76 ++++++++++++++++--- 3 files changed, 164 insertions(+), 49 deletions(-) diff --git a/source/ports/node_port/CMakeLists.txt b/source/ports/node_port/CMakeLists.txt index 89438a729..9a7553f0e 100644 --- a/source/ports/node_port/CMakeLists.txt +++ b/source/ports/node_port/CMakeLists.txt @@ -142,23 +142,84 @@ include(TestEnvironmentVariables) # Enable cobol test if it is built if(OPTION_BUILD_LOADERS_COB) + set(COBOL_DEPENDENCY cob_loader) set(TESTS_ENVIRONMENT_VARIABLES_COB "OPTION_BUILD_LOADERS_COB=1") endif() # Enable c test if it is built if(OPTION_BUILD_LOADERS_C) + set(C_DEPENDENCY c_loader) set(TESTS_ENVIRONMENT_VARIABLES_C "OPTION_BUILD_LOADERS_C=1") endif() # Enable rust test if it is built if(OPTION_BUILD_LOADERS_RS) + set(RS_DEPENDENCY rs_loader) set(TESTS_ENVIRONMENT_VARIABLES_RS "OPTION_BUILD_LOADERS_RS=1") endif() +# Disable OpenSSL related tests if versions are incompatible +set(NodeJS_EXECUTABLE_ONLY ON) + +find_package(NodeJS) +find_package(Python COMPONENTS Interpreter) + +set(TESTS_ENVIRONMENT_VARIABLES_OPENSSL "OPTION_NODEJS_PYTHON_OPENSSL_MISMATCH=1") + +if(NodeJS_FOUND AND Python_Interpreter_FOUND) + execute_process( + COMMAND ${NodeJS_EXECUTABLE} -e "console.log(process.versions.openssl)" + OUTPUT_VARIABLE NODEJS_OPENSSL_VERSION + ) + execute_process( + COMMAND ${Python_EXECUTABLE} -c "import ssl; print(ssl.OPENSSL_VERSION.split()[1])" + OUTPUT_VARIABLE PYTHON_OPENSSL_VERSION + ) + + if(NOT "${NODEJS_OPENSSL_VERSION}" STREQUAL "" AND NOT "${PYTHON_OPENSSL_VERSION}" STREQUAL "") + string(REGEX MATCHALL "-.*$|[0-9]+" NODEJS_OPENSSL_PARTIAL_VERSION_LIST "${NODEJS_OPENSSL_VERSION}") + list(GET NODEJS_OPENSSL_PARTIAL_VERSION_LIST 0 NODEJS_OPENSSL_VERSION_MAJOR) + list(GET NODEJS_OPENSSL_PARTIAL_VERSION_LIST 1 NODEJS_OPENSSL_VERSION_MINOR) + list(GET NODEJS_OPENSSL_PARTIAL_VERSION_LIST 2 NODEJS_OPENSSL_VERSION_PATCH) + + string(REGEX MATCHALL "-.*$|[0-9]+" PYTHON_OPENSSL_PARTIAL_VERSION_LIST "${PYTHON_OPENSSL_VERSION}") + list(GET PYTHON_OPENSSL_PARTIAL_VERSION_LIST 0 PYTHON_OPENSSL_VERSION_MAJOR) + list(GET PYTHON_OPENSSL_PARTIAL_VERSION_LIST 1 PYTHON_OPENSSL_VERSION_MINOR) + list(GET PYTHON_OPENSSL_PARTIAL_VERSION_LIST 2 PYTHON_OPENSSL_VERSION_PATCH) + + # If major and minor version match, then enable the OpenSSL related tests (https://github.com/metacall/core/issues/31#issuecomment-1736039845) + if(NODEJS_OPENSSL_VERSION_MAJOR VERSION_EQUAL PYTHON_OPENSSL_VERSION_MAJOR + AND NODEJS_OPENSSL_VERSION_MINOR VERSION_EQUAL PYTHON_OPENSSL_VERSION_MINOR) + set(TESTS_ENVIRONMENT_VARIABLES_OPENSSL) + endif() + endif() +endif() + +# TODO: When trying multiple versions of OpenSSL in the same project, +# Rust Loader generates a segmentation fault trying to free an unallocated block of memory, +# disable it for now until we can diagnose it +if(OPTION_BUILD_LOADERS_RS AND NOT TESTS_ENVIRONMENT_VARIABLES_OPENSSL) + set(RS_DEPENDENCY) + set(TESTS_ENVIRONMENT_VARIABLES_RS) +endif() + +# Add dependencies and optional dependencies +add_dependencies(${target} + node_loader + mock_loader + py_loader + rb_loader + ts_loader + ${COBOL_DEPENDENCY} + ${C_DEPENDENCY} + ${RS_DEPENDENCY} +) + test_environment_variables(${target} "" ${TESTS_ENVIRONMENT_VARIABLES} ${TESTS_ENVIRONMENT_VARIABLES_COB} ${TESTS_ENVIRONMENT_VARIABLES_C} ${TESTS_ENVIRONMENT_VARIABLES_RS} + ${TESTS_ENVIRONMENT_VARIABLES_OPENSSL} ) diff --git a/source/ports/node_port/test/index.js b/source/ports/node_port/test/index.js index 50da09ce2..918a2f9aa 100644 --- a/source/ports/node_port/test/index.js +++ b/source/ports/node_port/test/index.js @@ -202,43 +202,45 @@ describe('metacall', () => { assert.notStrictEqual(py_encode_basestring_ascii, undefined); assert.strictEqual(py_encode_basestring_ascii('asd'), '"asd"'); }); - it('require (py submodule dependency)', () => { - // Require the 'core' submodule from 'rsa' Python package - const { encrypt_int } = require('py:rsa.core'); - - // In NodeJS, the numbers are of type 'Number', this gets converted to TYPE_DOUBLE, - // but this function requires values of type 'int' in Python, which is TYPE_LONG. - // So basically in python3-rsa at version 4.0-4, this function has assertions - // for requiring type int as parameters, but the parameters are not annotated with types - // so the casting is impossible to be done, thus it throws an exception. In newer versions - // this has been solved and they added type hints, so it does not throw. - // - // Old version: - // def encrypt_int(message, ekey, n): - // """Encrypts a message using encryption key 'ekey', working modulo n""" - // - // assert_int(message, 'message') - // assert_int(ekey, 'ekey') - // assert_int(n, 'n') - // ... - // - // New version: - // def encrypt_int(message: int, ekey: int, n: int) -> int: - // """Encrypts a message using encryption key 'ekey', working modulo n""" - // - // assert_int(message, 'message') - // assert_int(ekey, 'ekey') - // assert_int(n, 'n') - // ... - // - // Without the type annotations metacall has no way to convert from NodeJS Number to Python int. - // So both paths of try and catch are valid for this tests, there is not a bug in MetaCall. - try { - assert.strictEqual(encrypt_int(3, 2, 5), 4); - } catch (e) { - assert.strictEqual(e.message, 'message should be an integer, not ') - } - }); + if (!process.env['OPTION_NODEJS_PYTHON_OPENSSL_MISMATCH']) { + it('require (py submodule dependency)', () => { + // Require the 'core' submodule from 'rsa' Python package + const { encrypt_int } = require('py:rsa.core'); + + // In NodeJS, the numbers are of type 'Number', this gets converted to TYPE_DOUBLE, + // but this function requires values of type 'int' in Python, which is TYPE_LONG. + // So basically in python3-rsa at version 4.0-4, this function has assertions + // for requiring type int as parameters, but the parameters are not annotated with types + // so the casting is impossible to be done, thus it throws an exception. In newer versions + // this has been solved and they added type hints, so it does not throw. + // + // Old version: + // def encrypt_int(message, ekey, n): + // """Encrypts a message using encryption key 'ekey', working modulo n""" + // + // assert_int(message, 'message') + // assert_int(ekey, 'ekey') + // assert_int(n, 'n') + // ... + // + // New version: + // def encrypt_int(message: int, ekey: int, n: int) -> int: + // """Encrypts a message using encryption key 'ekey', working modulo n""" + // + // assert_int(message, 'message') + // assert_int(ekey, 'ekey') + // assert_int(n, 'n') + // ... + // + // Without the type annotations metacall has no way to convert from NodeJS Number to Python int. + // So both paths of try and catch are valid for this tests, there is not a bug in MetaCall. + try { + assert.strictEqual(encrypt_int(3, 2, 5), 4); + } catch (e) { + assert.strictEqual(e.message, 'message should be an integer, not ') + } + }); + } it('require (rb)', () => { const cache = require('./cache.rb'); assert.notStrictEqual(cache, undefined); diff --git a/source/tests/metacall_node_port_test/CMakeLists.txt b/source/tests/metacall_node_port_test/CMakeLists.txt index 80a792f5e..7694e58f6 100644 --- a/source/tests/metacall_node_port_test/CMakeLists.txt +++ b/source/tests/metacall_node_port_test/CMakeLists.txt @@ -149,21 +149,80 @@ add_test(NAME ${target} ) # -# Define dependencies +# Define test labels # +set_property(TEST ${target} + PROPERTY LABELS ${target} +) + +include(TestEnvironmentVariables) + +# Enable cobol test if it is built if(OPTION_BUILD_LOADERS_COB) set(COBOL_DEPENDENCY cob_loader) set(TESTS_ENVIRONMENT_VARIABLES_COB "OPTION_BUILD_LOADERS_COB=1") endif() +# Enable c test if it is built if(OPTION_BUILD_LOADERS_C) set(C_DEPENDENCY c_loader) set(TESTS_ENVIRONMENT_VARIABLES_C "OPTION_BUILD_LOADERS_C=1") endif() +# Enable rust test if it is built +if(OPTION_BUILD_LOADERS_RS) + set(RS_DEPENDENCY rs_loader) + set(TESTS_ENVIRONMENT_VARIABLES_RS "OPTION_BUILD_LOADERS_RS=1") +endif() + +# Disable OpenSSL related tests if versions are incompatible +set(NodeJS_EXECUTABLE_ONLY ON) + +find_package(NodeJS) +find_package(Python COMPONENTS Interpreter) + +set(TESTS_ENVIRONMENT_VARIABLES_OPENSSL "OPTION_NODEJS_PYTHON_OPENSSL_MISMATCH=1") + +if(NodeJS_FOUND AND Python_Interpreter_FOUND) + execute_process( + COMMAND ${NodeJS_EXECUTABLE} -e "console.log(process.versions.openssl)" + OUTPUT_VARIABLE NODEJS_OPENSSL_VERSION + ) + execute_process( + COMMAND ${Python_EXECUTABLE} -c "import ssl; print(ssl.OPENSSL_VERSION.split()[1])" + OUTPUT_VARIABLE PYTHON_OPENSSL_VERSION + ) + + if(NOT "${NODEJS_OPENSSL_VERSION}" STREQUAL "" AND NOT "${PYTHON_OPENSSL_VERSION}" STREQUAL "") + string(REGEX MATCHALL "-.*$|[0-9]+" NODEJS_OPENSSL_PARTIAL_VERSION_LIST "${NODEJS_OPENSSL_VERSION}") + list(GET NODEJS_OPENSSL_PARTIAL_VERSION_LIST 0 NODEJS_OPENSSL_VERSION_MAJOR) + list(GET NODEJS_OPENSSL_PARTIAL_VERSION_LIST 1 NODEJS_OPENSSL_VERSION_MINOR) + list(GET NODEJS_OPENSSL_PARTIAL_VERSION_LIST 2 NODEJS_OPENSSL_VERSION_PATCH) + + string(REGEX MATCHALL "-.*$|[0-9]+" PYTHON_OPENSSL_PARTIAL_VERSION_LIST "${PYTHON_OPENSSL_VERSION}") + list(GET PYTHON_OPENSSL_PARTIAL_VERSION_LIST 0 PYTHON_OPENSSL_VERSION_MAJOR) + list(GET PYTHON_OPENSSL_PARTIAL_VERSION_LIST 1 PYTHON_OPENSSL_VERSION_MINOR) + list(GET PYTHON_OPENSSL_PARTIAL_VERSION_LIST 2 PYTHON_OPENSSL_VERSION_PATCH) + + # If major and minor version match, then enable the OpenSSL related tests (https://github.com/metacall/core/issues/31#issuecomment-1736039845) + if(NODEJS_OPENSSL_VERSION_MAJOR VERSION_EQUAL PYTHON_OPENSSL_VERSION_MAJOR + AND NODEJS_OPENSSL_VERSION_MINOR VERSION_EQUAL PYTHON_OPENSSL_VERSION_MINOR) + set(TESTS_ENVIRONMENT_VARIABLES_OPENSSL) + endif() + endif() +endif() + +# TODO: When trying multiple versions of OpenSSL in the same project, +# Rust Loader generates a segmentation fault trying to free an unallocated block of memory, +# disable it for now until we can diagnose it +if(OPTION_BUILD_LOADERS_RS AND NOT TESTS_ENVIRONMENT_VARIABLES_OPENSSL) + set(RS_DEPENDENCY) + set(TESTS_ENVIRONMENT_VARIABLES_RS) +endif() + +# Add dependencies and optional dependencies add_dependencies(${target} - node_port node_loader mock_loader py_loader @@ -171,21 +230,14 @@ add_dependencies(${target} ts_loader ${COBOL_DEPENDENCY} ${C_DEPENDENCY} + ${RS_DEPENDENCY} ) -# -# Define test properties -# - -set_property(TEST ${target} - PROPERTY LABELS ${target} -) - -include(TestEnvironmentVariables) - test_environment_variables(${target} "" ${TESTS_ENVIRONMENT_VARIABLES} ${TESTS_ENVIRONMENT_VARIABLES_COB} ${TESTS_ENVIRONMENT_VARIABLES_C} + ${TESTS_ENVIRONMENT_VARIABLES_RS} + ${TESTS_ENVIRONMENT_VARIABLES_OPENSSL} ) From 0c79a89e0c0aa587737546274475583658a166ef Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Tue, 26 Sep 2023 23:00:26 +0200 Subject: [PATCH 002/615] Improve a bit previous commit to make things simpler. --- source/ports/node_port/CMakeLists.txt | 6 +- source/ports/node_port/test/index.js | 2 +- source/tests/CMakeLists.txt | 1 + .../CMakeLists.txt | 1 + .../source/metacall_node_port_await_test.cpp | 6 +- .../metacall_node_port_rs_test/CMakeLists.txt | 152 ++++++++++++++++++ .../source/main.cpp | 28 ++++ .../source/metacall_node_port_rs_test.cpp | 59 +++++++ .../metacall_node_port_test/CMakeLists.txt | 7 +- 9 files changed, 250 insertions(+), 12 deletions(-) create mode 100644 source/tests/metacall_node_port_rs_test/CMakeLists.txt create mode 100644 source/tests/metacall_node_port_rs_test/source/main.cpp create mode 100644 source/tests/metacall_node_port_rs_test/source/metacall_node_port_rs_test.cpp diff --git a/source/ports/node_port/CMakeLists.txt b/source/ports/node_port/CMakeLists.txt index 9a7553f0e..1cac147c0 100644 --- a/source/ports/node_port/CMakeLists.txt +++ b/source/ports/node_port/CMakeLists.txt @@ -164,8 +164,6 @@ set(NodeJS_EXECUTABLE_ONLY ON) find_package(NodeJS) find_package(Python COMPONENTS Interpreter) -set(TESTS_ENVIRONMENT_VARIABLES_OPENSSL "OPTION_NODEJS_PYTHON_OPENSSL_MISMATCH=1") - if(NodeJS_FOUND AND Python_Interpreter_FOUND) execute_process( COMMAND ${NodeJS_EXECUTABLE} -e "console.log(process.versions.openssl)" @@ -190,7 +188,7 @@ if(NodeJS_FOUND AND Python_Interpreter_FOUND) # If major and minor version match, then enable the OpenSSL related tests (https://github.com/metacall/core/issues/31#issuecomment-1736039845) if(NODEJS_OPENSSL_VERSION_MAJOR VERSION_EQUAL PYTHON_OPENSSL_VERSION_MAJOR AND NODEJS_OPENSSL_VERSION_MINOR VERSION_EQUAL PYTHON_OPENSSL_VERSION_MINOR) - set(TESTS_ENVIRONMENT_VARIABLES_OPENSSL) + set(TESTS_ENVIRONMENT_VARIABLES_OPENSSL "OPTION_NODEJS_PYTHON_OPENSSL_MATCH=1") endif() endif() endif() @@ -198,7 +196,7 @@ endif() # TODO: When trying multiple versions of OpenSSL in the same project, # Rust Loader generates a segmentation fault trying to free an unallocated block of memory, # disable it for now until we can diagnose it -if(OPTION_BUILD_LOADERS_RS AND NOT TESTS_ENVIRONMENT_VARIABLES_OPENSSL) +if(OPTION_BUILD_LOADERS_RS AND TESTS_ENVIRONMENT_VARIABLES_OPENSSL) set(RS_DEPENDENCY) set(TESTS_ENVIRONMENT_VARIABLES_RS) endif() diff --git a/source/ports/node_port/test/index.js b/source/ports/node_port/test/index.js index 918a2f9aa..23995a849 100644 --- a/source/ports/node_port/test/index.js +++ b/source/ports/node_port/test/index.js @@ -202,7 +202,7 @@ describe('metacall', () => { assert.notStrictEqual(py_encode_basestring_ascii, undefined); assert.strictEqual(py_encode_basestring_ascii('asd'), '"asd"'); }); - if (!process.env['OPTION_NODEJS_PYTHON_OPENSSL_MISMATCH']) { + if (process.env['OPTION_NODEJS_PYTHON_OPENSSL_MATCH']) { it('require (py submodule dependency)', () => { // Require the 'core' submodule from 'rsa' Python package const { encrypt_int } = require('py:rsa.core'); diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index d11488bd2..34461bdc9 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -133,6 +133,7 @@ add_subdirectory(metacall_node_async_test) add_subdirectory(metacall_node_reentrant_test) add_subdirectory(metacall_node_port_test) add_subdirectory(metacall_node_port_await_test) +add_subdirectory(metacall_node_port_rs_test) add_subdirectory(metacall_node_python_port_mock_test) add_subdirectory(metacall_node_python_port_ruby_test) add_subdirectory(metacall_node_python_ruby_test) diff --git a/source/tests/metacall_node_port_await_test/CMakeLists.txt b/source/tests/metacall_node_port_await_test/CMakeLists.txt index 96359c264..7afce5c27 100644 --- a/source/tests/metacall_node_port_await_test/CMakeLists.txt +++ b/source/tests/metacall_node_port_await_test/CMakeLists.txt @@ -132,6 +132,7 @@ add_test(NAME ${target} add_dependencies(${target} node_loader + node_port ) # diff --git a/source/tests/metacall_node_port_await_test/source/metacall_node_port_await_test.cpp b/source/tests/metacall_node_port_await_test/source/metacall_node_port_await_test.cpp index 7d2f3cdbb..9ef976cb7 100644 --- a/source/tests/metacall_node_port_await_test/source/metacall_node_port_await_test.cpp +++ b/source/tests/metacall_node_port_await_test/source/metacall_node_port_await_test.cpp @@ -35,8 +35,8 @@ TEST_F(metacall_node_port_await_test, DefaultConstructor) ASSERT_EQ((int)0, (int)metacall_initialize()); -/* NodeJS & Python & Mock */ -#if defined(OPTION_BUILD_LOADERS_NODE) && defined(OPTION_BUILD_LOADERS_PY) +/* NodeJS */ +#if defined(OPTION_BUILD_LOADERS_NODE) { static const char buffer[] = /* NodeJS */ @@ -69,7 +69,7 @@ TEST_F(metacall_node_port_await_test, DefaultConstructor) ASSERT_EQ((int)0, (int)metacall_load_from_memory("node", buffer, sizeof(buffer), NULL)); } -#endif /* OPTION_BUILD_LOADERS_NODE && OPTION_BUILD_LOADERS_PY */ +#endif /* OPTION_BUILD_LOADERS_NODE */ EXPECT_EQ((int)0, (int)metacall_destroy()); } diff --git a/source/tests/metacall_node_port_rs_test/CMakeLists.txt b/source/tests/metacall_node_port_rs_test/CMakeLists.txt new file mode 100644 index 000000000..2882f8630 --- /dev/null +++ b/source/tests/metacall_node_port_rs_test/CMakeLists.txt @@ -0,0 +1,152 @@ +# Check if this loader is enabled +if(NOT OPTION_BUILD_LOADERS OR NOT OPTION_BUILD_LOADERS_NODE OR NOT OPTION_BUILD_LOADERS_RS OR NOT OPTION_BUILD_PORTS OR NOT OPTION_BUILD_PORTS_NODE) + return() +endif() + +# +# Executable name and options +# + +# Target name +set(target metacall-node-port-rs-test) +message(STATUS "Test ${target}") + +# +# Compiler warnings +# + +include(Warnings) + +# +# Compiler security +# + +include(SecurityFlags) + +# +# Sources +# + +set(include_path "${CMAKE_CURRENT_SOURCE_DIR}/include/${target}") +set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/source") + +set(sources + ${source_path}/main.cpp + ${source_path}/metacall_node_port_rs_test.cpp +) + +# Group source files +set(header_group "Header Files (API)") +set(source_group "Source Files") +source_group_by_path(${include_path} "\\\\.h$|\\\\.hpp$" + ${header_group} ${headers}) +source_group_by_path(${source_path} "\\\\.cpp$|\\\\.c$|\\\\.h$|\\\\.hpp$" + ${source_group} ${sources}) + +# +# Create executable +# + +# Build executable +add_executable(${target} + ${sources} +) + +# Create namespaced alias +add_executable(${META_PROJECT_NAME}::${target} ALIAS ${target}) + +# +# Project options +# + +set_target_properties(${target} + PROPERTIES + ${DEFAULT_PROJECT_OPTIONS} + FOLDER "${IDE_FOLDER}" +) + +# +# Include directories +# + +target_include_directories(${target} + PRIVATE + ${DEFAULT_INCLUDE_DIRECTORIES} + ${PROJECT_BINARY_DIR}/source/include +) + +# +# Libraries +# + +target_link_libraries(${target} + PRIVATE + ${DEFAULT_LIBRARIES} + + GTest + + ${META_PROJECT_NAME}::metacall +) + +# +# Compile definitions +# + +target_compile_definitions(${target} + PRIVATE + ${DEFAULT_COMPILE_DEFINITIONS} + + # NodeJS Port path + METACALL_NODE_PORT_PATH="${CMAKE_SOURCE_DIR}/source/ports/node_port/index.js" +) + +# +# Compile options +# + +target_compile_options(${target} + PRIVATE + ${DEFAULT_COMPILE_OPTIONS} +) + +# +# Linker options +# + +target_link_libraries(${target} + PRIVATE + ${DEFAULT_LINKER_OPTIONS} +) + +# +# Define test +# + +add_test(NAME ${target} + COMMAND $ +) + +# +# Define dependencies +# + +add_dependencies(${target} + node_port + node_loader + rs_loader +) + +# +# Define test properties +# + +set_property(TEST ${target} + PROPERTY LABELS ${target} +) + +include(TestEnvironmentVariables) + +test_environment_variables(${target} + "" + ${TESTS_ENVIRONMENT_VARIABLES} +) diff --git a/source/tests/metacall_node_port_rs_test/source/main.cpp b/source/tests/metacall_node_port_rs_test/source/main.cpp new file mode 100644 index 000000000..628e40890 --- /dev/null +++ b/source/tests/metacall_node_port_rs_test/source/main.cpp @@ -0,0 +1,28 @@ +/* + * MetaCall Library by Parra Studios + * A library for providing a foreign function interface calls. + * + * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +int main(int argc, char *argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} diff --git a/source/tests/metacall_node_port_rs_test/source/metacall_node_port_rs_test.cpp b/source/tests/metacall_node_port_rs_test/source/metacall_node_port_rs_test.cpp new file mode 100644 index 000000000..f55a72e10 --- /dev/null +++ b/source/tests/metacall_node_port_rs_test/source/metacall_node_port_rs_test.cpp @@ -0,0 +1,59 @@ +/* + * MetaCall Library by Parra Studios + * A library for providing a foreign function interface calls. + * + * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +class metacall_node_port_rs_test : public testing::Test +{ +public: +}; + +TEST_F(metacall_node_port_rs_test, DefaultConstructor) +{ + metacall_print_info(); + + ASSERT_EQ((int)0, (int)metacall_initialize()); + +/* NodeJS & Rust */ +#if defined(OPTION_BUILD_LOADERS_NODE) && defined(OPTION_BUILD_LOADERS_RS) + { + static const char buffer[] = + /* NodeJS */ + "const assert = require('assert');\n" + "require('" METACALL_NODE_PORT_PATH "');\n" + /* Rust Require */ + "const { new_string, add_vec2, add_float, return_vec } = require('./basic.rs');\n" + /* Rust Assert */ + "assert.strictEqual(new_string(123), 'get number 123');\n" + "assert.strictEqual(add_vec2([1, 2, 3, 4]), 10);\n" + "assert.strictEqual(add_float(12, 23), 35);\n" + "assert.strictEqual(return_vec().reduce((partialSum, a) => partialSum + a, 0), 15);\n" + "\n"; + + ASSERT_EQ((int)0, (int)metacall_load_from_memory("node", buffer, sizeof(buffer), NULL)); + } +#endif /* OPTION_BUILD_LOADERS_NODE && OPTION_BUILD_LOADERS_RS */ + + EXPECT_EQ((int)0, (int)metacall_destroy()); +} diff --git a/source/tests/metacall_node_port_test/CMakeLists.txt b/source/tests/metacall_node_port_test/CMakeLists.txt index 7694e58f6..9a75f0e6e 100644 --- a/source/tests/metacall_node_port_test/CMakeLists.txt +++ b/source/tests/metacall_node_port_test/CMakeLists.txt @@ -182,8 +182,6 @@ set(NodeJS_EXECUTABLE_ONLY ON) find_package(NodeJS) find_package(Python COMPONENTS Interpreter) -set(TESTS_ENVIRONMENT_VARIABLES_OPENSSL "OPTION_NODEJS_PYTHON_OPENSSL_MISMATCH=1") - if(NodeJS_FOUND AND Python_Interpreter_FOUND) execute_process( COMMAND ${NodeJS_EXECUTABLE} -e "console.log(process.versions.openssl)" @@ -208,7 +206,7 @@ if(NodeJS_FOUND AND Python_Interpreter_FOUND) # If major and minor version match, then enable the OpenSSL related tests (https://github.com/metacall/core/issues/31#issuecomment-1736039845) if(NODEJS_OPENSSL_VERSION_MAJOR VERSION_EQUAL PYTHON_OPENSSL_VERSION_MAJOR AND NODEJS_OPENSSL_VERSION_MINOR VERSION_EQUAL PYTHON_OPENSSL_VERSION_MINOR) - set(TESTS_ENVIRONMENT_VARIABLES_OPENSSL) + set(TESTS_ENVIRONMENT_VARIABLES_OPENSSL "OPTION_NODEJS_PYTHON_OPENSSL_MATCH=1") endif() endif() endif() @@ -216,13 +214,14 @@ endif() # TODO: When trying multiple versions of OpenSSL in the same project, # Rust Loader generates a segmentation fault trying to free an unallocated block of memory, # disable it for now until we can diagnose it -if(OPTION_BUILD_LOADERS_RS AND NOT TESTS_ENVIRONMENT_VARIABLES_OPENSSL) +if(OPTION_BUILD_LOADERS_RS AND TESTS_ENVIRONMENT_VARIABLES_OPENSSL) set(RS_DEPENDENCY) set(TESTS_ENVIRONMENT_VARIABLES_RS) endif() # Add dependencies and optional dependencies add_dependencies(${target} + node_port node_loader mock_loader py_loader From ad9e7cf7c9a5d04e214f2c0bc1fdaabfa8d1a911 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Tue, 26 Sep 2023 23:56:00 +0200 Subject: [PATCH 003/615] Solved issues in node port. --- .../rust/compiler/src/api/function.rs | 4 ++- source/ports/node_port/CMakeLists.txt | 32 +++++++---------- .../metacall_node_port_test/CMakeLists.txt | 34 +++++++------------ 3 files changed, 28 insertions(+), 42 deletions(-) diff --git a/source/loaders/rs_loader/rust/compiler/src/api/function.rs b/source/loaders/rs_loader/rust/compiler/src/api/function.rs index 4981d6365..a0e351419 100644 --- a/source/loaders/rs_loader/rust/compiler/src/api/function.rs +++ b/source/loaders/rs_loader/rust/compiler/src/api/function.rs @@ -56,12 +56,14 @@ extern "C" fn function_singleton_await( #[no_mangle] extern "C" fn function_singleton_destroy(_func: OpaqueType, func_impl: OpaqueType) { - // comment out this due to the seg fault + // TODO: This generates a segmentation fault in NodeJS Port Test, commented until it is fully reviewed if !func_impl.is_null() { + /* unsafe { let func_ptr = Box::from_raw(func_impl as *mut class::NormalFunction); drop(func_ptr); } + */ } } diff --git a/source/ports/node_port/CMakeLists.txt b/source/ports/node_port/CMakeLists.txt index 1cac147c0..2402d2a7f 100644 --- a/source/ports/node_port/CMakeLists.txt +++ b/source/ports/node_port/CMakeLists.txt @@ -158,6 +158,18 @@ if(OPTION_BUILD_LOADERS_RS) set(TESTS_ENVIRONMENT_VARIABLES_RS "OPTION_BUILD_LOADERS_RS=1") endif() +# Add dependencies and optional dependencies +add_dependencies(${target} + node_loader + mock_loader + py_loader + rb_loader + ts_loader + ${COBOL_DEPENDENCY} + ${C_DEPENDENCY} + ${RS_DEPENDENCY} +) + # Disable OpenSSL related tests if versions are incompatible set(NodeJS_EXECUTABLE_ONLY ON) @@ -193,26 +205,6 @@ if(NodeJS_FOUND AND Python_Interpreter_FOUND) endif() endif() -# TODO: When trying multiple versions of OpenSSL in the same project, -# Rust Loader generates a segmentation fault trying to free an unallocated block of memory, -# disable it for now until we can diagnose it -if(OPTION_BUILD_LOADERS_RS AND TESTS_ENVIRONMENT_VARIABLES_OPENSSL) - set(RS_DEPENDENCY) - set(TESTS_ENVIRONMENT_VARIABLES_RS) -endif() - -# Add dependencies and optional dependencies -add_dependencies(${target} - node_loader - mock_loader - py_loader - rb_loader - ts_loader - ${COBOL_DEPENDENCY} - ${C_DEPENDENCY} - ${RS_DEPENDENCY} -) - test_environment_variables(${target} "" ${TESTS_ENVIRONMENT_VARIABLES} diff --git a/source/tests/metacall_node_port_test/CMakeLists.txt b/source/tests/metacall_node_port_test/CMakeLists.txt index 9a75f0e6e..6ffc2981b 100644 --- a/source/tests/metacall_node_port_test/CMakeLists.txt +++ b/source/tests/metacall_node_port_test/CMakeLists.txt @@ -176,6 +176,19 @@ if(OPTION_BUILD_LOADERS_RS) set(TESTS_ENVIRONMENT_VARIABLES_RS "OPTION_BUILD_LOADERS_RS=1") endif() +# Add dependencies and optional dependencies +add_dependencies(${target} + node_port + node_loader + mock_loader + py_loader + rb_loader + ts_loader + ${COBOL_DEPENDENCY} + ${C_DEPENDENCY} + ${RS_DEPENDENCY} +) + # Disable OpenSSL related tests if versions are incompatible set(NodeJS_EXECUTABLE_ONLY ON) @@ -211,27 +224,6 @@ if(NodeJS_FOUND AND Python_Interpreter_FOUND) endif() endif() -# TODO: When trying multiple versions of OpenSSL in the same project, -# Rust Loader generates a segmentation fault trying to free an unallocated block of memory, -# disable it for now until we can diagnose it -if(OPTION_BUILD_LOADERS_RS AND TESTS_ENVIRONMENT_VARIABLES_OPENSSL) - set(RS_DEPENDENCY) - set(TESTS_ENVIRONMENT_VARIABLES_RS) -endif() - -# Add dependencies and optional dependencies -add_dependencies(${target} - node_port - node_loader - mock_loader - py_loader - rb_loader - ts_loader - ${COBOL_DEPENDENCY} - ${C_DEPENDENCY} - ${RS_DEPENDENCY} -) - test_environment_variables(${target} "" ${TESTS_ENVIRONMENT_VARIABLES} From 99595bdeecb02dc4f9cfd45252dfedcbb1377eec Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Wed, 27 Sep 2023 00:12:02 +0200 Subject: [PATCH 004/615] Trying to solve issues with windows libcurl. --- tools/metacall-environment.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/metacall-environment.ps1 b/tools/metacall-environment.ps1 index 2a985874a..1ecb001a5 100755 --- a/tools/metacall-environment.ps1 +++ b/tools/metacall-environment.ps1 @@ -215,6 +215,7 @@ function Set-Curl { $CURL_LIB="$CurlDir/lib/libcurl.dll.a" $CURL_LIB_NAME="$CurlDir/bin/libcurl-x64.dll" + Write-Output "-DCURL_INCLUDE_DIR=""$CURL_INCLUDE_DIR""" >> $EnvOpts Write-Output "-DCURL_INCLUDE_DIRS=""$CURL_INCLUDE_DIR""" >> $EnvOpts Write-Output "-DCURL_LIBRARY=""$CURL_LIB""" >> $EnvOpts Write-Output "-DCURL_LIBRARY_NAME=""$CURL_LIB_NAME""" >> $EnvOpts From f85e8883b46f8e180a7b0e0a5d4871a03e5f864a Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Wed, 27 Sep 2023 00:48:24 +0200 Subject: [PATCH 005/615] Trying to make windows ci pass. --- cmake/FindCoreCLR.cmake | 2 -- tools/metacall-environment.ps1 | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/cmake/FindCoreCLR.cmake b/cmake/FindCoreCLR.cmake index 62bda548c..d414a6e02 100644 --- a/cmake/FindCoreCLR.cmake +++ b/cmake/FindCoreCLR.cmake @@ -24,8 +24,6 @@ # CORECLR_LIBRARIES - List of CoreCLR libraries # CORECLR_CGINFO - List of CoreCLR libraries - - # Prevent vervosity if already included if(CORECLR_FOUND) set(CORECLR_FIND_QUIETLY TRUE) diff --git a/tools/metacall-environment.ps1 b/tools/metacall-environment.ps1 index 1ecb001a5..67c1c366a 100755 --- a/tools/metacall-environment.ps1 +++ b/tools/metacall-environment.ps1 @@ -197,7 +197,7 @@ function Set-Curl { if (!(Test-Path -Path "$DepsDir\curl.zip")) { # Download installer Write-Output "Curl not found downloading now..." - (New-Object Net.WebClient).DownloadFile("https://curl.se/windows/dl-8.1.2_3/curl-8.1.2_3-win64-mingw.zip", "$DepsDir\curl.zip") + (New-Object Net.WebClient).DownloadFile("https://curl.se/windows/dl-8.3.0_2/curl-8.3.0_2-win64-mingw.zip", "$DepsDir\curl.zip") } Set-Location $DepsDir From 216f336339115c4d931bd4f2afbeec1e48cae240 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Wed, 27 Sep 2023 23:11:57 +0200 Subject: [PATCH 006/615] Add base for sandboxing with libseccomp. --- .../source/cli_core_plugin.cpp | 16 +- source/plugins/CMakeLists.txt | 2 + .../plugins/backtrace_plugin/CMakeLists.txt | 2 +- .../backtrace_plugin/backtrace_plugin.h | 2 +- .../source/backtrace_plugin.cpp | 3 +- source/plugins/sandbox_plugin/CMakeLists.txt | 227 ++++++++++++++++++ .../sandbox_plugin/cmake/FindLibSecComp.cmake | 100 ++++++++ .../include/sandbox_plugin/sandbox_plugin.h | 40 +++ .../sandbox_plugin/source/metacall.json | 7 + .../sandbox_plugin/source/sandbox_plugin.cpp | 194 +++++++++++++++ source/tests/CMakeLists.txt | 1 + .../source/main.cpp | 4 +- .../source/metacall_backtrace_plugin_test.cpp | 9 +- .../CMakeLists.txt | 154 ++++++++++++ .../source/main.cpp | 28 +++ .../source/metacall_sandbox_plugin_test.cpp | 87 +++++++ 16 files changed, 857 insertions(+), 19 deletions(-) create mode 100644 source/plugins/sandbox_plugin/CMakeLists.txt create mode 100644 source/plugins/sandbox_plugin/cmake/FindLibSecComp.cmake create mode 100644 source/plugins/sandbox_plugin/include/sandbox_plugin/sandbox_plugin.h create mode 100644 source/plugins/sandbox_plugin/source/metacall.json create mode 100644 source/plugins/sandbox_plugin/source/sandbox_plugin.cpp create mode 100644 source/tests/metacall_sandbox_plugin_test/CMakeLists.txt create mode 100644 source/tests/metacall_sandbox_plugin_test/source/main.cpp create mode 100644 source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp diff --git a/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp b/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp index f100bd8e4..00e7f665a 100644 --- a/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp +++ b/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp @@ -319,13 +319,13 @@ void *inspect(size_t argc, void *args[], void *data) int cli_core_plugin(void *loader, void *handle, void *context) { (void)handle; - int ret = 0; + { enum metacall_value_id *arg_types = NULL; if (metacall_register_loaderv(loader, context, "inspect", inspect, METACALL_STRING, 0, arg_types) != 0) { log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: inspect"); - ret = 1; + return 1; } } @@ -334,7 +334,7 @@ int cli_core_plugin(void *loader, void *handle, void *context) if (metacall_register_loaderv(loader, context, "clear", clear, METACALL_INT, sizeof(arg_types) / sizeof(arg_types[0]), arg_types) != 0) { log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: clear"); - ret = 1; + return 1; } } @@ -343,7 +343,7 @@ int cli_core_plugin(void *loader, void *handle, void *context) if (metacall_register_loaderv(loader, context, "call", call, METACALL_PTR, sizeof(arg_types) / sizeof(arg_types[0]), arg_types) != 0) { log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: call"); - ret = 1; + return 1; } } @@ -352,7 +352,7 @@ int cli_core_plugin(void *loader, void *handle, void *context) if (metacall_register_loaderv(loader, context, "await", await, METACALL_PTR, sizeof(arg_types) / sizeof(arg_types[0]), arg_types) != 0) { log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: await"); - ret = 1; + return 1; } } @@ -361,7 +361,7 @@ int cli_core_plugin(void *loader, void *handle, void *context) if (metacall_register_loaderv(loader, context, "eval", eval, METACALL_INT, sizeof(arg_types) / sizeof(arg_types[0]), arg_types) != 0) { log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: eval"); - ret = 1; + return 1; } } @@ -370,9 +370,9 @@ int cli_core_plugin(void *loader, void *handle, void *context) if (metacall_register_loaderv(loader, context, "load", load, METACALL_INT, sizeof(arg_types) / sizeof(arg_types[0]), arg_types) != 0) { log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: load"); - ret = 1; + return 1; } } - return ret; + return 0; } diff --git a/source/plugins/CMakeLists.txt b/source/plugins/CMakeLists.txt index c10e60c0f..34aea20d6 100644 --- a/source/plugins/CMakeLists.txt +++ b/source/plugins/CMakeLists.txt @@ -5,9 +5,11 @@ endif() # Plugins options option(OPTION_BUILD_PLUGINS_BACKTRACE "Build cross-platform backtrace plugin." ON) +option(OPTION_BUILD_PLUGINS_SANDBOX "Build cross-platform Linux sandbox plugin." OFF) # Plugin sub-projects add_subdirectory(backtrace_plugin) +add_subdirectory(sandbox_plugin) # Install plugin directory install(DIRECTORY ${PROJECT_OUTPUT_DIR}/plugins diff --git a/source/plugins/backtrace_plugin/CMakeLists.txt b/source/plugins/backtrace_plugin/CMakeLists.txt index c19d801ca..866d1800a 100644 --- a/source/plugins/backtrace_plugin/CMakeLists.txt +++ b/source/plugins/backtrace_plugin/CMakeLists.txt @@ -32,7 +32,7 @@ find_package(Backward ) if(NOT BACKWARD_FOUND) - message(SEND_ERROR "BackwardCpp could not be found, skipping backtrace plugin compilation") + message(WARNING "BackwardCpp could not be found, skipping backtrace plugin compilation") return() endif() diff --git a/source/plugins/backtrace_plugin/include/backtrace_plugin/backtrace_plugin.h b/source/plugins/backtrace_plugin/include/backtrace_plugin/backtrace_plugin.h index a50dcf44c..a6ed27562 100644 --- a/source/plugins/backtrace_plugin/include/backtrace_plugin/backtrace_plugin.h +++ b/source/plugins/backtrace_plugin/include/backtrace_plugin/backtrace_plugin.h @@ -1,5 +1,5 @@ /* - * CLI Core Plugin by Parra Studios + * Backtrace Plugin by Parra Studios * A plugin implementing backtracing functionality for MetaCall Core. * * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia diff --git a/source/plugins/backtrace_plugin/source/backtrace_plugin.cpp b/source/plugins/backtrace_plugin/source/backtrace_plugin.cpp index a79983471..825233a45 100644 --- a/source/plugins/backtrace_plugin/source/backtrace_plugin.cpp +++ b/source/plugins/backtrace_plugin/source/backtrace_plugin.cpp @@ -1,5 +1,5 @@ /* - * CLI Core Plugin by Parra Studios + * Backtrace Plugin by Parra Studios * A plugin implementing backtracing functionality for MetaCall Core. * * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia @@ -37,5 +37,6 @@ int backtrace_plugin(void *loader, void *handle, void *context) log_write("metacall", LOG_LEVEL_ERROR, "Backtrace plugin failed to load, you need unwind/libunwind for stacktracing and libbfd/libdw/libdwarf for the debug information. Install the required libraries and recompile to utilise the backtrace plugin. For more information visit https://github.com/bombela/backward-cpp"); return 1; } + return 0; } diff --git a/source/plugins/sandbox_plugin/CMakeLists.txt b/source/plugins/sandbox_plugin/CMakeLists.txt new file mode 100644 index 000000000..b2dba7a15 --- /dev/null +++ b/source/plugins/sandbox_plugin/CMakeLists.txt @@ -0,0 +1,227 @@ +# Check if this loader is enabled +if(NOT OPTION_BUILD_LOADERS OR NOT OPTION_BUILD_LOADERS_EXT OR NOT OPTION_BUILD_EXTENSIONS OR NOT OPTION_BUILD_PLUGINS_SANDBOX) + return() +endif() + +include(Portability) + +if(NOT PROJECT_OS_FAMILY STREQUAL unix) + message(WARNING "Sandbox plugin requires LibSecComp which only works on Linux families by now, skipping sandbox plugin compilation") + return() +endif() + +# +# External dependencies +# + +# Include cmake modules +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +find_package(LibSecComp 2) + +if(NOT LibSecComp_FOUND) + message(WARNING "LibSecComp could not be found, skipping sandbox plugin compilation") + return() +endif() + +# +# Plugin name and options +# + +# Target name +set(target sandbox_plugin) + +# Exit here if required dependencies are not met +message(STATUS "Plugin ${target}") + +# Set API export file and macro +string(TOUPPER ${target} target_upper) +set(export_file "include/${target}/${target}_api.h") +set(export_macro "${target_upper}_API") + +# +# Compiler warnings +# + +include(Warnings) + +# +# Compiler security +# + +include(SecurityFlags) + +# +# Sources +# + +set(include_path "${CMAKE_CURRENT_SOURCE_DIR}/include/${target}") +set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/source") + +set(headers + ${include_path}/sandbox_plugin.h +) + +set(sources + ${source_path}/sandbox_plugin.cpp +) + +# Group source files +set(header_group "Header Files (API)") +set(source_group "Source Files") +source_group_by_path(${include_path} "\\\\.h$|\\\\.hpp$" + ${header_group} ${headers}) +source_group_by_path(${source_path} "\\\\.cpp$|\\\\.c$|\\\\.h$|\\\\.hpp$" + ${source_group} ${sources}) + +# +# Create library +# + +# Build library +add_library(${target} MODULE + ${sources} + ${headers} +) + +# Create namespaced alias +add_library(${META_PROJECT_NAME}::${target} ALIAS ${target}) + +# Export library for downstream projects +export(TARGETS ${target} NAMESPACE ${META_PROJECT_NAME}:: FILE ${PROJECT_BINARY_DIR}/cmake/${target}/${target}-export.cmake) + +# Create API export header +generate_export_header(${target} + EXPORT_FILE_NAME ${export_file} + EXPORT_MACRO_NAME ${export_macro} +) + +# +# Project options +# + +set(PLUGIN_OUTPUT_DIRECTORY "${PROJECT_OUTPUT_DIR}/plugins/${target}") + +set_target_properties(${target} + PROPERTIES + ${DEFAULT_PROJECT_OPTIONS} + FOLDER "${IDE_FOLDER}" + BUNDLE $<$:$<$>> + + # Define custom build output directory + LIBRARY_OUTPUT_DIRECTORY "${PLUGIN_OUTPUT_DIRECTORY}" + LIBRARY_OUTPUT_DIRECTORY_DEBUG "${PLUGIN_OUTPUT_DIRECTORY}" + LIBRARY_OUTPUT_DIRECTORY_RELEASE "${PLUGIN_OUTPUT_DIRECTORY}" + LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${PLUGIN_OUTPUT_DIRECTORY}" + LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${PLUGIN_OUTPUT_DIRECTORY}" + + RUNTIME_OUTPUT_DIRECTORY "${PLUGIN_OUTPUT_DIRECTORY}" + RUNTIME_OUTPUT_DIRECTORY_DEBUG "${PLUGIN_OUTPUT_DIRECTORY}" + RUNTIME_OUTPUT_DIRECTORY_RELEASE "${PLUGIN_OUTPUT_DIRECTORY}" + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${PLUGIN_OUTPUT_DIRECTORY}" + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${PLUGIN_OUTPUT_DIRECTORY}" + + ARCHIVE_OUTPUT_DIRECTORY "${PLUGIN_OUTPUT_DIRECTORY}" + ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${PLUGIN_OUTPUT_DIRECTORY}" + ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${PLUGIN_OUTPUT_DIRECTORY}" + ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${PLUGIN_OUTPUT_DIRECTORY}" + ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${PLUGIN_OUTPUT_DIRECTORY}" +) + +# +# Include directories +# + +target_include_directories(${target} + PRIVATE + ${PROJECT_BINARY_DIR}/source/include + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR}/include + + $ # MetaCall includes + + PUBLIC + ${DEFAULT_INCLUDE_DIRECTORIES} + + INTERFACE + $ + $ + $ +) + +# +# Libraries +# + +target_link_libraries(${target} + PRIVATE + ${META_PROJECT_NAME}::metacall # MetaCall library + + LibSecComp::LibSecComp # LibSecComp library + + PUBLIC + ${DEFAULT_LIBRARIES} + + INTERFACE +) + +# +# Compile definitions +# + +target_compile_definitions(${target} + PRIVATE + + PUBLIC + $<$>:${target_upper}_STATIC_DEFINE> + ${DEFAULT_COMPILE_DEFINITIONS} + + INTERFACE +) + +# +# Compile options +# + +target_compile_options(${target} + PRIVATE + + PUBLIC + ${DEFAULT_COMPILE_OPTIONS} + + INTERFACE +) + +# +# Linker options +# + +target_link_libraries(${target} + PRIVATE + + PUBLIC + ${DEFAULT_LINKER_OPTIONS} + + INTERFACE +) + +# +# Define dependencies +# + +# Copy metacall.json +add_custom_target(${target}-create-plugin-dir ALL + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E make_directory ${PLUGIN_OUTPUT_DIRECTORY} + COMMAND ${CMAKE_COMMAND} -E copy ${source_path}/metacall.json ${PLUGIN_OUTPUT_DIRECTORY}/metacall.json +) + +set_target_properties(${target}-create-plugin-dir + PROPERTIES + FOLDER "${IDE_FOLDER}" +) + +add_dependencies(${target} + ${target}-create-plugin-dir + plugin_extension +) diff --git a/source/plugins/sandbox_plugin/cmake/FindLibSecComp.cmake b/source/plugins/sandbox_plugin/cmake/FindLibSecComp.cmake new file mode 100644 index 000000000..b1e2af0c8 --- /dev/null +++ b/source/plugins/sandbox_plugin/cmake/FindLibSecComp.cmake @@ -0,0 +1,100 @@ +# +# CMake Find LibSecComp library by Parra Studios +# CMake script to find SecComp library. +# +# Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Find SecComp library and include paths +# +# LibSecComp_FOUND - True if SecComp library was found +# LibSecComp_INCLUDE_DIR - SecComp headers path +# LibSecComp_LIBRARY - List of SecComp libraries +# LibSecComp::LibSecComp - CMake target library + +# Prevent vervosity if already included +if(LibSecComp_FOUND) + set(LibSecComp_FIND_QUITELY TRUE) +endif() + +# Try to find the library paths with pkg-config +find_package(PkgConfig QUIET) + +if(PKG_CONFIG_FOUND) + pkg_check_modules(PKG_LibSecComp QUIET libseccomp libseccomp2) +endif() + +# Find library includes +find_path(LibSecComp_INCLUDE_DIRS + NAMES seccomp.h + HINTS ${PKG_LibSecComp_INCLUDE_DIRS} +) + +# Find library +set(LibSecComp_SUFFIXES + x86_64-linux-gnu + aarch64-linux-gnu + arm-linux-gnueabi + arm-linux-gnueabihf + i386-linux-gnu + mips64el-linux-gnuabi64 + mipsel-linux-gnu + powerpc64le-linux-gnu + s390x-linux-gnu +) + +# Require LibSecComp as shared library +set(LibSecComp_LIBRARY_NAMES + ${CMAKE_SHARED_LIBRARY_PREFIX}seccomp${CMAKE_SHARED_LIBRARY_SUFFIX} +) + +if(LibSecComp_FIND_VERSION) + set(LibSecComp_LIBRARY_NAMES + ${LibSecComp_LIBRARY_NAMES} + ${CMAKE_SHARED_LIBRARY_PREFIX}seccomp${CMAKE_SHARED_LIBRARY_SUFFIX}.${LibSecComp_FIND_VERSION} + ) +endif() + +find_library(LibSecComp_LIBRARIES + NAMES ${LibSecComp_LIBRARY_NAMES} + HINTS ${PKG_LibSecComp_LIBRARY_DIRS} + PATHS /usr /usr/lib /usr/local /opt/local + PATH_SUFFIXES lib lib64 ${LibSecComp_SUFFIXES} +) + +# Declare the library and required paths +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LibSecComp + FOUND_VAR LibSecComp_FOUND + REQUIRED_VARS LibSecComp_LIBRARIES LibSecComp_INCLUDE_DIRS +) + +# Define CMake library target +if (LibSecComp_FOUND AND NOT TARGET LibSecComp::LibSecComp) + add_library(LibSecComp::LibSecComp UNKNOWN IMPORTED) + set_target_properties(LibSecComp::LibSecComp PROPERTIES + IMPORTED_LOCATION "${LibSecComp_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${LibSecComp_INCLUDE_DIRS}" + ) +endif() + +mark_as_advanced(LibSecComp_LIBRARIES LibSecComp_INCLUDE_DIRS) + +# Add extra properties +include(FeatureSummary) +set_package_properties(LibSecComp PROPERTIES + URL "https://github.com/seccomp/libseccomp" + DESCRIPTION "The libseccomp library provides an easy to use, platform independent, interface to the Linux Kernel's syscall filtering mechanism." +) diff --git a/source/plugins/sandbox_plugin/include/sandbox_plugin/sandbox_plugin.h b/source/plugins/sandbox_plugin/include/sandbox_plugin/sandbox_plugin.h new file mode 100644 index 000000000..9ec080fd4 --- /dev/null +++ b/source/plugins/sandbox_plugin/include/sandbox_plugin/sandbox_plugin.h @@ -0,0 +1,40 @@ +/* + * Sandbox Plugin by Parra Studios + * A plugin implementing sandboxing functionality for MetaCall Core. + * + * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef SANDBOX_PLUGIN_H +#define SANDBOX_PLUGIN_H 1 + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +SANDBOX_PLUGIN_API int sandbox_plugin(void *loader, void *handle, void *context); + +DYNLINK_SYMBOL_EXPORT(sandbox_plugin); + +#ifdef __cplusplus +} +#endif + +#endif /* SANDBOX_PLUGIN_H */ diff --git a/source/plugins/sandbox_plugin/source/metacall.json b/source/plugins/sandbox_plugin/source/metacall.json new file mode 100644 index 000000000..53c43f817 --- /dev/null +++ b/source/plugins/sandbox_plugin/source/metacall.json @@ -0,0 +1,7 @@ +{ + "language_id": "ext", + "path": ".", + "scripts": [ + "sandbox_plugin" + ] +} diff --git a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp new file mode 100644 index 000000000..3251935ea --- /dev/null +++ b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp @@ -0,0 +1,194 @@ +/* + * Sandbox Plugin by Parra Studios + * A plugin implementing sandboxing functionality for MetaCall Core. + * + * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include + +#include + +#include + +#include + +/* TODO: Use SCMP_ACT_KILL_PROCESS for catching the signal and showing the stack trace? */ +#define SANDBOX_DEFAULT_ACTION SCMP_ACT_ALLOW // SCMP_ACT_KILL + +void *sandbox_initialize(size_t argc, void *args[], void *data) +{ + scmp_filter_ctx ctx; + + (void)argc; + (void)args; + (void)data; + + /* Initialize the scmp context */ + ctx = seccomp_init(SANDBOX_DEFAULT_ACTION); + + if (ctx == NULL) + { + log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to initialize a context."); + } + + return metacall_value_create_ptr(ctx); +} + +/*int sandbox_uname(void *ctx, int allow) +{ + seccomp_rule_add(ctx, allow == 0L ? SCMP_ACT_KILL : SCMP_ACT_ALLOW, SCMP_SYS(uname), 0); + seccomp_load(ctx); + return 0; +}*/ + +void *sandbox_uname(size_t argc, void *args[], void *data) +{ + scmp_filter_ctx ctx; + + (void)data; + + if (argc != 2) + { + log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to set uname syscall permissions. The required number of argumens is one, received: %" PRIuS, argc); + goto error_args; + } + + if (metacall_value_id(args[0]) != METACALL_PTR) + { + log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to set uname syscall permissions. " + "The first parameter requires a pointer to the context, received: %s", + metacall_value_type_name(args[0])); + goto error_args; + } + + if (metacall_value_id(args[1]) != METACALL_BOOL) + { + log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to set uname syscall permissions. " + "The second parameter requires a boolean indicating if it is allowed or not, received: %s", + metacall_value_type_name(args[1])); + goto error_args; + } + + ctx = metacall_value_to_ptr(args[0]); + + seccomp_rule_add(ctx, metacall_value_to_bool(args[1]) == 0L ? SCMP_ACT_KILL : SCMP_ACT_ALLOW, SCMP_SYS(uname), 0); + seccomp_load(ctx); + + return metacall_value_create_int(0); + +error_args: + return metacall_value_create_int(1); +} + +void *sandbox_destroy(size_t argc, void *args[], void *data) +{ + scmp_filter_ctx ctx; + + (void)data; + + if (argc != 1) + { + log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to destroy a context. The required number of argumens is one, received: %" PRIuS, argc); + goto error_args; + } + + if (metacall_value_id(args[0]) != METACALL_PTR) + { + log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to destroy a context. " + "The first parameter requires a pointer to the context, received: %s", + metacall_value_type_name(args[0])); + goto error_args; + } + + ctx = metacall_value_to_ptr(args[0]); + + if (ctx == NULL) + { + log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to destroy a context. " + "The first parameter requires a non null pointer"); + goto error_args; + } + + seccomp_release(ctx); + + return metacall_value_create_int(0); + +error_args: + return metacall_value_create_int(1); +} + +#ifdef METACALL_FORK_SAFE +static int sandbox_plugin_post_fork_callback(metacall_pid id, void *data) +{ + (void)id; + (void)data; + + /* Reset libseccomp library status: https://man7.org/linux/man-pages/man3/seccomp_init.3.html */ + return seccomp_reset(NULL, SANDBOX_DEFAULT_ACTION); +} +#endif /* METACALL_FORK_SAFE */ + +int sandbox_plugin(void *loader, void *handle, void *context) +{ + (void)handle; + +#define SANDBOX_FUNCTION_IMPL_0(ret, name) \ + do \ + { \ + if (metacall_register_loaderv(loader, context, PREPROCESSOR_STRINGIFY(name), name, ret, 0, NULL) != 0) \ + { \ + log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \ + return 1; \ + } \ + } while (0) + +#define SANDBOX_FUNCTION_IMPL(ret, name, ...) \ + do \ + { \ + enum metacall_value_id arg_types[] = { __VA_ARGS__ }; \ + if (metacall_register_loaderv(loader, context, PREPROCESSOR_STRINGIFY(name), name, ret, PREPROCESSOR_ARGS_COUNT(__VA_ARGS__), arg_types) != 0) \ + { \ + log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \ + return 1; \ + } \ + } while (0) + +#define SANDBOX_FUNCTION(ret, name, ...) \ + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + SANDBOX_FUNCTION_IMPL_0(ret, PREPROCESSOR_CONCAT(sandbox_, name)), \ + SANDBOX_FUNCTION_IMPL(ret, PREPROCESSOR_CONCAT(sandbox_, name), __VA_ARGS__)) + + SANDBOX_FUNCTION(METACALL_PTR, initialize); + SANDBOX_FUNCTION_IMPL(METACALL_INT, sandbox_uname, METACALL_PTR, METACALL_BOOL); + SANDBOX_FUNCTION_IMPL(METACALL_INT, sandbox_destroy, METACALL_PTR); + +#undef SANDBOX_FUNCTION_IMPL_0 +#undef SANDBOX_FUNCTION_IMPL +#undef SANDBOX_FUNCTION + +#if 0 /* TODO: Fork safety */ + #ifdef METACALL_FORK_SAFE + /* TODO: This requires to implement multiple callback handling in metacall_fork which is not implemented yet, + and maybe also passing a context to the pre/post fork callbacks which is not implemented neither */ + metacall_fork(NULL, &sandbox_plugin_post_fork_callback); + #endif /* METACALL_FORK_SAFE */ +#endif + + return 0; +} diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index 34461bdc9..38a23906a 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -243,3 +243,4 @@ add_subdirectory(metacall_plugin_extension_destroy_order_test) add_subdirectory(metacall_cli_core_plugin_test) add_subdirectory(metacall_cli_core_plugin_await_test) add_subdirectory(metacall_backtrace_plugin_test) +add_subdirectory(metacall_sandbox_plugin_test) diff --git a/source/tests/metacall_backtrace_plugin_test/source/main.cpp b/source/tests/metacall_backtrace_plugin_test/source/main.cpp index 4676e4763..628e40890 100644 --- a/source/tests/metacall_backtrace_plugin_test/source/main.cpp +++ b/source/tests/metacall_backtrace_plugin_test/source/main.cpp @@ -1,6 +1,6 @@ /* - * Loader Library by Parra Studios - * A plugin for loading ruby code at run-time into a process. + * MetaCall Library by Parra Studios + * A library for providing a foreign function interface calls. * * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia * diff --git a/source/tests/metacall_backtrace_plugin_test/source/metacall_backtrace_plugin_test.cpp b/source/tests/metacall_backtrace_plugin_test/source/metacall_backtrace_plugin_test.cpp index 0f6739501..d06acd721 100644 --- a/source/tests/metacall_backtrace_plugin_test/source/metacall_backtrace_plugin_test.cpp +++ b/source/tests/metacall_backtrace_plugin_test/source/metacall_backtrace_plugin_test.cpp @@ -1,6 +1,6 @@ /* - * Loader Library by Parra Studios - * A plugin for loading ruby code at run-time into a process. + * MetaCall Library by Parra Studios + * A library for providing a foreign function interface calls. * * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia * @@ -58,10 +58,7 @@ TEST_F(metacall_backtrace_plugin_test, DefaultConstructor) ASSERT_EQ((int)0, (int)metacall_initialize()); /* Generate a segmentation fault in order to catch it by backtrace plugin */ - EXPECT_DEATH({ - badass_function(); - }, - ""); + EXPECT_DEATH({ badass_function(); }, ""); EXPECT_EQ((int)0, (int)metacall_destroy()); } diff --git a/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt b/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt new file mode 100644 index 000000000..354274b73 --- /dev/null +++ b/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt @@ -0,0 +1,154 @@ +# Check if this loader is enabled +if(NOT OPTION_BUILD_LOADERS OR NOT OPTION_BUILD_LOADERS_EXT OR NOT OPTION_BUILD_EXTENSIONS OR NOT OPTION_BUILD_PLUGINS_SANDBOX) + return() +endif() + +include(Portability) + +if(NOT PROJECT_OS_FAMILY STREQUAL unix) + return() +endif() + +# +# Executable name and options +# + +# Target name +set(target metacall-sandbox-plugin-test) +message(STATUS "Test ${target}") + +# +# Compiler warnings +# + +include(Warnings) + +# +# Compiler security +# + +include(SecurityFlags) + +# +# Sources +# + +set(include_path "${CMAKE_CURRENT_SOURCE_DIR}/include/${target}") +set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/source") + +set(sources + ${source_path}/main.cpp + ${source_path}/metacall_sandbox_plugin_test.cpp +) + +# Group source files +set(header_group "Header Files (API)") +set(source_group "Source Files") +source_group_by_path(${include_path} "\\\\.h$|\\\\.hpp$" + ${header_group} ${headers}) +source_group_by_path(${source_path} "\\\\.cpp$|\\\\.c$|\\\\.h$|\\\\.hpp$" + ${source_group} ${sources}) + +# +# Create executable +# + +# Build executable +add_executable(${target} + ${sources} +) + +# Create namespaced alias +add_executable(${META_PROJECT_NAME}::${target} ALIAS ${target}) + +# +# Project options +# + +set_target_properties(${target} + PROPERTIES + ${DEFAULT_PROJECT_OPTIONS} + FOLDER "${IDE_FOLDER}" +) + +# +# Include directories +# + +target_include_directories(${target} + PRIVATE + ${DEFAULT_INCLUDE_DIRECTORIES} + ${PROJECT_BINARY_DIR}/source/include +) + +# +# Libraries +# + +target_link_libraries(${target} + PRIVATE + ${DEFAULT_LIBRARIES} + + GTest + + ${META_PROJECT_NAME}::metacall +) + +# +# Compile definitions +# + +target_compile_definitions(${target} + PRIVATE + ${DEFAULT_COMPILE_DEFINITIONS} +) + +# +# Compile options +# + +target_compile_options(${target} + PRIVATE + ${DEFAULT_COMPILE_OPTIONS} +) + +# +# Linker options +# + +target_link_libraries(${target} + PRIVATE + ${DEFAULT_LINKER_OPTIONS} +) + +# +# Define test +# + +add_test(NAME ${target} + COMMAND $ +) + +# +# Define dependencies +# + +add_dependencies(${target} + ext_loader + sandbox_plugin +) + +# +# Define test properties +# + +set_property(TEST ${target} + PROPERTY LABELS ${target} +) + +include(TestEnvironmentVariables) + +test_environment_variables(${target} + "" + ${TESTS_ENVIRONMENT_VARIABLES} +) diff --git a/source/tests/metacall_sandbox_plugin_test/source/main.cpp b/source/tests/metacall_sandbox_plugin_test/source/main.cpp new file mode 100644 index 000000000..628e40890 --- /dev/null +++ b/source/tests/metacall_sandbox_plugin_test/source/main.cpp @@ -0,0 +1,28 @@ +/* + * MetaCall Library by Parra Studios + * A library for providing a foreign function interface calls. + * + * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +int main(int argc, char *argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} diff --git a/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp b/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp new file mode 100644 index 000000000..e9beb938f --- /dev/null +++ b/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp @@ -0,0 +1,87 @@ +/* + * MetaCall Library by Parra Studios + * A library for providing a foreign function interface calls. + * + * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include + +#include +#include + +void invalid_syscall(void) +{ + struct utsname data; + uname(&data); + printf("%s\n", data.sysname); +} + +class metacall_sandbox_plugin_test : public testing::Test +{ +protected: +}; + +TEST_F(metacall_sandbox_plugin_test, DefaultConstructor) +{ + ASSERT_EQ((int)0, (int)metacall_initialize()); + + void *sandbox_ctx, *handle = metacall_plugin_extension(); + + /* Initialize sandboxing */ + { + void *args[1] = { metacall_value_create_bool(0L) }; + + sandbox_ctx = metacallhv_s(handle, "sandbox_initialize", args, 1); + + EXPECT_NE((void *)NULL, (void *)sandbox_ctx); + EXPECT_NE((void *)metacall_value_to_ptr(sandbox_ctx), (void *)NULL); + + metacall_value_destroy(args[0]); + } + + /* Disable uname syscall */ + { + void *args[2] = { sandbox_ctx, metacall_value_create_bool(0L) }; + + void *ret = metacallhv_s(handle, "sandbox_uname", args, 2); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(ret); + metacall_value_destroy(args[1]); + } + + /* Generate a syscall exception when trying to execute uname */ + ASSERT_EXIT({ invalid_syscall(); }, testing::KilledBySignal(SIGSYS), ""); + + /* Destroy sandboxing */ + { + void *args[1] = { sandbox_ctx }; + + void *ret = metacallhv_s(handle, "sandbox_destroy", args, 1); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(args[0]); + } + + EXPECT_EQ((int)0, (int)metacall_destroy()); +} From 8bda05bf48455ca7be808129ec6f5d0e8aadc0ae Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 28 Sep 2023 01:54:19 +0200 Subject: [PATCH 007/615] Add sandboxing to the tooling and ci. --- docker-compose.test.yml | 4 ++-- tools/metacall-configure.sh | 13 +++++++++++++ tools/metacall-environment.sh | 22 ++++++++++++++++++++++ tools/metacall-runtime.sh | 34 +++++++++++++++++++++++++++++++++- 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 5b2784f5f..c08b897f3 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -24,10 +24,10 @@ services: image: metacall/core:deps build: args: - METACALL_INSTALL_OPTIONS: base python ruby netcore7 nodejs typescript file rpc wasm java c cobol go rust rapidjson funchook swig pack backtrace # clangformat v8rep51 coverage + METACALL_INSTALL_OPTIONS: base python ruby netcore7 nodejs typescript file rpc wasm java c cobol go rust rapidjson funchook swig pack backtrace sandbox # clangformat v8rep51 coverage dev: image: metacall/core:dev build: args: METACALL_BUILD_TYPE: ${METACALL_BUILD_TYPE} - METACALL_BUILD_OPTIONS: ${METACALL_BUILD_SANITIZER} python ruby netcore7 nodejs typescript file rpc wasm java c cobol go rust examples tests scripts ports install pack benchmarks # v8 coverage + METACALL_BUILD_OPTIONS: ${METACALL_BUILD_SANITIZER} python ruby netcore7 nodejs typescript file rpc wasm java c cobol go rust examples tests scripts ports install pack sandbox benchmarks # v8 coverage diff --git a/tools/metacall-configure.sh b/tools/metacall-configure.sh index de53616ad..2a44d9614 100755 --- a/tools/metacall-configure.sh +++ b/tools/metacall-configure.sh @@ -45,6 +45,7 @@ BUILD_EXAMPLES=0 BUILD_TESTS=0 BUILD_BENCHMARKS=0 BUILD_PORTS=0 +BUILD_SANDBOX=0 BUILD_COVERAGE=0 BUILD_ADDRESS_SANITIZER=0 BUILD_THREAD_SANITIZER=0 @@ -162,6 +163,10 @@ sub_options() { echo "Build all ports" BUILD_PORTS=1 fi + if [ "$option" = 'sandbox' ]; then + echo "Build with sandboxing support" + BUILD_SANDBOX=1 + fi if [ "$option" = 'coverage' ]; then echo "Build all coverage reports" BUILD_COVERAGE=1 @@ -442,6 +447,13 @@ sub_configure() { BUILD_STRING="$BUILD_STRING -DOPTION_BUILD_PORTS=Off" fi + # Sandbox + if [ $BUILD_SANDBOX = 1 ]; then + BUILD_STRING="$BUILD_STRING -DOPTION_BUILD_PLUGINS_SANDBOX=On" + else + BUILD_STRING="$BUILD_STRING -DOPTION_BUILD_PLUGINS_SANDBOX=Off" + fi + # Coverage if [ $BUILD_COVERAGE = 1 ]; then BUILD_STRING="$BUILD_STRING -DOPTION_COVERAGE=On" @@ -514,6 +526,7 @@ sub_help() { echo " install: install all libraries" echo " static: build as static libraries" echo " ports: build all ports" + echo " sandbox: build with sandboxing support" echo " coverage: build all coverage reports" echo " address-sanitizer: build with address sanitizer" echo " thread-sanitizer: build with thread sanitizer" diff --git a/tools/metacall-environment.sh b/tools/metacall-environment.sh index 9b22faf0c..90c4e0798 100755 --- a/tools/metacall-environment.sh +++ b/tools/metacall-environment.sh @@ -56,6 +56,7 @@ INSTALL_PACK=0 INSTALL_COVERAGE=0 INSTALL_CLANGFORMAT=0 INSTALL_BACKTRACE=0 +INSTALL_SANDBOX=0 SHOW_HELP=0 PROGNAME=$(basename $0) @@ -818,7 +819,20 @@ sub_backtrace(){ echo "-DLIBDWARF_INCLUDE_DIR=${LIBDWARD_PREFIX}/include" >> $CMAKE_CONFIG_PATH echo "-DLIBELF_LIBRARY=${LIBELF_PREFIX}/lib/libelf.a" >> $CMAKE_CONFIG_PATH echo "-DLIBELF_INCLUDE_DIR=${LIBELF_PREFIX}/include" >> $CMAKE_CONFIG_PATH + fi +} +# Sandbox (this provides sandboxing features in Linux through BFS filters with libseccomp) +sub_sandbox(){ + echo "configure sandbox" + cd $ROOT_DIR + + if [ "${OPERATIVE_SYSTEM}" = "Linux" ]; then + if [ "${LINUX_DISTRO}" = "debian" ] || [ "${LINUX_DISTRO}" = "ubuntu" ]; then + $SUDO_CMD apt-get install -y --no-install-recommends libseccomp-dev + elif [ "${LINUX_DISTRO}" = "alpine" ]; then + $SUDO_CMD apk add --no-cache libseccomp-dev + fi fi } @@ -907,6 +921,9 @@ sub_install(){ if [ $INSTALL_BACKTRACE = 1 ]; then sub_backtrace fi + if [ $INSTALL_SANDBOX = 1 ]; then + sub_sandbox + fi echo "install finished in workspace $ROOT_DIR" } @@ -1041,6 +1058,10 @@ sub_options(){ echo "backtrace selected" INSTALL_BACKTRACE=1 fi + if [ "$var" = 'sandbox' ]; then + echo "sandbox selected" + INSTALL_SANDBOX=1 + fi done } @@ -1077,6 +1098,7 @@ sub_help() { echo " coverage" echo " clangformat" echo " backtrace" + echo " sandbox" echo "" } diff --git a/tools/metacall-runtime.sh b/tools/metacall-runtime.sh index 50cc16c06..b272aefad 100755 --- a/tools/metacall-runtime.sh +++ b/tools/metacall-runtime.sh @@ -39,6 +39,7 @@ INSTALL_JAVA=0 INSTALL_C=0 INSTALL_COBOL=0 INSTALL_BACKTRACE=0 +INSTALL_SANDBOX=0 INSTALL_PORTS=0 INSTALL_CLEAN=0 SHOW_HELP=0 @@ -267,7 +268,30 @@ sub_cobol(){ sub_backtrace(){ echo "configure backtrace" - sub_apt_install_hold libdw1 + if [ "${OPERATIVE_SYSTEM}" = "Linux" ]; then + if [ "${LINUX_DISTRO}" = "debian" ] || [ "${LINUX_DISTRO}" = "ubuntu" ]; then + sub_apt_install_hold libdw1 + elif [ "${LINUX_DISTRO}" = "alpine" ]; then + $SUDO_CMD apk add --no-cache binutils + fi + elif [ "${OPERATIVE_SYSTEM}" = "Darwin" ]; then + brew install dwarfutils + brew install libelf + fi +} + +# Sandbox (this provides sandboxing features in Linux through BFS filters with libseccomp) +sub_sandbox(){ + echo "configure sandbox" + cd $ROOT_DIR + + if [ "${OPERATIVE_SYSTEM}" = "Linux" ]; then + if [ "${LINUX_DISTRO}" = "debian" ] || [ "${LINUX_DISTRO}" = "ubuntu" ]; then + $SUDO_CMD apt-get install -y --no-install-recommends libseccomp + elif [ "${LINUX_DISTRO}" = "alpine" ]; then + $SUDO_CMD apk add --no-cache libseccomp + fi + fi } # Ports @@ -327,6 +351,9 @@ sub_install(){ if [ $INSTALL_BACKTRACE = 1 ]; then sub_backtrace fi + if [ $INSTALL_SANDBOX = 1 ]; then + sub_sandbox + fi if [ $INSTALL_PORTS = 1 ]; then sub_ports fi @@ -413,6 +440,10 @@ sub_options(){ echo "backtrace selected" INSTALL_BACKTRACE=1 fi + if [ "$var" = 'sandbox' ]; then + echo "sandbox selected" + INSTALL_SANDBOX=1 + fi if [ "$var" = 'ports' ]; then echo "ports selected" INSTALL_PORTS=1 @@ -443,6 +474,7 @@ sub_help() { echo " c" echo " cobol" echo " backtrace" + echo " sandbox" echo " ports" echo " clean" echo "" From 3bf25cbb6aa95bc8e5f4ee549db654cb3459e010 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 28 Sep 2023 01:57:48 +0200 Subject: [PATCH 008/615] Change timeout of tests from 5400 to 7200. --- source/tests/CMakeLists.txt | 2 +- tools/metacall-build.ps1 | 2 +- tools/metacall-build.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index 38a23906a..8f50f50c5 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -80,7 +80,7 @@ if(OPTION_TEST_MEMORYCHECK AND NOT (OPTION_BUILD_ADDRESS_SANITIZER OR OPTION_BUI --label-exclude MEMCHECK_IGNORE --force-new-ctest-process --test-action memcheck - --timeout 5400 + --timeout 7200 COMMAND ${CMAKE_COMMAND} -E cat "${CMAKE_BINARY_DIR}/Testing/Temporary/MemoryChecker.*.log" ) endif() diff --git a/tools/metacall-build.ps1 b/tools/metacall-build.ps1 index 4c758006a..482d65cd9 100755 --- a/tools/metacall-build.ps1 +++ b/tools/metacall-build.ps1 @@ -78,7 +78,7 @@ function Sub-Build { # Tests (coverage needs to run the tests) if (($BUILD_TESTS -eq 1) -or ($BUILD_BENCHMARKS -eq 1) -or ($BUILD_COVERAGE -eq 1)) { echo "Running the tests..." - ctest "-j$((Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors)" --timeout 5400 --output-on-failure -C $BUILD_TYPE + ctest "-j$((Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors)" --timeout 7200 --output-on-failure -C $BUILD_TYPE if (-not $?) { $RecentExitCode = $LASTEXITCODE diff --git a/tools/metacall-build.sh b/tools/metacall-build.sh index d0a97492e..6535fb21b 100755 --- a/tools/metacall-build.sh +++ b/tools/metacall-build.sh @@ -75,7 +75,7 @@ sub_build() { # Tests (coverage needs to run the tests) if [ $BUILD_TESTS = 1 ] || [ $BUILD_BENCHMARKS=1 ] || [ $BUILD_COVERAGE = 1 ]; then - ctest -j$(getconf _NPROCESSORS_ONLN) --timeout 5400 --output-on-failure --test-output-size-failed 3221000000 -C $BUILD_TYPE + ctest -j$(getconf _NPROCESSORS_ONLN) --timeout 7200 --output-on-failure --test-output-size-failed 3221000000 -C $BUILD_TYPE fi # Coverage From 0ae725283b3196eac28a4387c2476c6f10b0753d Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 28 Sep 2023 02:02:15 +0200 Subject: [PATCH 009/615] Trying to solve issues with win32 ci. --- cmake/FindNodeJS.cmake | 2 +- source/loaders/node_loader/CMakeLists.txt | 4 ++-- source/loaders/py_loader/CMakeLists.txt | 4 ++-- source/loaders/rb_loader/CMakeLists.txt | 4 ++-- source/loaders/rpc_loader/CMakeLists.txt | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cmake/FindNodeJS.cmake b/cmake/FindNodeJS.cmake index f369a40b5..37bd26a00 100644 --- a/cmake/FindNodeJS.cmake +++ b/cmake/FindNodeJS.cmake @@ -489,7 +489,7 @@ if(NOT NodeJS_LIBRARY) # Copy library to MetaCall output path execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_OUTPUT_DIR}) - file(COPY ${NodeJS_COMPILE_PATH}/${NodeJS_LIBRARY_NAME} DESTINATION ${PROJECT_OUTPUT_DIR}) + file(COPY "${NodeJS_COMPILE_PATH}/${NodeJS_LIBRARY_NAME}" DESTINATION ${PROJECT_OUTPUT_DIR}) message(STATUS "Install NodeJS shared library") endif() diff --git a/source/loaders/node_loader/CMakeLists.txt b/source/loaders/node_loader/CMakeLists.txt index be4391592..7d887d5d0 100644 --- a/source/loaders/node_loader/CMakeLists.txt +++ b/source/loaders/node_loader/CMakeLists.txt @@ -19,7 +19,7 @@ endif() # TODO: https://gist.github.com/micahsnyder/5d98ac8548b429309ec5a35bca9366da if(NodeJS_LIBRARY_NAME_PATH AND WIN32) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_OUTPUT_DIR}) - file(COPY ${NodeJS_LIBRARY_NAME_PATH} DESTINATION ${PROJECT_OUTPUT_DIR}) + file(COPY "${NodeJS_LIBRARY_NAME_PATH}" DESTINATION ${PROJECT_OUTPUT_DIR}) endif() # @@ -230,7 +230,7 @@ install(TARGETS ${target} # TODO: https://gist.github.com/micahsnyder/5d98ac8548b429309ec5a35bca9366da if(NodeJS_LIBRARY_NAME_PATH AND WIN32) install(FILES - ${NodeJS_LIBRARY_NAME_PATH} + "${NodeJS_LIBRARY_NAME_PATH}" DESTINATION ${INSTALL_LIB} COMPONENT runtime ) diff --git a/source/loaders/py_loader/CMakeLists.txt b/source/loaders/py_loader/CMakeLists.txt index 61db0917e..39136bb2f 100644 --- a/source/loaders/py_loader/CMakeLists.txt +++ b/source/loaders/py_loader/CMakeLists.txt @@ -46,7 +46,7 @@ endif() if(Python3_LIBRARY_NAME) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_OUTPUT_DIR}) - file(COPY ${Python3_LIBRARY_NAME} DESTINATION ${PROJECT_OUTPUT_DIR}) + file(COPY "${Python3_LIBRARY_NAME}" DESTINATION ${PROJECT_OUTPUT_DIR}) endif() # @@ -231,7 +231,7 @@ install(TARGETS ${target} # TODO: https://gist.github.com/micahsnyder/5d98ac8548b429309ec5a35bca9366da if(Python3_LIBRARY_NAME) install(FILES - ${Python3_LIBRARY_NAME} + "${Python3_LIBRARY_NAME}" DESTINATION ${INSTALL_LIB} COMPONENT runtime ) diff --git a/source/loaders/rb_loader/CMakeLists.txt b/source/loaders/rb_loader/CMakeLists.txt index 4d28a04e8..787fb3a17 100644 --- a/source/loaders/rb_loader/CMakeLists.txt +++ b/source/loaders/rb_loader/CMakeLists.txt @@ -19,7 +19,7 @@ endif() # TODO: https://gist.github.com/micahsnyder/5d98ac8548b429309ec5a35bca9366da if(WIN32 AND Ruby_LIBRARY_NAME) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_OUTPUT_DIR}) - file(COPY ${Ruby_LIBRARY_NAME} DESTINATION ${PROJECT_OUTPUT_DIR}) + file(COPY "${Ruby_LIBRARY_NAME}" DESTINATION ${PROJECT_OUTPUT_DIR}) endif() # @@ -212,7 +212,7 @@ install(TARGETS ${target} # TODO: https://gist.github.com/micahsnyder/5d98ac8548b429309ec5a35bca9366da if(WIN32 AND Ruby_LIBRARY_NAME) install(FILES - ${Ruby_LIBRARY_NAME} + "${Ruby_LIBRARY_NAME}" DESTINATION ${INSTALL_LIB} COMPONENT runtime ) diff --git a/source/loaders/rpc_loader/CMakeLists.txt b/source/loaders/rpc_loader/CMakeLists.txt index 6663e6f74..9ebdc58c0 100644 --- a/source/loaders/rpc_loader/CMakeLists.txt +++ b/source/loaders/rpc_loader/CMakeLists.txt @@ -14,7 +14,7 @@ find_package(CURL REQUIRED) # TODO: https://gist.github.com/micahsnyder/5d98ac8548b429309ec5a35bca9366da if(WIN32 AND CURL_LIBRARY_NAME) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_OUTPUT_DIR}) - file(COPY ${CURL_LIBRARY_NAME} DESTINATION ${PROJECT_OUTPUT_DIR}) + file(COPY "${CURL_LIBRARY_NAME}" DESTINATION ${PROJECT_OUTPUT_DIR}) endif() # @@ -197,7 +197,7 @@ install(TARGETS ${target} # TODO: https://gist.github.com/micahsnyder/5d98ac8548b429309ec5a35bca9366da if(WIN32 AND CURL_LIBRARY_NAME) install(FILES - ${CURL_LIBRARY_NAME} + "${CURL_LIBRARY_NAME}" DESTINATION ${INSTALL_LIB} COMPONENT runtime ) From f71fae5addc6c497a7ec5d0509afb8bd82d7f804 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 28 Sep 2023 02:05:23 +0200 Subject: [PATCH 010/615] Solve issue with path curl. --- tools/metacall-environment.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/metacall-environment.ps1 b/tools/metacall-environment.ps1 index 67c1c366a..0861ea1f3 100755 --- a/tools/metacall-environment.ps1 +++ b/tools/metacall-environment.ps1 @@ -193,18 +193,19 @@ function Set-Curl { Set-Location $ROOT_DIR $RuntimeDir = "$env:ProgramFiles\curl" $DepsDir = "$ROOT_DIR\dependencies" + $Version = "8.3.0_2" if (!(Test-Path -Path "$DepsDir\curl.zip")) { # Download installer Write-Output "Curl not found downloading now..." - (New-Object Net.WebClient).DownloadFile("https://curl.se/windows/dl-8.3.0_2/curl-8.3.0_2-win64-mingw.zip", "$DepsDir\curl.zip") + (New-Object Net.WebClient).DownloadFile("https://curl.se/windows/dl-$Version/curl-$Version-win64-mingw.zip", "$DepsDir\curl.zip") } Set-Location $DepsDir 7z x "$DepsDir\curl.zip" - robocopy /move /e "$DepsDir\curl-8.1.2_3-win64-mingw" $RuntimeDir + robocopy /move /e "$DepsDir\curl-$Version-win64-mingw" $RuntimeDir Add-to-Path "$RuntimeDir\bin" From 404b8ef276955f194cd5ffafc80cd1813fed3c65 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Wed, 4 Oct 2023 18:20:25 +0200 Subject: [PATCH 011/615] Add base interface for declaring plugins. --- .../source/cli_core_plugin.cpp | 62 +++---------------- .../plugin/include/plugin/plugin_interface.h | 58 +++++++++++++++++ .../sandbox_plugin/source/sandbox_plugin.cpp | 44 ++----------- .../include/preprocessor/preprocessor_if.h | 12 ++-- 4 files changed, 78 insertions(+), 98 deletions(-) create mode 100644 source/plugin/include/plugin/plugin_interface.h diff --git a/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp b/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp index 00e7f665a..a308fce68 100644 --- a/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp +++ b/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp @@ -20,8 +20,7 @@ #include -#include -#include +#include #include @@ -320,59 +319,12 @@ int cli_core_plugin(void *loader, void *handle, void *context) { (void)handle; - { - enum metacall_value_id *arg_types = NULL; - if (metacall_register_loaderv(loader, context, "inspect", inspect, METACALL_STRING, 0, arg_types) != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: inspect"); - return 1; - } - } - - { - enum metacall_value_id arg_types[] = { METACALL_STRING, METACALL_STRING }; - if (metacall_register_loaderv(loader, context, "clear", clear, METACALL_INT, sizeof(arg_types) / sizeof(arg_types[0]), arg_types) != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: clear"); - return 1; - } - } - - { - enum metacall_value_id arg_types[] = { METACALL_STRING }; - if (metacall_register_loaderv(loader, context, "call", call, METACALL_PTR, sizeof(arg_types) / sizeof(arg_types[0]), arg_types) != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: call"); - return 1; - } - } - - { - enum metacall_value_id arg_types[] = { METACALL_STRING }; - if (metacall_register_loaderv(loader, context, "await", await, METACALL_PTR, sizeof(arg_types) / sizeof(arg_types[0]), arg_types) != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: await"); - return 1; - } - } - - { - enum metacall_value_id arg_types[] = { METACALL_STRING, METACALL_STRING }; - if (metacall_register_loaderv(loader, context, "eval", eval, METACALL_INT, sizeof(arg_types) / sizeof(arg_types[0]), arg_types) != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: eval"); - return 1; - } - } - - { - enum metacall_value_id arg_types[] = { METACALL_STRING, METACALL_ARRAY }; - if (metacall_register_loaderv(loader, context, "load", load, METACALL_INT, sizeof(arg_types) / sizeof(arg_types[0]), arg_types) != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: load"); - return 1; - } - } + EXTENSION_FUNCTION(METACALL_STRING, inspect); + EXTENSION_FUNCTION(METACALL_INT, clear, METACALL_STRING, METACALL_STRING); + EXTENSION_FUNCTION(METACALL_PTR, call, METACALL_STRING); + EXTENSION_FUNCTION(METACALL_PTR, await, METACALL_STRING); + EXTENSION_FUNCTION(METACALL_INT, eval, METACALL_STRING, METACALL_STRING); + EXTENSION_FUNCTION(METACALL_INT, load, METACALL_STRING, METACALL_ARRAY); return 0; } diff --git a/source/plugin/include/plugin/plugin_interface.h b/source/plugin/include/plugin/plugin_interface.h new file mode 100644 index 000000000..0775d7265 --- /dev/null +++ b/source/plugin/include/plugin/plugin_interface.h @@ -0,0 +1,58 @@ +/* + * Plugin Library by Parra Studios + * A library for plugins at run-time into a process. + * + * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef PLUGIN_INTERFACE_H +#define PLUGIN_INTERFACE_H 1 + +/* Private interface for using it inside any loader, extension or plugin for registering functions */ + +#include + +#include + +#include + +#define EXTENSION_FUNCTION_IMPL_VOID(ret, name) \ + do \ + { \ + if (metacall_register_loaderv(loader, context, PREPROCESSOR_STRINGIFY(name), name, ret, 0, NULL) != 0) \ + { \ + log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \ + return 1; \ + } \ + } while (0) + +#define EXTENSION_FUNCTION_IMPL(ret, name, ...) \ + do \ + { \ + enum metacall_value_id arg_types[] = { __VA_ARGS__ }; \ + if (metacall_register_loaderv(loader, context, PREPROCESSOR_STRINGIFY(name), name, ret, PREPROCESSOR_ARGS_COUNT(__VA_ARGS__), arg_types) != 0) \ + { \ + log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \ + return 1; \ + } \ + } while (0) + +#define EXTENSION_FUNCTION(ret, name, ...) \ + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + EXTENSION_FUNCTION_IMPL_VOID(ret, name), \ + EXTENSION_FUNCTION_IMPL(ret, name, __VA_ARGS__)) + +#endif /* PLUGIN_INTERFACE_H */ diff --git a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp index 3251935ea..fa70a89d4 100644 --- a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp +++ b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp @@ -20,13 +20,9 @@ #include -#include - -#include +#include -#include - -#include +#include /* TODO: Use SCMP_ACT_KILL_PROCESS for catching the signal and showing the stack trace? */ #define SANDBOX_DEFAULT_ACTION SCMP_ACT_ALLOW // SCMP_ACT_KILL @@ -148,39 +144,9 @@ int sandbox_plugin(void *loader, void *handle, void *context) { (void)handle; -#define SANDBOX_FUNCTION_IMPL_0(ret, name) \ - do \ - { \ - if (metacall_register_loaderv(loader, context, PREPROCESSOR_STRINGIFY(name), name, ret, 0, NULL) != 0) \ - { \ - log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \ - return 1; \ - } \ - } while (0) - -#define SANDBOX_FUNCTION_IMPL(ret, name, ...) \ - do \ - { \ - enum metacall_value_id arg_types[] = { __VA_ARGS__ }; \ - if (metacall_register_loaderv(loader, context, PREPROCESSOR_STRINGIFY(name), name, ret, PREPROCESSOR_ARGS_COUNT(__VA_ARGS__), arg_types) != 0) \ - { \ - log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \ - return 1; \ - } \ - } while (0) - -#define SANDBOX_FUNCTION(ret, name, ...) \ - PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ - SANDBOX_FUNCTION_IMPL_0(ret, PREPROCESSOR_CONCAT(sandbox_, name)), \ - SANDBOX_FUNCTION_IMPL(ret, PREPROCESSOR_CONCAT(sandbox_, name), __VA_ARGS__)) - - SANDBOX_FUNCTION(METACALL_PTR, initialize); - SANDBOX_FUNCTION_IMPL(METACALL_INT, sandbox_uname, METACALL_PTR, METACALL_BOOL); - SANDBOX_FUNCTION_IMPL(METACALL_INT, sandbox_destroy, METACALL_PTR); - -#undef SANDBOX_FUNCTION_IMPL_0 -#undef SANDBOX_FUNCTION_IMPL -#undef SANDBOX_FUNCTION + EXTENSION_FUNCTION(METACALL_PTR, sandbox_initialize); + EXTENSION_FUNCTION(METACALL_INT, sandbox_uname, METACALL_PTR, METACALL_BOOL); + EXTENSION_FUNCTION(METACALL_INT, sandbox_destroy, METACALL_PTR); #if 0 /* TODO: Fork safety */ #ifdef METACALL_FORK_SAFE diff --git a/source/preprocessor/include/preprocessor/preprocessor_if.h b/source/preprocessor/include/preprocessor/preprocessor_if.h index df0cf3759..8e31e054c 100644 --- a/source/preprocessor/include/preprocessor/preprocessor_if.h +++ b/source/preprocessor/include/preprocessor/preprocessor_if.h @@ -21,8 +21,12 @@ extern "C" { /* -- Macros -- */ -#define PREPROCESSOR_IIF_IMPL_0(true_expr, false_expr) false_expr -#define PREPROCESSOR_IIF_IMPL_1(true_expr, false_expr) true_expr +#define PREPROCESSOR_IIF_IMPL_EXPAND_ARGS(...) __VA_ARGS__ +#define PREPROCESSOR_IIF_IMPL_EXPAND(expr) expr +#define PREPROCESSOR_IIF_IMPL_EXPAND_REMOVE_PARENTHESIS(expr) PREPROCESSOR_IIF_IMPL_EXPAND(PREPROCESSOR_IIF_IMPL_EXPAND_ARGS expr) + +#define PREPROCESSOR_IIF_IMPL_0(true_expr, false_expr) PREPROCESSOR_IIF_IMPL_EXPAND_REMOVE_PARENTHESIS(false_expr) +#define PREPROCESSOR_IIF_IMPL_1(true_expr, false_expr) PREPROCESSOR_IIF_IMPL_EXPAND_REMOVE_PARENTHESIS(true_expr) #if defined(_MSC_VER) && !defined(__clang__) #define PREPROCESSOR_IIF_IMPL_I(expr) expr @@ -40,9 +44,9 @@ extern "C" { #if defined(__EDG__) || defined(__EDG_VERSION__) #define PREPROCESSOR_IF_IMPL(condition, true_expr, false_expr) PREPROCESSOR_IIF(PREPROCESSOR_BOOL(condition), true_expr, false_expr) - #define PREPROCESSOR_IF(condition, true_expr, false_expr) PREPROCESSOR_IF_IMPL(condition, true_expr, false_expr) + #define PREPROCESSOR_IF(condition, true_expr, false_expr) PREPROCESSOR_IF_IMPL(condition, (true_expr), (false_expr)) #else - #define PREPROCESSOR_IF(condition, true_expr, false_expr) PREPROCESSOR_IIF(PREPROCESSOR_BOOL(condition), true_expr, false_expr) + #define PREPROCESSOR_IF(condition, true_expr, false_expr) PREPROCESSOR_IIF(PREPROCESSOR_BOOL(condition), (true_expr), (false_expr)) #endif #ifdef __cplusplus From 05b2d0a68f68d7e58f15cc620937ba539e55680d Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 5 Oct 2023 00:44:39 +0200 Subject: [PATCH 012/615] Add special case in preprocessor if for msvc. --- .../sandbox_plugin/source/sandbox_plugin.cpp | 6 ++++-- .../include/preprocessor/preprocessor_if.h | 20 +++++++++++++------ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp index fa70a89d4..df6288b46 100644 --- a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp +++ b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp @@ -129,7 +129,8 @@ void *sandbox_destroy(size_t argc, void *args[], void *data) return metacall_value_create_int(1); } -#ifdef METACALL_FORK_SAFE +#if 0 /* TODO: Fork safety */ + #ifdef METACALL_FORK_SAFE static int sandbox_plugin_post_fork_callback(metacall_pid id, void *data) { (void)id; @@ -138,7 +139,8 @@ static int sandbox_plugin_post_fork_callback(metacall_pid id, void *data) /* Reset libseccomp library status: https://man7.org/linux/man-pages/man3/seccomp_init.3.html */ return seccomp_reset(NULL, SANDBOX_DEFAULT_ACTION); } -#endif /* METACALL_FORK_SAFE */ + #endif /* METACALL_FORK_SAFE */ +#endif int sandbox_plugin(void *loader, void *handle, void *context) { diff --git a/source/preprocessor/include/preprocessor/preprocessor_if.h b/source/preprocessor/include/preprocessor/preprocessor_if.h index 8e31e054c..d3068cbdd 100644 --- a/source/preprocessor/include/preprocessor/preprocessor_if.h +++ b/source/preprocessor/include/preprocessor/preprocessor_if.h @@ -21,12 +21,18 @@ extern "C" { /* -- Macros -- */ -#define PREPROCESSOR_IIF_IMPL_EXPAND_ARGS(...) __VA_ARGS__ -#define PREPROCESSOR_IIF_IMPL_EXPAND(expr) expr -#define PREPROCESSOR_IIF_IMPL_EXPAND_REMOVE_PARENTHESIS(expr) PREPROCESSOR_IIF_IMPL_EXPAND(PREPROCESSOR_IIF_IMPL_EXPAND_ARGS expr) -#define PREPROCESSOR_IIF_IMPL_0(true_expr, false_expr) PREPROCESSOR_IIF_IMPL_EXPAND_REMOVE_PARENTHESIS(false_expr) -#define PREPROCESSOR_IIF_IMPL_1(true_expr, false_expr) PREPROCESSOR_IIF_IMPL_EXPAND_REMOVE_PARENTHESIS(true_expr) +#if defined(__GNUC__) || defined(__clang__) + #define PREPROCESSOR_IIF_IMPL_EXPAND_ARGS(...) __VA_ARGS__ + #define PREPROCESSOR_IIF_IMPL_EXPAND(expr) expr + #define PREPROCESSOR_IIF_IMPL_EXPAND_REMOVE_PARENTHESIS(expr) PREPROCESSOR_IIF_IMPL_EXPAND(PREPROCESSOR_IIF_IMPL_EXPAND_ARGS expr) + + #define PREPROCESSOR_IIF_IMPL_0(true_expr, false_expr) PREPROCESSOR_IIF_IMPL_EXPAND_REMOVE_PARENTHESIS(false_expr) + #define PREPROCESSOR_IIF_IMPL_1(true_expr, false_expr) PREPROCESSOR_IIF_IMPL_EXPAND_REMOVE_PARENTHESIS(true_expr) +#else + #define PREPROCESSOR_IIF_IMPL_0(true_expr, false_expr) false_expr + #define PREPROCESSOR_IIF_IMPL_1(true_expr, false_expr) true_expr +#endif #if defined(_MSC_VER) && !defined(__clang__) #define PREPROCESSOR_IIF_IMPL_I(expr) expr @@ -44,7 +50,9 @@ extern "C" { #if defined(__EDG__) || defined(__EDG_VERSION__) #define PREPROCESSOR_IF_IMPL(condition, true_expr, false_expr) PREPROCESSOR_IIF(PREPROCESSOR_BOOL(condition), true_expr, false_expr) - #define PREPROCESSOR_IF(condition, true_expr, false_expr) PREPROCESSOR_IF_IMPL(condition, (true_expr), (false_expr)) + #define PREPROCESSOR_IF(condition, true_expr, false_expr) PREPROCESSOR_IF_IMPL(condition, true_expr, false_expr) +#elif defined(_MSC_VER) && !defined(__clang__) + #define PREPROCESSOR_IF(condition, true_expr, false_expr) PREPROCESSOR_IIF(PREPROCESSOR_BOOL(condition), true_expr, false_expr) #else #define PREPROCESSOR_IF(condition, true_expr, false_expr) PREPROCESSOR_IIF(PREPROCESSOR_BOOL(condition), (true_expr), (false_expr)) #endif From 0d0bd147c734a008d39508fcacb0049cb07c1095 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 5 Oct 2023 00:59:59 +0200 Subject: [PATCH 013/615] Disable sandbox test with thread sanitizer. --- source/preprocessor/include/preprocessor/preprocessor_if.h | 1 - source/tests/metacall_sandbox_plugin_test/CMakeLists.txt | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/source/preprocessor/include/preprocessor/preprocessor_if.h b/source/preprocessor/include/preprocessor/preprocessor_if.h index d3068cbdd..d904cf395 100644 --- a/source/preprocessor/include/preprocessor/preprocessor_if.h +++ b/source/preprocessor/include/preprocessor/preprocessor_if.h @@ -21,7 +21,6 @@ extern "C" { /* -- Macros -- */ - #if defined(__GNUC__) || defined(__clang__) #define PREPROCESSOR_IIF_IMPL_EXPAND_ARGS(...) __VA_ARGS__ #define PREPROCESSOR_IIF_IMPL_EXPAND(expr) expr diff --git a/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt b/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt index 354274b73..92b8f53fc 100644 --- a/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt +++ b/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt @@ -5,10 +5,16 @@ endif() include(Portability) +# Sandbox is only supported in Linux if(NOT PROJECT_OS_FAMILY STREQUAL unix) return() endif() +# Thread Sanitizer deadlocks with ASSERT_EXIT +if(OPTION_BUILD_THREAD_SANITIZER) + return() +endif() + # # Executable name and options # From fbbdd746e9e411825adbf26b22b841a5eeb58f7b Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 5 Oct 2023 01:34:02 +0200 Subject: [PATCH 014/615] Trying to solve issues with windows preprocessor. --- source/plugin/include/plugin/plugin_interface.h | 1 + .../include/preprocessor/preprocessor_if.h | 2 -- .../include/preprocessor/preprocessor_stringify.h | 10 +--------- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/source/plugin/include/plugin/plugin_interface.h b/source/plugin/include/plugin/plugin_interface.h index 0775d7265..8a7d21410 100644 --- a/source/plugin/include/plugin/plugin_interface.h +++ b/source/plugin/include/plugin/plugin_interface.h @@ -22,6 +22,7 @@ #define PLUGIN_INTERFACE_H 1 /* Private interface for using it inside any loader, extension or plugin for registering functions */ +/* TODO: Move this to source/metacall/include/metacall/private? */ #include diff --git a/source/preprocessor/include/preprocessor/preprocessor_if.h b/source/preprocessor/include/preprocessor/preprocessor_if.h index d904cf395..4426a13ca 100644 --- a/source/preprocessor/include/preprocessor/preprocessor_if.h +++ b/source/preprocessor/include/preprocessor/preprocessor_if.h @@ -50,8 +50,6 @@ extern "C" { #if defined(__EDG__) || defined(__EDG_VERSION__) #define PREPROCESSOR_IF_IMPL(condition, true_expr, false_expr) PREPROCESSOR_IIF(PREPROCESSOR_BOOL(condition), true_expr, false_expr) #define PREPROCESSOR_IF(condition, true_expr, false_expr) PREPROCESSOR_IF_IMPL(condition, true_expr, false_expr) -#elif defined(_MSC_VER) && !defined(__clang__) - #define PREPROCESSOR_IF(condition, true_expr, false_expr) PREPROCESSOR_IIF(PREPROCESSOR_BOOL(condition), true_expr, false_expr) #else #define PREPROCESSOR_IF(condition, true_expr, false_expr) PREPROCESSOR_IIF(PREPROCESSOR_BOOL(condition), (true_expr), (false_expr)) #endif diff --git a/source/preprocessor/include/preprocessor/preprocessor_stringify.h b/source/preprocessor/include/preprocessor/preprocessor_stringify.h index 6344ee217..0848f740f 100644 --- a/source/preprocessor/include/preprocessor/preprocessor_stringify.h +++ b/source/preprocessor/include/preprocessor/preprocessor_stringify.h @@ -21,15 +21,7 @@ extern "C" { /* -- Macros -- */ -#if defined(_MSC_VER) && !defined(__clang__) - #define PREPROCESSOR_STRINGIFY_IMPL_II(...) #__VA_ARGS__ - #define PREPROCESSOR_STRINGIFY_IMPL(...) \ - PREPROCESSOR_IF(PREPROCESSOR_ARGS_NOT_EMPTY(__VA_ARGS__), \ - PREPROCESSOR_STRINGIFY_IMPL_II(__VA_ARGS__), \ - "") -#else - #define PREPROCESSOR_STRINGIFY_IMPL(expr) #expr -#endif +#define PREPROCESSOR_STRINGIFY_IMPL(...) #__VA_ARGS__ #if defined(__MWERKS__) #define PREPROCESSOR_STRINGIFY_IMPL_I(tuple) PREPROCESSOR_STRINGIFY_IMPL##tuple From 73bdcd49093e78729fc5243b384dfc7aabebc3f3 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 5 Oct 2023 01:51:08 +0200 Subject: [PATCH 015/615] Solve issues with stringify on windows. --- .../include/dynlink/dynlink_interface.h.in | 2 +- .../preprocessor/preprocessor_stringify.h | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/source/dynlink/include/dynlink/dynlink_interface.h.in b/source/dynlink/include/dynlink/dynlink_interface.h.in index f3c23053b..83a4b7866 100644 --- a/source/dynlink/include/dynlink/dynlink_interface.h.in +++ b/source/dynlink/include/dynlink/dynlink_interface.h.in @@ -42,7 +42,7 @@ extern "C" { /* -- Macros -- */ #define DYNLINK_SYMBOL_PREFIX_STR() \ - PREPROCESSOR_STRINGIFY(DYNLINK_SYMBOL_PREFIX) + PREPROCESSOR_STRINGIFY_OR_EMPTY(DYNLINK_SYMBOL_PREFIX) #define DYNLINK_SYMBOL_NAME(name) \ PREPROCESSOR_CONCAT(DYNLINK_SYMBOL_PREFIX, name) diff --git a/source/preprocessor/include/preprocessor/preprocessor_stringify.h b/source/preprocessor/include/preprocessor/preprocessor_stringify.h index 0848f740f..9b749e2f7 100644 --- a/source/preprocessor/include/preprocessor/preprocessor_stringify.h +++ b/source/preprocessor/include/preprocessor/preprocessor_stringify.h @@ -21,6 +21,7 @@ extern "C" { /* -- Macros -- */ +/* Stringify a symbol */ #define PREPROCESSOR_STRINGIFY_IMPL(...) #__VA_ARGS__ #if defined(__MWERKS__) @@ -33,6 +34,28 @@ extern "C" { #define PREPROCESSOR_STRINGIFY(expr) PREPROCESSOR_STRINGIFY_IMPL(expr) #endif +/* Stringify a symbol or return empty string if the expression expands to nothing */ +#if defined(_MSC_VER) && !defined(__clang__) + #define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL_II(...) #__VA_ARGS__ + #define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL(...) \ + PREPROCESSOR_IF(PREPROCESSOR_ARGS_NOT_EMPTY(__VA_ARGS__), \ + PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL_II(__VA_ARGS__), \ + "") +#else + #define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL(expr) #expr +#endif + +#if defined(__MWERKS__) + #define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL_I(tuple) PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL##tuple + #define PREPROCESSOR_STRINGIFY_OR_EMPTY(expr) PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL_I((expr)) +#elif defined(_MSC_VER) && !defined(__clang__) + #define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL_I(tuple) PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL tuple + #define PREPROCESSOR_STRINGIFY_OR_EMPTY(expr) PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL_I((expr)) +#else + #define PREPROCESSOR_STRINGIFY_OR_EMPTY(expr) PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL(expr) +#endif + +/* Stringify a list of symbols */ #define PREPROCESSOR_STRINGIFY_VARIADIC(...) \ PREPROCESSOR_FOR_EACH(PREPROCESSOR_STRINGIFY, __VA_ARGS__) From 38c164c23c706bd497f89a6f27ad75d9b90d01a3 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 5 Oct 2023 09:27:54 +0300 Subject: [PATCH 016/615] Revert "Change timeout of tests from 5400 to 7200." This reverts commit 3bf25cbb6aa95bc8e5f4ee549db654cb3459e010. --- source/tests/CMakeLists.txt | 2 +- tools/metacall-build.ps1 | 2 +- tools/metacall-build.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index 8f50f50c5..38a23906a 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -80,7 +80,7 @@ if(OPTION_TEST_MEMORYCHECK AND NOT (OPTION_BUILD_ADDRESS_SANITIZER OR OPTION_BUI --label-exclude MEMCHECK_IGNORE --force-new-ctest-process --test-action memcheck - --timeout 7200 + --timeout 5400 COMMAND ${CMAKE_COMMAND} -E cat "${CMAKE_BINARY_DIR}/Testing/Temporary/MemoryChecker.*.log" ) endif() diff --git a/tools/metacall-build.ps1 b/tools/metacall-build.ps1 index 482d65cd9..4c758006a 100755 --- a/tools/metacall-build.ps1 +++ b/tools/metacall-build.ps1 @@ -78,7 +78,7 @@ function Sub-Build { # Tests (coverage needs to run the tests) if (($BUILD_TESTS -eq 1) -or ($BUILD_BENCHMARKS -eq 1) -or ($BUILD_COVERAGE -eq 1)) { echo "Running the tests..." - ctest "-j$((Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors)" --timeout 7200 --output-on-failure -C $BUILD_TYPE + ctest "-j$((Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors)" --timeout 5400 --output-on-failure -C $BUILD_TYPE if (-not $?) { $RecentExitCode = $LASTEXITCODE diff --git a/tools/metacall-build.sh b/tools/metacall-build.sh index 6535fb21b..d0a97492e 100755 --- a/tools/metacall-build.sh +++ b/tools/metacall-build.sh @@ -75,7 +75,7 @@ sub_build() { # Tests (coverage needs to run the tests) if [ $BUILD_TESTS = 1 ] || [ $BUILD_BENCHMARKS=1 ] || [ $BUILD_COVERAGE = 1 ]; then - ctest -j$(getconf _NPROCESSORS_ONLN) --timeout 7200 --output-on-failure --test-output-size-failed 3221000000 -C $BUILD_TYPE + ctest -j$(getconf _NPROCESSORS_ONLN) --timeout 5400 --output-on-failure --test-output-size-failed 3221000000 -C $BUILD_TYPE fi # Coverage From e002bc166e782b3a5b0853a6d33d36b2a14ebcc1 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 5 Oct 2023 09:31:40 +0300 Subject: [PATCH 017/615] Minor improvement in PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL. --- .../preprocessor/include/preprocessor/preprocessor_stringify.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/preprocessor/include/preprocessor/preprocessor_stringify.h b/source/preprocessor/include/preprocessor/preprocessor_stringify.h index 9b749e2f7..10f680ce7 100644 --- a/source/preprocessor/include/preprocessor/preprocessor_stringify.h +++ b/source/preprocessor/include/preprocessor/preprocessor_stringify.h @@ -42,7 +42,7 @@ extern "C" { PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL_II(__VA_ARGS__), \ "") #else - #define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL(expr) #expr + #define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL(...) #__VA_ARGS__ #endif #if defined(__MWERKS__) From 88a83e3e8329090f1151ab1e7a28ea74bceb4fb5 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 5 Oct 2023 16:55:14 +0200 Subject: [PATCH 018/615] Solve issues with MSVC, improve macros for sandbox_plugin. --- .../plugins/cli_core_plugin/CMakeLists.txt | 6 +- .../plugin/include/plugin/plugin_interface.h | 59 ---------- .../include/plugin/plugin_interface.hpp | 104 ++++++++++++++++++ .../plugins/backtrace_plugin/CMakeLists.txt | 6 +- source/plugins/sandbox_plugin/CMakeLists.txt | 6 +- .../sandbox_plugin/source/sandbox_plugin.cpp | 86 ++++----------- .../include/preprocessor/preprocessor_if.h | 2 +- .../preprocessor/preprocessor_stringify.h | 6 +- .../CMakeLists.txt | 2 +- 9 files changed, 140 insertions(+), 137 deletions(-) delete mode 100644 source/plugin/include/plugin/plugin_interface.h create mode 100644 source/plugin/include/plugin/plugin_interface.hpp diff --git a/source/cli/plugins/cli_core_plugin/CMakeLists.txt b/source/cli/plugins/cli_core_plugin/CMakeLists.txt index 3287aaec9..486e308b8 100644 --- a/source/cli/plugins/cli_core_plugin/CMakeLists.txt +++ b/source/cli/plugins/cli_core_plugin/CMakeLists.txt @@ -187,18 +187,18 @@ target_link_libraries(${target} # # Copy metacall.json -add_custom_target(${target}-create-plugin-dir ALL +add_custom_target(${target}_config ALL WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory ${PLUGIN_OUTPUT_DIRECTORY} COMMAND ${CMAKE_COMMAND} -E copy ${source_path}/metacall.json ${PLUGIN_OUTPUT_DIRECTORY}/metacall.json ) -set_target_properties(${target}-create-plugin-dir +set_target_properties(${target}_config PROPERTIES FOLDER "${IDE_FOLDER}" ) add_dependencies(${target} - ${target}-create-plugin-dir + ${target}_config plugin_extension ) diff --git a/source/plugin/include/plugin/plugin_interface.h b/source/plugin/include/plugin/plugin_interface.h deleted file mode 100644 index 8a7d21410..000000000 --- a/source/plugin/include/plugin/plugin_interface.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Plugin Library by Parra Studios - * A library for plugins at run-time into a process. - * - * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef PLUGIN_INTERFACE_H -#define PLUGIN_INTERFACE_H 1 - -/* Private interface for using it inside any loader, extension or plugin for registering functions */ -/* TODO: Move this to source/metacall/include/metacall/private? */ - -#include - -#include - -#include - -#define EXTENSION_FUNCTION_IMPL_VOID(ret, name) \ - do \ - { \ - if (metacall_register_loaderv(loader, context, PREPROCESSOR_STRINGIFY(name), name, ret, 0, NULL) != 0) \ - { \ - log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \ - return 1; \ - } \ - } while (0) - -#define EXTENSION_FUNCTION_IMPL(ret, name, ...) \ - do \ - { \ - enum metacall_value_id arg_types[] = { __VA_ARGS__ }; \ - if (metacall_register_loaderv(loader, context, PREPROCESSOR_STRINGIFY(name), name, ret, PREPROCESSOR_ARGS_COUNT(__VA_ARGS__), arg_types) != 0) \ - { \ - log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \ - return 1; \ - } \ - } while (0) - -#define EXTENSION_FUNCTION(ret, name, ...) \ - PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ - EXTENSION_FUNCTION_IMPL_VOID(ret, name), \ - EXTENSION_FUNCTION_IMPL(ret, name, __VA_ARGS__)) - -#endif /* PLUGIN_INTERFACE_H */ diff --git a/source/plugin/include/plugin/plugin_interface.hpp b/source/plugin/include/plugin/plugin_interface.hpp new file mode 100644 index 000000000..67fee1961 --- /dev/null +++ b/source/plugin/include/plugin/plugin_interface.hpp @@ -0,0 +1,104 @@ +/* + * Plugin Library by Parra Studios + * A library for plugins at run-time into a process. + * + * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef PLUGIN_INTERFACE_HPP +#define PLUGIN_INTERFACE_HPP 1 + +/* Private interface for using it inside any loader, extension or plugin for registering functions */ +/* TODO: Move this to source/metacall/include/metacall/private? */ + +#include + +#include + +#include + +#include + +#include +#include + +#define EXTENSION_FUNCTION_IMPL_VOID(ret, name) \ + do \ + { \ + if (metacall_register_loaderv(loader, context, PREPROCESSOR_STRINGIFY(name), name, ret, 0, NULL) != 0) \ + { \ + log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \ + return 1; \ + } \ + } while (0) + +#define EXTENSION_FUNCTION_IMPL(ret, name, ...) \ + do \ + { \ + enum metacall_value_id arg_types[] = { __VA_ARGS__ }; \ + if (metacall_register_loaderv(loader, context, PREPROCESSOR_STRINGIFY(name), name, ret, PREPROCESSOR_ARGS_COUNT(__VA_ARGS__), arg_types) != 0) \ + { \ + log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \ + return 1; \ + } \ + } while (0) + +#define EXTENSION_FUNCTION(ret, name, ...) \ + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + EXTENSION_FUNCTION_IMPL_VOID(ret, name), \ + EXTENSION_FUNCTION_IMPL(ret, name, __VA_ARGS__)) + +#define EXTENSION_FUNCTION_THROW(error) \ + do \ + { \ + log_write("metacall", LOG_LEVEL_ERROR, error); \ + exception ex = exception_create_const(error, "PluginException", 0, ""); \ + throwable th = throwable_create(value_create_exception(ex)); \ + return value_create_throwable(th); \ + } while (0) + +#define EXTENSION_FUNCTION_CHECK_ITERATOR(value, iterator, error) \ + if (metacall_value_id(args[iterator]) != value) \ + { \ + std::stringstream ss; \ + ss << error ". The parameter number " PREPROCESSOR_STRINGIFY(PREPROCESSOR_ARGS_COUNT(iterator)) " requires a value of type " metacall_value_id_name(value) ", received: " << metacall_value_type_name(args[iterator]); \ + std::string error_msg = ss.str(); \ + EXTENSION_FUNCTION_THROW(error_msg.c_str()); \ + } + +/* TODO: */ +#define PREPROCESSOR_FOR(macro, context, ...) + +#define EXTENSION_FUNCTION_CHECK(error, ...) \ + do \ + { \ + (void)data; /* TODO: Do something with data */ \ + /* Disable warning on args when no args */ \ + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + (void)args; \ + , \ + PREPROCESSOR_EMPTY_SYMBOL()) \ + if (argc != PREPROCESSOR_ARGS_COUNT(__VA_ARGS__)) \ + { \ + std::stringstream ss; \ + ss << error ". The required number of argumens is " PREPROCESSOR_STRINGIFY(PREPROCESSOR_ARGS_COUNT(__VA_ARGS__)) ", received: " << argc; \ + std::string error_msg = ss.str(); \ + EXTENSION_FUNCTION_THROW(error_msg.c_str()); \ + } \ + PREPROCESSOR_FOR(EXTENSION_FUNCTION_CHECK_ITERATOR, error, __VA_ARGS__) \ + } while (0) + +#endif /* PLUGIN_INTERFACE_HPP */ diff --git a/source/plugins/backtrace_plugin/CMakeLists.txt b/source/plugins/backtrace_plugin/CMakeLists.txt index 866d1800a..0789db78b 100644 --- a/source/plugins/backtrace_plugin/CMakeLists.txt +++ b/source/plugins/backtrace_plugin/CMakeLists.txt @@ -222,18 +222,18 @@ target_link_libraries(${target} # # Copy metacall.json -add_custom_target(${target}-create-plugin-dir ALL +add_custom_target(${target}_config ALL WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory ${PLUGIN_OUTPUT_DIRECTORY} COMMAND ${CMAKE_COMMAND} -E copy ${source_path}/metacall.json ${PLUGIN_OUTPUT_DIRECTORY}/metacall.json ) -set_target_properties(${target}-create-plugin-dir +set_target_properties(${target}_config PROPERTIES FOLDER "${IDE_FOLDER}" ) add_dependencies(${target} - ${target}-create-plugin-dir + ${target}_config plugin_extension ) diff --git a/source/plugins/sandbox_plugin/CMakeLists.txt b/source/plugins/sandbox_plugin/CMakeLists.txt index b2dba7a15..8d271bf3f 100644 --- a/source/plugins/sandbox_plugin/CMakeLists.txt +++ b/source/plugins/sandbox_plugin/CMakeLists.txt @@ -210,18 +210,18 @@ target_link_libraries(${target} # # Copy metacall.json -add_custom_target(${target}-create-plugin-dir ALL +add_custom_target(${target}_config ALL WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory ${PLUGIN_OUTPUT_DIRECTORY} COMMAND ${CMAKE_COMMAND} -E copy ${source_path}/metacall.json ${PLUGIN_OUTPUT_DIRECTORY}/metacall.json ) -set_target_properties(${target}-create-plugin-dir +set_target_properties(${target}_config PROPERTIES FOLDER "${IDE_FOLDER}" ) add_dependencies(${target} - ${target}-create-plugin-dir + ${target}_config plugin_extension ) diff --git a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp index df6288b46..72715c094 100644 --- a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp +++ b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp @@ -20,113 +20,71 @@ #include -#include +#include #include -/* TODO: Use SCMP_ACT_KILL_PROCESS for catching the signal and showing the stack trace? */ -#define SANDBOX_DEFAULT_ACTION SCMP_ACT_ALLOW // SCMP_ACT_KILL +/* TODO: Use SCMP_ACT_KILL_PROCESS instead of SCMP_ACT_KILL for catching the signal and showing the stack trace? */ +/* TODO: We can disable bool (true/false) for string ("allow"/"disable") */ +#define SANDBOX_ACTION(value) \ + metacall_value_to_bool(value) == 0L ? SCMP_ACT_KILL : SCMP_ACT_ALLOW + +/* Error messages */ +#define SANDBOX_INITIALIZE_ERROR "Sandbox plugin failed to initialize a context" +#define SANDBOX_UNAME_ERROR "Sandbox plugin failed to set uname syscall permissions" +#define SANDBOX_DESTROY_ERROR "Sandbox plugin failed to destroy a context" void *sandbox_initialize(size_t argc, void *args[], void *data) { scmp_filter_ctx ctx; - (void)argc; - (void)args; - (void)data; + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(SANDBOX_INITIALIZE_ERROR, METACALL_BOOL); - /* Initialize the scmp context */ - ctx = seccomp_init(SANDBOX_DEFAULT_ACTION); + /* Initialize the seccomp context */ + ctx = seccomp_init(SANDBOX_ACTION(args[0])); if (ctx == NULL) { - log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to initialize a context."); + /* Throw exception if seccomp initialization failed */ + EXTENSION_FUNCTION_THROW(SANDBOX_INITIALIZE_ERROR); } return metacall_value_create_ptr(ctx); } -/*int sandbox_uname(void *ctx, int allow) -{ - seccomp_rule_add(ctx, allow == 0L ? SCMP_ACT_KILL : SCMP_ACT_ALLOW, SCMP_SYS(uname), 0); - seccomp_load(ctx); - return 0; -}*/ - void *sandbox_uname(size_t argc, void *args[], void *data) { scmp_filter_ctx ctx; - (void)data; - - if (argc != 2) - { - log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to set uname syscall permissions. The required number of argumens is one, received: %" PRIuS, argc); - goto error_args; - } - - if (metacall_value_id(args[0]) != METACALL_PTR) - { - log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to set uname syscall permissions. " - "The first parameter requires a pointer to the context, received: %s", - metacall_value_type_name(args[0])); - goto error_args; - } - - if (metacall_value_id(args[1]) != METACALL_BOOL) - { - log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to set uname syscall permissions. " - "The second parameter requires a boolean indicating if it is allowed or not, received: %s", - metacall_value_type_name(args[1])); - goto error_args; - } + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(SANDBOX_UNAME_ERROR, METACALL_PTR, METACALL_BOOL); ctx = metacall_value_to_ptr(args[0]); - seccomp_rule_add(ctx, metacall_value_to_bool(args[1]) == 0L ? SCMP_ACT_KILL : SCMP_ACT_ALLOW, SCMP_SYS(uname), 0); + seccomp_rule_add(ctx, SANDBOX_ACTION(args[1]), SCMP_SYS(uname), 0); seccomp_load(ctx); return metacall_value_create_int(0); - -error_args: - return metacall_value_create_int(1); } void *sandbox_destroy(size_t argc, void *args[], void *data) { scmp_filter_ctx ctx; - (void)data; - - if (argc != 1) - { - log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to destroy a context. The required number of argumens is one, received: %" PRIuS, argc); - goto error_args; - } - - if (metacall_value_id(args[0]) != METACALL_PTR) - { - log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to destroy a context. " - "The first parameter requires a pointer to the context, received: %s", - metacall_value_type_name(args[0])); - goto error_args; - } + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(SANDBOX_DESTROY_ERROR, METACALL_PTR); ctx = metacall_value_to_ptr(args[0]); if (ctx == NULL) { - log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to destroy a context. " - "The first parameter requires a non null pointer"); - goto error_args; + EXTENSION_FUNCTION_THROW(SANDBOX_DESTROY_ERROR ", the first parameter requires a non null pointer"); } seccomp_release(ctx); return metacall_value_create_int(0); - -error_args: - return metacall_value_create_int(1); } #if 0 /* TODO: Fork safety */ diff --git a/source/preprocessor/include/preprocessor/preprocessor_if.h b/source/preprocessor/include/preprocessor/preprocessor_if.h index 4426a13ca..797ff0fb8 100644 --- a/source/preprocessor/include/preprocessor/preprocessor_if.h +++ b/source/preprocessor/include/preprocessor/preprocessor_if.h @@ -21,7 +21,7 @@ extern "C" { /* -- Macros -- */ -#if defined(__GNUC__) || defined(__clang__) +#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) #define PREPROCESSOR_IIF_IMPL_EXPAND_ARGS(...) __VA_ARGS__ #define PREPROCESSOR_IIF_IMPL_EXPAND(expr) expr #define PREPROCESSOR_IIF_IMPL_EXPAND_REMOVE_PARENTHESIS(expr) PREPROCESSOR_IIF_IMPL_EXPAND(PREPROCESSOR_IIF_IMPL_EXPAND_ARGS expr) diff --git a/source/preprocessor/include/preprocessor/preprocessor_stringify.h b/source/preprocessor/include/preprocessor/preprocessor_stringify.h index 10f680ce7..31b69da16 100644 --- a/source/preprocessor/include/preprocessor/preprocessor_stringify.h +++ b/source/preprocessor/include/preprocessor/preprocessor_stringify.h @@ -37,9 +37,9 @@ extern "C" { /* Stringify a symbol or return empty string if the expression expands to nothing */ #if defined(_MSC_VER) && !defined(__clang__) #define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL_II(...) #__VA_ARGS__ - #define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL(...) \ - PREPROCESSOR_IF(PREPROCESSOR_ARGS_NOT_EMPTY(__VA_ARGS__), \ - PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL_II(__VA_ARGS__), \ + #define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL(...) \ + PREPROCESSOR_IF(PREPROCESSOR_ARGS_NOT_EMPTY(__VA_ARGS__), \ + PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL_II(__VA_ARGS__), \ "") #else #define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL(...) #__VA_ARGS__ diff --git a/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt b/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt index 92b8f53fc..36ad6e331 100644 --- a/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt +++ b/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt @@ -10,7 +10,7 @@ if(NOT PROJECT_OS_FAMILY STREQUAL unix) return() endif() -# Thread Sanitizer deadlocks with ASSERT_EXIT +# Thread Sanitizer deadlocks with ASSERT_EXIT (TODO: Review this when fork safety is implemented in sandbox_plugin) if(OPTION_BUILD_THREAD_SANITIZER) return() endif() From 5d4f0faaaf5ce8b78f26f1cb9a1c0753ba303953 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 5 Oct 2023 16:55:29 +0200 Subject: [PATCH 019/615] Change macro newline alignement. --- .clang-format | 2 +- source/adt/include/adt/adt_string.h | 11 +- source/adt/include/adt/adt_vector.h | 40 +++---- .../source/cli_core_plugin.cpp | 2 +- .../dynlink/include/dynlink/dynlink_flags.h | 12 +- .../dynlink/dynlink_impl_symbol_beos.h | 4 +- .../dynlink/dynlink_impl_symbol_macos.h | 4 +- .../dynlink/dynlink_impl_symbol_unix.h | 4 +- .../dynlink/dynlink_impl_symbol_win32.h | 6 +- .../environment/environment_variable_path.h | 8 +- .../source/environment_variable_path.c | 8 +- source/format/include/format/format_print.h | 6 +- .../format/include/format/format_specifier.h | 48 ++++---- source/loader/source/loader_impl.c | 2 +- .../file_loader/source/file_loader_impl.c | 12 +- .../node_loader/source/node_loader_impl.cpp | 6 +- .../node_loader/source/node_loader_port.cpp | 31 +++--- .../source/node_loader_trampoline.cpp | 4 +- .../loaders/rb_loader/source/rb_loader_impl.c | 36 +++--- source/log/include/log/log_preprocessor.h | 8 +- source/log/source/log_policy_format_text.c | 6 +- source/log/source/log_policy_stream_syslog.c | 10 +- .../metacall/include/metacall/metacall_fork.h | 6 +- source/metacall/source/metacall_fork.c | 12 +- .../portability/portability_executable_path.h | 4 +- .../include/portability/portability_path.h | 14 +-- .../source/portability_executable_path.c | 2 +- .../source/portability_library_path.c | 4 +- source/portability/source/portability_path.c | 6 +- .../reflect/reflect_class_visibility.h | 4 +- .../include/reflect/reflect_memory_tracker.h | 80 +++++++------- .../reflect/source/reflect_class_visibility.c | 4 +- .../source/metacall_fork_test.cpp | 2 +- .../source/node_extension_test.c | 4 +- .../source/metacall_sandbox_plugin_test.cpp | 4 +- .../metacall_test/source/metacall_test.cpp | 12 +- .../threading/threading_atomic_win32.h | 104 +++++++++--------- .../include/threading/threading_mutex.h | 8 +- 38 files changed, 265 insertions(+), 275 deletions(-) diff --git a/.clang-format b/.clang-format index a3ebb75c1..bffce04a3 100644 --- a/.clang-format +++ b/.clang-format @@ -5,7 +5,7 @@ AlignAfterOpenBracket: DontAlign AlignConsecutiveBitFields: true # AlignConsecutiveDeclarations: false AlignConsecutiveMacros: true -# AlignEscapedNewlines: Right +AlignEscapedNewlines: DontAlign # AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: false diff --git a/source/adt/include/adt/adt_string.h b/source/adt/include/adt/adt_string.h index 903acbbd1..ebb634422 100644 --- a/source/adt/include/adt/adt_string.h +++ b/source/adt/include/adt/adt_string.h @@ -35,13 +35,12 @@ extern "C" { /* -- Macros -- */ /* This is a temporary solution for safe strings, it can be improved in the future */ -#define string_copy(dest, src, dest_size) \ - do \ - { \ +#define string_copy(dest, src, dest_size) \ + do \ + { \ size_t __string_copy_length = strnlen(src, dest_size - 1); \ - memcpy(dest, src, __string_copy_length); \ - dest[__string_copy_length] = '\0'; \ - \ + memcpy(dest, src, __string_copy_length); \ + dest[__string_copy_length] = '\0'; \ } while (0) #ifdef __cplusplus diff --git a/source/adt/include/adt/adt_vector.h b/source/adt/include/adt/adt_vector.h index d839b2b8d..3399b1f60 100644 --- a/source/adt/include/adt/adt_vector.h +++ b/source/adt/include/adt/adt_vector.h @@ -205,13 +205,11 @@ typedef struct vector_type *vector; * @param[in] type_name * Type of element to be modified */ -#define vector_set_const(v, position, constant, type_name) \ - do \ - { \ - type_name macro_vector_type_const_to_var = constant; \ - \ +#define vector_set_const(v, position, constant, type_name) \ + do \ + { \ + type_name macro_vector_type_const_to_var = constant; \ vector_set(v, position, ¯o_vector_type_const_to_var); \ - \ } while (0) /** @@ -228,13 +226,11 @@ typedef struct vector_type *vector; * @param[in] type_name * Type of element to be inserted */ -#define vector_push_back_const(v, constant, type_name) \ - do \ - { \ - type_name macro_vector_type_const_to_var = constant; \ - \ +#define vector_push_back_const(v, constant, type_name) \ + do \ + { \ + type_name macro_vector_type_const_to_var = constant; \ vector_push_back(v, ¯o_vector_type_const_to_var); \ - \ } while (0) /** @@ -251,13 +247,11 @@ typedef struct vector_type *vector; * @param[in] type_name * Type of element to be inserted */ -#define vector_push_front_const(v, constant, type_name) \ - do \ - { \ - type_name macro_vector_type_const_to_var = constant; \ - \ +#define vector_push_front_const(v, constant, type_name) \ + do \ + { \ + type_name macro_vector_type_const_to_var = constant; \ vector_push_front(v, ¯o_vector_type_const_to_var); \ - \ } while (0) /** @@ -279,13 +273,11 @@ typedef struct vector_type *vector; * @param[in] type_name * Type of element to be inserted */ -#define vector_insert_const(v, position, constant, type_name) \ - do \ - { \ - type_name macro_vector_type_const_to_var = constant; \ - \ +#define vector_insert_const(v, position, constant, type_name) \ + do \ + { \ + type_name macro_vector_type_const_to_var = constant; \ vector_insert(v, position, ¯o_vector_type_const_to_var); \ - \ } while (0) /* -- Methods -- */ diff --git a/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp b/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp index a308fce68..ecc7d5757 100644 --- a/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp +++ b/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp @@ -20,7 +20,7 @@ #include -#include +#include #include diff --git a/source/dynlink/include/dynlink/dynlink_flags.h b/source/dynlink/include/dynlink/dynlink_flags.h index 77060053a..3c94c4026 100644 --- a/source/dynlink/include/dynlink/dynlink_flags.h +++ b/source/dynlink/include/dynlink/dynlink_flags.h @@ -58,9 +58,9 @@ extern "C" { * */ #define DYNLINK_FLAGS_SET(flags, flag) \ - do \ - { \ - flags = (flag); \ + do \ + { \ + flags = (flag); \ } while (0) /** @@ -83,9 +83,9 @@ extern "C" { * */ #define DYNLINK_FLAGS_ADD(flags, flag) \ - do \ - { \ - flags |= (flag); \ + do \ + { \ + flags |= (flag); \ } while (0) /** diff --git a/source/dynlink/include/dynlink/dynlink_impl_symbol_beos.h b/source/dynlink/include/dynlink/dynlink_impl_symbol_beos.h index 1c50340e9..33fcbac2b 100644 --- a/source/dynlink/include/dynlink/dynlink_impl_symbol_beos.h +++ b/source/dynlink/include/dynlink/dynlink_impl_symbol_beos.h @@ -36,9 +36,9 @@ extern "C" { /* -- Macros -- */ -#define DYNLINK_SYMBOL_EXPORT(name) \ +#define DYNLINK_SYMBOL_EXPORT(name) \ DYNLINK_API struct dynlink_symbol_addr_beos_type DYNLINK_SYMBOL_NAME(name) = { \ - (dynlink_symbol_addr_beos_impl)&name \ + (dynlink_symbol_addr_beos_impl)&name \ } #define DYNLINK_SYMBOL_GET(name) \ diff --git a/source/dynlink/include/dynlink/dynlink_impl_symbol_macos.h b/source/dynlink/include/dynlink/dynlink_impl_symbol_macos.h index a1198b08b..e06fa5f93 100644 --- a/source/dynlink/include/dynlink/dynlink_impl_symbol_macos.h +++ b/source/dynlink/include/dynlink/dynlink_impl_symbol_macos.h @@ -36,9 +36,9 @@ extern "C" { /* -- Macros -- */ -#define DYNLINK_SYMBOL_EXPORT(name) \ +#define DYNLINK_SYMBOL_EXPORT(name) \ DYNLINK_API struct dynlink_symbol_addr_macos_type DYNLINK_SYMBOL_NAME(name) = { \ - (dynlink_symbol_addr_macos_impl)&name \ + (dynlink_symbol_addr_macos_impl)&name \ } #define DYNLINK_SYMBOL_GET(name) \ diff --git a/source/dynlink/include/dynlink/dynlink_impl_symbol_unix.h b/source/dynlink/include/dynlink/dynlink_impl_symbol_unix.h index 9d4f38d40..7d4119eee 100644 --- a/source/dynlink/include/dynlink/dynlink_impl_symbol_unix.h +++ b/source/dynlink/include/dynlink/dynlink_impl_symbol_unix.h @@ -36,9 +36,9 @@ extern "C" { /* -- Macros -- */ -#define DYNLINK_SYMBOL_EXPORT(name) \ +#define DYNLINK_SYMBOL_EXPORT(name) \ DYNLINK_API struct dynlink_symbol_addr_unix_type DYNLINK_SYMBOL_NAME(name) = { \ - (dynlink_symbol_addr_unix_impl)&name \ + (dynlink_symbol_addr_unix_impl)&name \ } #define DYNLINK_SYMBOL_GET(name) \ diff --git a/source/dynlink/include/dynlink/dynlink_impl_symbol_win32.h b/source/dynlink/include/dynlink/dynlink_impl_symbol_win32.h index 769ada398..b1314824c 100644 --- a/source/dynlink/include/dynlink/dynlink_impl_symbol_win32.h +++ b/source/dynlink/include/dynlink/dynlink_impl_symbol_win32.h @@ -38,9 +38,9 @@ extern "C" { /* -- Macros -- */ #define DYNLINK_SYMBOL_EXPORT(name) \ - DYNLINK_NO_EXPORT struct \ - { \ - char name; \ + DYNLINK_NO_EXPORT struct \ + { \ + char name; \ } PREPROCESSOR_CONCAT(dynlink_no_export_, name) #define DYNLINK_SYMBOL_GET(name) name diff --git a/source/environment/include/environment/environment_variable_path.h b/source/environment/include/environment/environment_variable_path.h index 42e19ca58..402a2eeb0 100644 --- a/source/environment/include/environment/environment_variable_path.h +++ b/source/environment/include/environment/environment_variable_path.h @@ -35,15 +35,15 @@ extern "C" { /* -- Definitions -- */ -#if defined(WIN32) || defined(_WIN32) || \ +#if defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) #define ENVIRONMENT_VARIABLE_PATH_SEPARATOR_C '\\' #define ENVIRONMENT_VARIABLE_PATH_SEPARATOR_STR "\\" -#elif defined(unix) || defined(__unix__) || defined(__unix) || \ +#elif defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__CYGWIN__) || defined(__CYGWIN32__) || \ - (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) || \ + defined(__CYGWIN__) || defined(__CYGWIN32__) || \ + (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) || \ defined(__HAIKU__) || defined(__BEOS__) #define ENVIRONMENT_VARIABLE_PATH_SEPARATOR_C '/' #define ENVIRONMENT_VARIABLE_PATH_SEPARATOR_STR "/" diff --git a/source/environment/source/environment_variable_path.c b/source/environment/source/environment_variable_path.c index 1a7891dee..351db6994 100644 --- a/source/environment/source/environment_variable_path.c +++ b/source/environment/source/environment_variable_path.c @@ -27,14 +27,14 @@ /* -- Definitions -- */ -#if defined(WIN32) || defined(_WIN32) || \ +#if defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) #define ENVIRONMENT_VARIABLE_PATH_SEPARATOR(chr) (chr == '/' || chr == '\\') -#elif defined(unix) || defined(__unix__) || defined(__unix) || \ +#elif defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__CYGWIN__) || defined(__CYGWIN32__) || \ - (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) || \ + defined(__CYGWIN__) || defined(__CYGWIN32__) || \ + (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) || \ defined(__HAIKU__) || defined(__BEOS__) #define ENVIRONMENT_VARIABLE_PATH_SEPARATOR(chr) (chr == '/') #else diff --git a/source/format/include/format/format_print.h b/source/format/include/format/format_print.h index 31a4c777c..5bc3ec7e1 100644 --- a/source/format/include/format/format_print.h +++ b/source/format/include/format/format_print.h @@ -45,10 +45,10 @@ extern "C" { #ifndef vsnprintf #define vsnprintf _vsnprintf #endif -#elif (defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1900)) || \ - defined(_BSD_SOURCE) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500) || \ +#elif (defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1900)) || \ + defined(_BSD_SOURCE) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500) || \ defined(_ISOC99_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \ - defined(__HAIKU__) || defined(__BEOS__) || \ + defined(__HAIKU__) || defined(__BEOS__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) /* Supported */ diff --git a/source/format/include/format/format_specifier.h b/source/format/include/format/format_specifier.h index 8a83081c9..2d51d9c3c 100644 --- a/source/format/include/format/format_specifier.h +++ b/source/format/include/format/format_specifier.h @@ -34,10 +34,10 @@ extern "C" { #include #include -#if !defined(_WIN32) && \ - (defined(unix) || defined(__unix__) || defined(__unix) || \ +#if !defined(_WIN32) && \ + (defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__CYGWIN__) || defined(__CYGWIN32__) || \ + defined(__CYGWIN__) || defined(__CYGWIN32__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__)) #include @@ -59,31 +59,31 @@ extern "C" { /* -- Definitions -- */ -#if defined(__LP64__) || defined(_LP64) || \ - defined(_WIN64) || \ +#if defined(__LP64__) || defined(_LP64) || \ + defined(_WIN64) || \ defined(alpha) || defined(__ALPHA) || defined(__alpha) || defined(__alpha__) || defined(_M_ALPHA) || \ - defined(_IA64) || defined(__IA64__) || defined(__ia64__) || defined(__ia64) || defined(_M_IA64) || \ - defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || defined(__amd64) || \ - defined(__mips64) || \ - defined(__powerpc64__) || defined(__ppc64__) || defined(_ARCH_PPC64) || \ - defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \ + defined(_IA64) || defined(__IA64__) || defined(__ia64__) || defined(__ia64) || defined(_M_IA64) || \ + defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || defined(__amd64) || \ + defined(__mips64) || \ + defined(__powerpc64__) || defined(__ppc64__) || defined(_ARCH_PPC64) || \ + defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \ defined(__s390__) || defined(__s390x__) #define FORMAT_64BIT 1 /* 64-bit */ -#elif defined(_ILP32) || defined(__ILP32__) || \ - defined(_WIN32) || \ - defined(__386__) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__X86) || defined(_M_IX86) || \ - defined(__mips__) || defined(__mips) || defined(__MIPS__) || defined(_M_MRX000) || \ - defined(__hppa) || defined(__hppa__) || \ - ((defined(__PPC) || defined(__POWERPC__) || defined(__powerpc) || defined(__powerpc64__) || defined(__PPC__) || \ - defined(__powerpc__) || defined(__ppc__) || defined(__ppc) || defined(_ARCH_PPC) || defined(_M_PPC)) && \ - !defined(__powerpc64__)) || \ - (defined(_ARCH_COM) && defined(_ARCH_PPC)) || \ +#elif defined(_ILP32) || defined(__ILP32__) || \ + defined(_WIN32) || \ + defined(__386__) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__X86) || defined(_M_IX86) || \ + defined(__mips__) || defined(__mips) || defined(__MIPS__) || defined(_M_MRX000) || \ + defined(__hppa) || defined(__hppa__) || \ + ((defined(__PPC) || defined(__POWERPC__) || defined(__powerpc) || defined(__powerpc64__) || defined(__PPC__) || \ + defined(__powerpc__) || defined(__ppc__) || defined(__ppc) || defined(_ARCH_PPC) || defined(_M_PPC)) && \ + !defined(__powerpc64__)) || \ + (defined(_ARCH_COM) && defined(_ARCH_PPC)) || \ ((defined(__sparc__) || defined(__sparc) || defined(sparc)) && !(defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__))) || \ - defined(__arm__) || defined(__arm) || defined(ARM) || defined(_ARM) || defined(_ARM_) || defined(__ARM__) || defined(_M_ARM) || \ - defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ - defined(__sh__) || defined(__sh) || defined(SHx) || defined(_SHX_) || \ + defined(__arm__) || defined(__arm) || defined(ARM) || defined(_ARM) || defined(_ARM_) || defined(__ARM__) || defined(_M_ARM) || \ + defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ + defined(__sh__) || defined(__sh) || defined(SHx) || defined(_SHX_) || \ defined(nios2) || defined(__nios2) || defined(__nios2__) #define FORMAT_32BIT 1 /* 32-bit */ @@ -94,8 +94,8 @@ extern "C" { #if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER < 1900) #define FORMAT_PREFIX "I" -#elif defined(FORMAT_32BIT) || \ - (defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1900)) || \ +#elif defined(FORMAT_32BIT) || \ + (defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1900)) || \ defined(_BSD_SOURCE) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500) || \ defined(_ISOC99_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) #define FORMAT_PREFIX "z" diff --git a/source/loader/source/loader_impl.c b/source/loader/source/loader_impl.c index f35f0714b..bb99f66cc 100644 --- a/source/loader/source/loader_impl.c +++ b/source/loader/source/loader_impl.c @@ -49,7 +49,7 @@ #define LOADER_IMPL_FUNCTION_INIT "__metacall_initialize__" #define LOADER_IMPL_FUNCTION_FINI "__metacall_finalize__" -#if defined(WIN32) || defined(_WIN32) || \ +#if defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) diff --git a/source/loaders/file_loader/source/file_loader_impl.c b/source/loaders/file_loader/source/file_loader_impl.c index 4ef87e5ed..a3a73289b 100644 --- a/source/loaders/file_loader/source/file_loader_impl.c +++ b/source/loaders/file_loader/source/file_loader_impl.c @@ -53,10 +53,10 @@ typedef struct _stat file_stat_type; #define file_stat _stat -#elif defined(unix) || defined(__unix__) || defined(__unix) || \ +#elif defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__CYGWIN__) || defined(__CYGWIN32__) || \ - defined(__MINGW32__) || defined(__MINGW64__) || \ + defined(__CYGWIN__) || defined(__CYGWIN32__) || \ + defined(__MINGW32__) || defined(__MINGW64__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) #include @@ -68,10 +68,10 @@ typedef struct stat file_stat_type; #endif /* Support for glob, only in POSIX for now (TODO: Implement Windows support) */ -#if !defined(_WIN32) && \ - (defined(unix) || defined(__unix__) || defined(__unix) || \ +#if !defined(_WIN32) && \ + (defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__CYGWIN__) || defined(__CYGWIN32__) || \ + defined(__CYGWIN__) || defined(__CYGWIN32__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__)) #include diff --git a/source/loaders/node_loader/source/node_loader_impl.cpp b/source/loaders/node_loader/source/node_loader_impl.cpp index b0d021665..1b0660c20 100644 --- a/source/loaders/node_loader/source/node_loader_impl.cpp +++ b/source/loaders/node_loader/source/node_loader_impl.cpp @@ -149,9 +149,9 @@ namespace node extern bool linux_at_secure; } -#define NODE_GET_EVENT_LOOP \ - (NAPI_VERSION >= 2) && \ - ((NODE_MAJOR_VERSION == 8 && NODE_MINOR_VERSION >= 10) || \ +#define NODE_GET_EVENT_LOOP \ + (NAPI_VERSION >= 2) && \ + ((NODE_MAJOR_VERSION == 8 && NODE_MINOR_VERSION >= 10) || \ (NODE_MAJOR_VERSION == 9 && NODE_MINOR_VERSION >= 3) || \ (NODE_MAJOR_VERSION >= 10)) diff --git a/source/loaders/node_loader/source/node_loader_port.cpp b/source/loaders/node_loader/source/node_loader_port.cpp index 168038a43..82cdc899e 100644 --- a/source/loaders/node_loader/source/node_loader_port.cpp +++ b/source/loaders/node_loader/source/node_loader_port.cpp @@ -796,26 +796,25 @@ napi_value node_loader_port_metacall_logs(napi_env env, napi_callback_info) // This functions sets the necessary js functions that could be called in NodeJs void node_loader_port_exports(napi_env env, napi_value exports) { -#define NODE_LOADER_PORT_DECL_FUNC(name) \ - do \ - { \ - const char PREPROCESSOR_CONCAT(function_str_, name)[] = PREPROCESSOR_STRINGIFY(name); \ - napi_value PREPROCESSOR_CONCAT(function_, name); \ +#define NODE_LOADER_PORT_DECL_FUNC(name) \ + do \ + { \ + const char PREPROCESSOR_CONCAT(function_str_, name)[] = PREPROCESSOR_STRINGIFY(name); \ + napi_value PREPROCESSOR_CONCAT(function_, name); \ napi_create_function(env, PREPROCESSOR_CONCAT(function_str_, name), sizeof(PREPROCESSOR_CONCAT(function_str_, name)) - 1, PREPROCESSOR_CONCAT(node_loader_port_, name), NULL, &PREPROCESSOR_CONCAT(function_, name)); \ - napi_set_named_property(env, exports, PREPROCESSOR_CONCAT(function_str_, name), PREPROCESSOR_CONCAT(function_, name)); \ - \ + napi_set_named_property(env, exports, PREPROCESSOR_CONCAT(function_str_, name), PREPROCESSOR_CONCAT(function_, name)); \ } while (0) -#define NODE_LOADER_PORT_DECL_X_MACRO(x) \ - x(metacall); \ - x(metacall_await); \ - x(metacall_load_from_file); \ - x(metacall_load_from_file_export); \ - x(metacall_load_from_memory); \ - x(metacall_load_from_memory_export); \ - x(metacall_load_from_configuration); \ +#define NODE_LOADER_PORT_DECL_X_MACRO(x) \ + x(metacall); \ + x(metacall_await); \ + x(metacall_load_from_file); \ + x(metacall_load_from_file_export); \ + x(metacall_load_from_memory); \ + x(metacall_load_from_memory_export); \ + x(metacall_load_from_configuration); \ x(metacall_load_from_configuration_export); \ - x(metacall_inspect); \ + x(metacall_inspect); \ x(metacall_logs); /* Declare all the functions */ diff --git a/source/loaders/node_loader/source/node_loader_trampoline.cpp b/source/loaders/node_loader/source/node_loader_trampoline.cpp index ceeae0606..15380ef50 100644 --- a/source/loaders/node_loader/source/node_loader_trampoline.cpp +++ b/source/loaders/node_loader/source/node_loader_trampoline.cpp @@ -12,8 +12,8 @@ #include /* TODO: Improve this trick */ #define NODE_LOADER_TRAMPOLINE_DECLARE_NAPI_METHOD(name, func) \ - { \ - name, 0, func, 0, 0, 0, napi_default, 0 \ + { \ + name, 0, func, 0, 0, 0, napi_default, 0 \ } typedef void *(*future_resolve_callback)(void *, void *); diff --git a/source/loaders/rb_loader/source/rb_loader_impl.c b/source/loaders/rb_loader/source/rb_loader_impl.c index 4e7ee73f0..0bd8fb194 100644 --- a/source/loaders/rb_loader/source/rb_loader_impl.c +++ b/source/loaders/rb_loader/source/rb_loader_impl.c @@ -67,14 +67,14 @@ #define rb_fiber_resume_kw(o, c, v, kw) rb_fiber_resume(o, c, v) #define rb_fiber_yield_kw(c, v, kw) rb_fiber_yield(c, v) #define rb_enumeratorize_with_size_kw(o, m, c, v, f, kw) rb_enumeratorize_with_size(o, m, c, v, f) - #define SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) \ + #define SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) \ rb_enumeratorize_with_size((obj), ID2SYM(rb_frame_this_func()), \ (argc), (argv), (size_fn)) #define RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) \ - do \ - { \ - if (!rb_block_given_p()) \ - return SIZED_ENUMERATOR(obj, argc, argv, size_fn); \ + do \ + { \ + if (!rb_block_given_p()) \ + return SIZED_ENUMERATOR(obj, argc, argv, size_fn); \ } while (0) #define RETURN_ENUMERATOR_KW(obj, argc, argv, kw_splat) RETURN_SIZED_ENUMERATOR(obj, argc, argv, 0) #define rb_check_funcall_kw(o, m, c, v, kw) rb_check_funcall(o, m, c, v) @@ -378,20 +378,20 @@ static VALUE rb_loader_impl_funcallv_kw_protect(VALUE args) } /* TODO: Convert this into a return exception */ -#define rb_loader_impl_print_last_exception() \ - do \ - { \ - VALUE e = rb_errinfo(); \ - if (e != Qnil) \ - { \ - VALUE error; \ - VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0); \ - VALUE msg = rb_funcall(e, rb_intern("message"), 0); \ - bt = rb_ary_entry(bt, 0); \ - error = rb_sprintf("%" PRIsVALUE ": %" PRIsVALUE " (%s)\n", bt, msg, rb_obj_classname(e)); \ +#define rb_loader_impl_print_last_exception() \ + do \ + { \ + VALUE e = rb_errinfo(); \ + if (e != Qnil) \ + { \ + VALUE error; \ + VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0); \ + VALUE msg = rb_funcall(e, rb_intern("message"), 0); \ + bt = rb_ary_entry(bt, 0); \ + error = rb_sprintf("%" PRIsVALUE ": %" PRIsVALUE " (%s)\n", bt, msg, rb_obj_classname(e)); \ log_write("metacall", LOG_LEVEL_ERROR, "Exception raised in Ruby '%s'", RSTRING_PTR(error)); \ - rb_backtrace(); \ - } \ + rb_backtrace(); \ + } \ } while (0) function_return function_rb_interface_invoke(function func, function_impl impl, function_args args, size_t size) diff --git a/source/log/include/log/log_preprocessor.h b/source/log/include/log/log_preprocessor.h index cbdbe5cb8..621a2f2b5 100644 --- a/source/log/include/log/log_preprocessor.h +++ b/source/log/include/log/log_preprocessor.h @@ -43,13 +43,13 @@ extern "C" { #if (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ (defined(__STDC__) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) - #define log_write(name, level, ...) \ - PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + #define log_write(name, level, ...) \ + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ log_write_impl(name, LOG_PREPROCESSOR_LINE, log_record_function(), __FILE__, level, __VA_ARGS__), \ log_write_impl_va(name, LOG_PREPROCESSOR_LINE, log_record_function(), __FILE__, level, __VA_ARGS__)) #else - #define log_write(name, level, message, ...) \ - PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + #define log_write(name, level, message, ...) \ + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ log_write_impl(name, LOG_PREPROCESSOR_LINE, log_record_function(), __FILE__, level, message), \ log_write_impl_va(name, LOG_PREPROCESSOR_LINE, log_record_function(), __FILE__, level, message, __VA_ARGS__)) #endif diff --git a/source/log/source/log_policy_format_text.c b/source/log/source/log_policy_format_text.c index addbf6c6b..1a4648fe5 100644 --- a/source/log/source/log_policy_format_text.c +++ b/source/log/source/log_policy_format_text.c @@ -32,10 +32,10 @@ #define va_copy(dest, src) __va_copy((dest), (src)) #elif defined(__builtin_va_copy) #define va_copy(dest, src) __builtin_va_copy((dest), (src)) - #elif defined(_WIN32) || defined(_WIN64) || \ - defined(_ARCH_PPC) || defined(_POWER) || defined(powerpc) || defined(__powerpc) || \ + #elif defined(_WIN32) || defined(_WIN64) || \ + defined(_ARCH_PPC) || defined(_POWER) || defined(powerpc) || defined(__powerpc) || \ defined(__powerpc__) || defined(__PowerPC__) || defined(__POWERPC__) || defined(PPC) || \ - defined(__ppc__) || defined(__PPC) || defined(__PPC__) || \ + defined(__ppc__) || defined(__PPC) || defined(__PPC__) || \ defined(_ARCH_PPC64) || defined(__powerpc64__) || defined(__ppc64) || defined(__ppc64__) || defined(__PPC64__) /* Works for Microsoft x86, x64 and PowerPC-based platforms */ #define va_copy(dest, src) ((void)memcpy(&(dest), &(src), sizeof(va_list))) diff --git a/source/log/source/log_policy_stream_syslog.c b/source/log/source/log_policy_stream_syslog.c index 17fb6dade..f07edb6e0 100644 --- a/source/log/source/log_policy_stream_syslog.c +++ b/source/log/source/log_policy_stream_syslog.c @@ -26,7 +26,7 @@ #include #endif #elif defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__FreeBSD__) || \ + defined(__FreeBSD__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) #include #endif @@ -55,7 +55,7 @@ struct log_policy_stream_syslog_data_type #if defined(_WIN32) HANDLE handle; #elif defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__FreeBSD__) || \ + defined(__FreeBSD__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) /* ... */ #endif @@ -105,7 +105,7 @@ static int log_policy_stream_syslog_create(log_policy policy, const log_policy_c #if defined(_WIN32) syslog_data->handle = RegisterEventSource(NULL, syslog_data->name); #elif defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__FreeBSD__) || \ + defined(__FreeBSD__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) openlog(syslog_data->name, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER); #endif @@ -133,7 +133,7 @@ static int log_policy_stream_syslog_write(log_policy policy, const void *buffer, LOG_POLICY_STREAM_SYSLOG_WIN_MSG, NULL, 1, 0, (LPTSTR *)lpt_str, NULL); #elif defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__FreeBSD__) || \ + defined(__FreeBSD__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) (void)syslog_data; @@ -162,7 +162,7 @@ static int log_policy_stream_syslog_destroy(log_policy policy) DeregisterEventSource(syslog_data->handle); } #elif defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__FreeBSD__) || \ + defined(__FreeBSD__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) closelog(); #endif diff --git a/source/metacall/include/metacall/metacall_fork.h b/source/metacall/include/metacall/metacall_fork.h index 9e9b7f0cc..d3a78eccc 100644 --- a/source/metacall/include/metacall/metacall_fork.h +++ b/source/metacall/include/metacall/metacall_fork.h @@ -29,7 +29,7 @@ extern "C" { #endif -#if defined(WIN32) || defined(_WIN32) || \ +#if defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) @@ -41,9 +41,9 @@ extern "C" { typedef int metacall_pid; -#elif defined(unix) || defined(__unix__) || defined(__unix) || \ +#elif defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__CYGWIN__) || defined(__CYGWIN32__) || \ + defined(__CYGWIN__) || defined(__CYGWIN32__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) /* -- Headers -- */ diff --git a/source/metacall/source/metacall_fork.c b/source/metacall/source/metacall_fork.c index 0e5eb60f4..2bfa05e6c 100644 --- a/source/metacall/source/metacall_fork.c +++ b/source/metacall/source/metacall_fork.c @@ -17,7 +17,7 @@ #include -#if defined(WIN32) || defined(_WIN32) || \ +#if defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) @@ -85,9 +85,9 @@ NTSTATUS NTAPI metacall_fork_hook(ULONG ProcessFlags, HANDLE DebugPort, PRTL_USER_PROCESS_INFORMATION ProcessInformation); -#elif defined(unix) || defined(__unix__) || defined(__unix) || \ +#elif defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__CYGWIN__) || defined(__CYGWIN32__) || \ + defined(__CYGWIN__) || defined(__CYGWIN32__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) /* -- Methods -- */ @@ -115,7 +115,7 @@ static int metacall_fork_flag = 1; /* -- Methods -- */ -#if defined(WIN32) || defined(_WIN32) || \ +#if defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) @@ -205,9 +205,9 @@ NTSTATUS NTAPI metacall_fork_hook(ULONG ProcessFlags, return result; } -#elif defined(unix) || defined(__unix__) || defined(__unix) || \ +#elif defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__CYGWIN__) || defined(__CYGWIN32__) || \ + defined(__CYGWIN__) || defined(__CYGWIN32__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) void (*metacall_fork_func(void))(void) diff --git a/source/portability/include/portability/portability_executable_path.h b/source/portability/include/portability/portability_executable_path.h index a1d5be8b8..0f1908d59 100644 --- a/source/portability/include/portability/portability_executable_path.h +++ b/source/portability/include/portability/portability_executable_path.h @@ -31,11 +31,11 @@ typedef char portability_executable_path_str[PORTABILITY_PATH_SIZE]; -#if defined(WIN32) || defined(_WIN32) || \ +#if defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) typedef DWORD portability_executable_path_length; -#elif defined(unix) || defined(__unix__) || defined(__unix) || \ +#elif defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ defined(__NetBSD__) || defined(__DragonFly__) diff --git a/source/portability/include/portability/portability_path.h b/source/portability/include/portability/portability_path.h index 2421092ea..f8124edca 100644 --- a/source/portability/include/portability/portability_path.h +++ b/source/portability/include/portability/portability_path.h @@ -28,7 +28,7 @@ /* -- Definitions -- */ /* Path limits */ -#if defined(WIN32) || defined(_WIN32) || \ +#if defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) @@ -42,7 +42,7 @@ #include #define PORTABILITY_PATH_SIZE MAX_PATH -#elif defined(unix) || defined(__unix__) || defined(__unix) || \ +#elif defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ defined(__NetBSD__) || defined(__DragonFly__) @@ -73,17 +73,17 @@ #endif /* Path separator */ -#if defined(WIN32) || defined(_WIN32) || \ +#if defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) #define PORTABILITY_PATH_SEPARATOR(chr) (chr == '\\' || chr == '/') #define PORTABILITY_PATH_SEPARATOR_C '/' -#elif defined(unix) || defined(__unix__) || defined(__unix) || \ +#elif defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__CYGWIN__) || defined(__CYGWIN32__) || \ - (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) || \ + defined(__CYGWIN__) || defined(__CYGWIN32__) || \ + (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) || \ defined(__HAIKU__) || defined(__BEOS__) #define PORTABILITY_PATH_SEPARATOR(chr) (chr == '/') #define PORTABILITY_PATH_SEPARATOR_C '/' @@ -93,7 +93,7 @@ #endif /* Path delimiter */ -#if defined(WIN32) || defined(_WIN32) || \ +#if defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) diff --git a/source/portability/source/portability_executable_path.c b/source/portability/source/portability_executable_path.c index ac07d1151..75cc306c8 100644 --- a/source/portability/source/portability_executable_path.c +++ b/source/portability/source/portability_executable_path.c @@ -35,7 +35,7 @@ int portability_executable_path(portability_executable_path_str path, portabilit /* Reset the path */ memset(path, 0, path_max_length); -#if defined(WIN32) || defined(_WIN32) || \ +#if defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) *length = GetModuleFileName(NULL, path, (DWORD)path_max_length); diff --git a/source/portability/source/portability_library_path.c b/source/portability/source/portability_library_path.c index 2f6f7c996..baaaa5bb1 100644 --- a/source/portability/source/portability_library_path.c +++ b/source/portability/source/portability_library_path.c @@ -68,7 +68,7 @@ static int portability_library_path_phdr_callback(struct dl_phdr_info *info, siz return 0; } -#elif defined(WIN32) || defined(_WIN32) || \ +#elif defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) @@ -118,7 +118,7 @@ int portability_library_path(const char name[], portability_library_path_str pat return 0; -#elif defined(WIN32) || defined(_WIN32) || \ +#elif defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) diff --git a/source/portability/source/portability_path.c b/source/portability/source/portability_path.c index 31ed52060..87bedb53e 100644 --- a/source/portability/source/portability_path.c +++ b/source/portability/source/portability_path.c @@ -250,10 +250,10 @@ int portability_path_is_absolute(const char *path, size_t size) return !((path[0] != '\0' && (path[0] >= 'A' && path[0] <= 'Z')) && (path[1] != '\0' && path[1] == ':') && (path[2] != '\0' && PORTABILITY_PATH_SEPARATOR(path[2]))); -#elif defined(unix) || defined(__unix__) || defined(__unix) || \ +#elif defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__CYGWIN__) || defined(__CYGWIN32__) || \ - (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) || \ + defined(__CYGWIN__) || defined(__CYGWIN32__) || \ + (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) || \ defined(__HAIKU__) || defined(__BEOS__) if (size < 1) diff --git a/source/reflect/include/reflect/reflect_class_visibility.h b/source/reflect/include/reflect/reflect_class_visibility.h index 5df5e0bdb..3f81c8dcb 100644 --- a/source/reflect/include/reflect/reflect_class_visibility.h +++ b/source/reflect/include/reflect/reflect_class_visibility.h @@ -31,8 +31,8 @@ extern "C" { #endif -#define CLASS_VISIBILITY_X(X) \ - X(PUBLIC, "public", 0), \ +#define CLASS_VISIBILITY_X(X) \ + X(PUBLIC, "public", 0), \ X(PROTECTED, "protected", 1), \ X(PRIVATE, "private", 2) diff --git a/source/reflect/include/reflect/reflect_memory_tracker.h b/source/reflect/include/reflect/reflect_memory_tracker.h index 166f5a72c..28e85c6d3 100644 --- a/source/reflect/include/reflect/reflect_memory_tracker.h +++ b/source/reflect/include/reflect/reflect_memory_tracker.h @@ -35,13 +35,13 @@ extern "C" { #include - #define reflect_memory_tracker(name) \ - static struct \ - { \ - atomic_uintmax_t allocations; \ + #define reflect_memory_tracker(name) \ + static struct \ + { \ + atomic_uintmax_t allocations; \ atomic_uintmax_t deallocations; \ - atomic_uintmax_t increments; \ - atomic_uintmax_t decrements; \ + atomic_uintmax_t increments; \ + atomic_uintmax_t decrements; \ } name = { 0, 0, 0, 0 } #define reflect_memory_tracker_allocation(name) \ @@ -57,34 +57,34 @@ extern "C" { atomic_fetch_add_explicit(&name.decrements, 1, memory_order_relaxed) #if !defined(NDEBUG) || defined(DEBUG) || defined(_DEBUG) || defined(__DEBUG) || defined(__DEBUG__) - #define reflect_memory_tracker_print(name, title) \ - do \ - { \ - printf("----------------- " title " -----------------\n"); \ - printf("Allocations: %" PRIuMAX "\n", atomic_load_explicit(&name.allocations, memory_order_relaxed)); \ + #define reflect_memory_tracker_print(name, title) \ + do \ + { \ + printf("----------------- " title " -----------------\n"); \ + printf("Allocations: %" PRIuMAX "\n", atomic_load_explicit(&name.allocations, memory_order_relaxed)); \ printf("Deallocations: %" PRIuMAX "\n", atomic_load_explicit(&name.deallocations, memory_order_relaxed)); \ - printf("Increments: %" PRIuMAX "\n", atomic_load_explicit(&name.increments, memory_order_relaxed)); \ - printf("Decrements: %" PRIuMAX "\n", atomic_load_explicit(&name.decrements, memory_order_relaxed)); \ - fflush(stdout); \ + printf("Increments: %" PRIuMAX "\n", atomic_load_explicit(&name.increments, memory_order_relaxed)); \ + printf("Decrements: %" PRIuMAX "\n", atomic_load_explicit(&name.decrements, memory_order_relaxed)); \ + fflush(stdout); \ } while (0) #else - #define reflect_memory_tracker_print(name, title) \ - do \ - { \ - uintmax_t allocations = atomic_load_explicit(&name.allocations, memory_order_relaxed); \ - uintmax_t deallocations = atomic_load_explicit(&name.deallocations, memory_order_relaxed); \ - uintmax_t increments = atomic_load_explicit(&name.increments, memory_order_relaxed); \ - uintmax_t decrements = atomic_load_explicit(&name.decrements, memory_order_relaxed); \ + #define reflect_memory_tracker_print(name, title) \ + do \ + { \ + uintmax_t allocations = atomic_load_explicit(&name.allocations, memory_order_relaxed); \ + uintmax_t deallocations = atomic_load_explicit(&name.deallocations, memory_order_relaxed); \ + uintmax_t increments = atomic_load_explicit(&name.increments, memory_order_relaxed); \ + uintmax_t decrements = atomic_load_explicit(&name.decrements, memory_order_relaxed); \ /* This comparison is safe to be done like this because it is done once execution has finalized */ \ - if (allocations != deallocations || increments != decrements) \ - { \ - printf("----------------- " title " -----------------\n"); \ - printf("Allocations: %" PRIuMAX "\n", allocations); \ - printf("Deallocations: %" PRIuMAX "\n", deallocations); \ - printf("Increments: %" PRIuMAX "\n", increments); \ - printf("Decrements: %" PRIuMAX "\n", decrements); \ - fflush(stdout); \ - } \ + if (allocations != deallocations || increments != decrements) \ + { \ + printf("----------------- " title " -----------------\n"); \ + printf("Allocations: %" PRIuMAX "\n", allocations); \ + printf("Deallocations: %" PRIuMAX "\n", deallocations); \ + printf("Increments: %" PRIuMAX "\n", increments); \ + printf("Decrements: %" PRIuMAX "\n", decrements); \ + fflush(stdout); \ + } \ } while (0) #endif #else @@ -92,28 +92,28 @@ extern "C" { typedef char reflect_memory_tracker_disabled #define reflect_memory_tracker_allocation(name) \ - do \ - { \ + do \ + { \ } while (0) #define reflect_memory_tracker_deallocation(name) \ - do \ - { \ + do \ + { \ } while (0) #define reflect_memory_tracker_increment(name) \ - do \ - { \ + do \ + { \ } while (0) #define reflect_memory_tracker_decrement(name) \ - do \ - { \ + do \ + { \ } while (0) #define reflect_memory_tracker_print(name, title) \ - do \ - { \ + do \ + { \ } while (0) #endif diff --git a/source/reflect/source/reflect_class_visibility.c b/source/reflect/source/reflect_class_visibility.c index 1515cc0a1..142a85a72 100644 --- a/source/reflect/source/reflect_class_visibility.c +++ b/source/reflect/source/reflect_class_visibility.c @@ -29,8 +29,8 @@ struct visibility_string_length_type }; #define CLASS_VISIBILITY_STRUCT(name, str, id) \ - { \ - str, sizeof(str) - 1 \ + { \ + str, sizeof(str) - 1 \ } static struct visibility_string_length_type visibility_array[] = { diff --git a/source/tests/metacall_fork_test/source/metacall_fork_test.cpp b/source/tests/metacall_fork_test/source/metacall_fork_test.cpp index 63a02f88f..0e25266a2 100644 --- a/source/tests/metacall_fork_test/source/metacall_fork_test.cpp +++ b/source/tests/metacall_fork_test/source/metacall_fork_test.cpp @@ -20,7 +20,7 @@ class metacall_fork_test : public testing::Test static int pre_callback_fired = 0; static int post_callback_fired = 0; -#if defined(WIN32) || defined(_WIN32) || \ +#if defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) diff --git a/source/tests/metacall_node_extension_test/node_extension_test/source/node_extension_test.c b/source/tests/metacall_node_extension_test/node_extension_test/source/node_extension_test.c index 24b135680..d5a9087f2 100644 --- a/source/tests/metacall_node_extension_test/node_extension_test/source/node_extension_test.c +++ b/source/tests/metacall_node_extension_test/node_extension_test/source/node_extension_test.c @@ -33,8 +33,8 @@ static napi_value Method(napi_env env, napi_callback_info info) return world; } -#define DECLARE_NAPI_METHOD(name, func) \ - { \ +#define DECLARE_NAPI_METHOD(name, func) \ + { \ name, 0, func, 0, 0, 0, napi_default, 0 \ } diff --git a/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp b/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp index e9beb938f..9e075cd3b 100644 --- a/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp +++ b/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp @@ -45,7 +45,7 @@ TEST_F(metacall_sandbox_plugin_test, DefaultConstructor) /* Initialize sandboxing */ { - void *args[1] = { metacall_value_create_bool(0L) }; + void *args[1] = { metacall_value_create_bool(1L) /* Allow */ }; sandbox_ctx = metacallhv_s(handle, "sandbox_initialize", args, 1); @@ -57,7 +57,7 @@ TEST_F(metacall_sandbox_plugin_test, DefaultConstructor) /* Disable uname syscall */ { - void *args[2] = { sandbox_ctx, metacall_value_create_bool(0L) }; + void *args[2] = { sandbox_ctx, metacall_value_create_bool(0L) /* Kill */ }; void *ret = metacallhv_s(handle, "sandbox_uname", args, 2); diff --git a/source/tests/metacall_test/source/metacall_test.cpp b/source/tests/metacall_test/source/metacall_test.cpp index 36a225395..831cb2926 100644 --- a/source/tests/metacall_test/source/metacall_test.cpp +++ b/source/tests/metacall_test/source/metacall_test.cpp @@ -36,10 +36,10 @@ #endif #include -#elif defined(unix) || defined(__unix__) || defined(__unix) || \ +#elif defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__CYGWIN__) || defined(__CYGWIN32__) || \ - defined(__MINGW32__) || defined(__MINGW64__) || \ + defined(__CYGWIN__) || defined(__CYGWIN32__) || \ + defined(__MINGW32__) || defined(__MINGW64__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) #include #endif @@ -79,10 +79,10 @@ TEST_F(metacall_test, DefaultConstructor) ASSERT_NE((DWORD)0, (DWORD)GetCurrentDirectory(length, cwd)); - #elif defined(unix) || defined(__unix__) || defined(__unix) || \ + #elif defined(unix) || defined(__unix__) || defined(__unix) || \ defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ - defined(__CYGWIN__) || defined(__CYGWIN32__) || \ - defined(__MINGW32__) || defined(__MINGW64__) || \ + defined(__CYGWIN__) || defined(__CYGWIN32__) || \ + defined(__MINGW32__) || defined(__MINGW64__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) char cwd[PATH_MAX]; diff --git a/source/threading/include/threading/threading_atomic_win32.h b/source/threading/include/threading/threading_atomic_win32.h index 4676b69fd..895838e72 100644 --- a/source/threading/include/threading/threading_atomic_win32.h +++ b/source/threading/include/threading/threading_atomic_win32.h @@ -183,29 +183,29 @@ static inline void atomic_store_explicit64(LONG64 volatile *obj, LONG64 desired, #define atomic_store(obj, desired) \ atomic_store_explicit(obj, desired, memory_order_seq_cst) -#define atomic_store_explicit(obj, desired, order) \ - do \ - { \ - if (sizeof *(obj) == 1) \ - { \ - atomic_store_explicit8((CHAR volatile *)(obj), (CHAR)(desired), order); \ - } \ - else if (sizeof *(obj) == 2) \ - { \ - atomic_store_explicit16((SHORT volatile *)(obj), (SHORT)(desired), order); \ - } \ - else if (sizeof *(obj) == 4) \ - { \ - atomic_store_explicit32((LONG volatile *)(obj), (LONG)(desired), order); \ - } \ - else if (sizeof *(obj) == 8) \ - { \ +#define atomic_store_explicit(obj, desired, order) \ + do \ + { \ + if (sizeof *(obj) == 1) \ + { \ + atomic_store_explicit8((CHAR volatile *)(obj), (CHAR)(desired), order); \ + } \ + else if (sizeof *(obj) == 2) \ + { \ + atomic_store_explicit16((SHORT volatile *)(obj), (SHORT)(desired), order); \ + } \ + else if (sizeof *(obj) == 4) \ + { \ + atomic_store_explicit32((LONG volatile *)(obj), (LONG)(desired), order); \ + } \ + else if (sizeof *(obj) == 8) \ + { \ atomic_store_explicit64((LONG64 volatile *)(obj), (LONG64)(desired), order); \ - } \ - else \ - { \ - abort(); \ - } \ + } \ + else \ + { \ + abort(); \ + } \ } while (0) #define atomic_load(obj) \ @@ -217,10 +217,10 @@ static inline void atomic_store_explicit64(LONG64 volatile *obj, LONG64 desired, #define atomic_exchange(obj, desired) \ atomic_exchange_explicit(obj, desired, memory_order_seq_cst) -#define atomic_exchange_explicit(obj, desired, order) \ - ((sizeof *(obj) == 1) ? _InterlockedExchange8((CHAR volatile *)obj, (CHAR)desired) : \ - (sizeof *(obj) == 2) ? _InterlockedExchange16((SHORT volatile *)obj, (SHORT)desired) : \ - (sizeof *(obj) == 4) ? _InterlockedExchange((LONG volatile *)obj, (LONG)desired) : \ +#define atomic_exchange_explicit(obj, desired, order) \ + ((sizeof *(obj) == 1) ? _InterlockedExchange8((CHAR volatile *)obj, (CHAR)desired) : \ + (sizeof *(obj) == 2) ? _InterlockedExchange16((SHORT volatile *)obj, (SHORT)desired) : \ + (sizeof *(obj) == 4) ? _InterlockedExchange((LONG volatile *)obj, (LONG)desired) : \ (sizeof *(obj) == 8) ? _InterlockedExchange64((LONG64 volatile *)obj, (LONG64)desired) : \ (abort(), 0)) @@ -276,10 +276,10 @@ static inline bool atomic_compare_exchange64(LONG64 volatile *obj, LONG64 *expec return result; } -#define atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, fail) \ - ((sizeof *(obj) == 1) ? atomic_compare_exchange8((CHAR volatile *)(obj), (CHAR *)(expected), (CHAR)(desired)) : \ - (sizeof *(obj) == 2) ? atomic_compare_exchange16((SHORT volatile *)(obj), (SHORT *)(expected), (SHORT)(desired)) : \ - (sizeof *(obj) == 4) ? atomic_compare_exchange32((LONG volatile *)(obj), (LONG *)(expected), (LONG)(desired)) : \ +#define atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, fail) \ + ((sizeof *(obj) == 1) ? atomic_compare_exchange8((CHAR volatile *)(obj), (CHAR *)(expected), (CHAR)(desired)) : \ + (sizeof *(obj) == 2) ? atomic_compare_exchange16((SHORT volatile *)(obj), (SHORT *)(expected), (SHORT)(desired)) : \ + (sizeof *(obj) == 4) ? atomic_compare_exchange32((LONG volatile *)(obj), (LONG *)(expected), (LONG)(desired)) : \ (sizeof *(obj) == 8) ? atomic_compare_exchange64((LONG64 volatile *)(obj), (LONG64 *)(expected), (LONG64)(desired)) : \ (abort(), false)) @@ -294,10 +294,10 @@ static inline bool atomic_compare_exchange64(LONG64 volatile *obj, LONG64 *expec #define atomic_fetch_add(obj, arg) \ atomic_fetch_add_explicit(obj, arg, memory_order_seq_cst) -#define atomic_fetch_add_explicit(obj, arg, order) \ - ((sizeof *(obj) == 1) ? _InterlockedExchangeAdd8((char volatile *)obj, (char)(arg)) : \ - (sizeof *(obj) == 2) ? _InterlockedExchangeAdd16((SHORT volatile *)obj, (SHORT)(arg)) : \ - (sizeof *(obj) == 4) ? _InterlockedExchangeAdd((LONG volatile *)obj, (LONG)(arg)) : \ +#define atomic_fetch_add_explicit(obj, arg, order) \ + ((sizeof *(obj) == 1) ? _InterlockedExchangeAdd8((char volatile *)obj, (char)(arg)) : \ + (sizeof *(obj) == 2) ? _InterlockedExchangeAdd16((SHORT volatile *)obj, (SHORT)(arg)) : \ + (sizeof *(obj) == 4) ? _InterlockedExchangeAdd((LONG volatile *)obj, (LONG)(arg)) : \ (sizeof *(obj) == 8) ? _InterlockedExchangeAdd64((LONG64 volatile *)obj, (LONG64)(arg)) : \ (abort(), 0)) @@ -310,40 +310,40 @@ static inline bool atomic_compare_exchange64(LONG64 volatile *obj, LONG64 *expec #define atomic_fetch_or(obj, arg) \ atomic_fetch_or_explicit(obj, arg, memory_order_seq_cst) -#define atomic_fetch_or_explicit(obj, arg, order) \ - ((sizeof *(obj) == 1) ? _InterlockedOr8((char volatile *)obj, (char)(arg)) : \ - (sizeof *(obj) == 2) ? _InterlockedOr16((SHORT volatile *)obj, (SHORT)(arg)) : \ - (sizeof *(obj) == 4) ? _InterlockedOr((LONG volatile *)obj, (LONG)(arg)) : \ +#define atomic_fetch_or_explicit(obj, arg, order) \ + ((sizeof *(obj) == 1) ? _InterlockedOr8((char volatile *)obj, (char)(arg)) : \ + (sizeof *(obj) == 2) ? _InterlockedOr16((SHORT volatile *)obj, (SHORT)(arg)) : \ + (sizeof *(obj) == 4) ? _InterlockedOr((LONG volatile *)obj, (LONG)(arg)) : \ (sizeof *(obj) == 8) ? _InterlockedOr64((LONG64 volatile *)obj, (LONG64)(arg)) : \ (abort(), 0)) #define atomic_fetch_xor(obj, arg) \ atomic_fetch_xor_explicit(obj, arg, memory_order_seq_cst) -#define atomic_fetch_xor_explicit(obj, arg, order) \ - ((sizeof *(obj) == 1) ? _InterlockedXor8((char volatile *)obj, (char)(arg)) : \ - (sizeof *(obj) == 2) ? _InterlockedXor16((SHORT volatile *)obj, (SHORT)(arg)) : \ - (sizeof *(obj) == 4) ? _InterlockedXor((LONG volatile *)obj, (LONG)(arg)) : \ +#define atomic_fetch_xor_explicit(obj, arg, order) \ + ((sizeof *(obj) == 1) ? _InterlockedXor8((char volatile *)obj, (char)(arg)) : \ + (sizeof *(obj) == 2) ? _InterlockedXor16((SHORT volatile *)obj, (SHORT)(arg)) : \ + (sizeof *(obj) == 4) ? _InterlockedXor((LONG volatile *)obj, (LONG)(arg)) : \ (sizeof *(obj) == 8) ? _InterlockedXor64((LONG64 volatile *)obj, (LONG64)(arg)) : \ (abort(), 0)) #define atomic_fetch_and(obj, arg) \ atomic_fetch_and_explicit(obj, arg, memory_order_seq_cst) -#define atomic_fetch_and_explicit(obj, arg, order) \ - ((sizeof *(obj) == 1) ? _InterlockedAnd8((char volatile *)obj, (char)(arg)) : \ - (sizeof *(obj) == 2) ? _InterlockedAnd16((SHORT volatile *)obj, (SHORT)(arg)) : \ - (sizeof *(obj) == 4) ? _InterlockedAnd((LONG volatile *)obj, (LONG)(arg)) : \ +#define atomic_fetch_and_explicit(obj, arg, order) \ + ((sizeof *(obj) == 1) ? _InterlockedAnd8((char volatile *)obj, (char)(arg)) : \ + (sizeof *(obj) == 2) ? _InterlockedAnd16((SHORT volatile *)obj, (SHORT)(arg)) : \ + (sizeof *(obj) == 4) ? _InterlockedAnd((LONG volatile *)obj, (LONG)(arg)) : \ (sizeof *(obj) == 8) ? _InterlockedAnd64((LONG64 volatile *)obj, (LONG64)(arg)) : \ (abort(), 0)) -#define __atomic_compiler_barrier(order) \ - do \ - { \ +#define __atomic_compiler_barrier(order) \ + do \ + { \ if (order > memory_order_consume) \ - { \ - _ReadWriteBarrier(); \ - } \ + { \ + _ReadWriteBarrier(); \ + } \ } while (0) static inline void atomic_thread_fence(memory_order order) diff --git a/source/threading/include/threading/threading_mutex.h b/source/threading/include/threading/threading_mutex.h index e0048eacf..29f5163de 100644 --- a/source/threading/include/threading/threading_mutex.h +++ b/source/threading/include/threading/threading_mutex.h @@ -35,10 +35,10 @@ extern "C" { #include typedef CRITICAL_SECTION threading_mutex_impl_type; #elif (defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux) || defined(__gnu_linux__) || defined(__TOS_LINUX__)) || \ - defined(__FreeBSD__) || \ - defined(__NetBSD__) || \ - defined(__OpenBSD__) || \ - (defined(bsdi) || defined(__bsdi__)) || \ + defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__OpenBSD__) || \ + (defined(bsdi) || defined(__bsdi__)) || \ defined(__DragonFly__) #include typedef pthread_mutex_t threading_mutex_impl_type; From f66f453a61599513deba8380d7af1915ee13fd15 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 5 Oct 2023 21:36:26 +0200 Subject: [PATCH 020/615] Solving more issues with preprocessor. --- source/tests/preprocessor_test/source/preprocessor_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/tests/preprocessor_test/source/preprocessor_test.cpp b/source/tests/preprocessor_test/source/preprocessor_test.cpp index a569c2ded..442f74de8 100644 --- a/source/tests/preprocessor_test/source/preprocessor_test.cpp +++ b/source/tests/preprocessor_test/source/preprocessor_test.cpp @@ -114,7 +114,7 @@ TEST_F(preprocessor_test, empty) { const char empty_str[] = ""; - EXPECT_EQ((int)0, (int)strcmp(empty_str, PREPROCESSOR_STRINGIFY(PREPROCESSOR_EMPTY_SYMBOL()))); + EXPECT_EQ((int)0, (int)strcmp(empty_str, PREPROCESSOR_STRINGIFY_OR_EMPTY(PREPROCESSOR_EMPTY_SYMBOL()))); PREPROCESSOR_EMPTY_EXPANSION(this must compile) From 18d0d5e031a1d4096c5a3ecdb9b3ffac5b0aa6e5 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 5 Oct 2023 22:18:48 +0200 Subject: [PATCH 021/615] Add base of preprocessor for. --- .../include/plugin/plugin_interface.hpp | 5 +- .../sandbox_plugin/source/sandbox_plugin.cpp | 2 +- .../preprocessor/cmake/preprocessor_for.cmake | 30 +++++ .../cmake/preprocessor_for_body.h.in | 36 ++++++ .../include/preprocessor/preprocessor_for.h | 104 ++++++++++++++++++ .../source/preprocessor_test.cpp | 30 +++-- 6 files changed, 194 insertions(+), 13 deletions(-) diff --git a/source/plugin/include/plugin/plugin_interface.hpp b/source/plugin/include/plugin/plugin_interface.hpp index 67fee1961..83d41bba6 100644 --- a/source/plugin/include/plugin/plugin_interface.hpp +++ b/source/plugin/include/plugin/plugin_interface.hpp @@ -70,7 +70,7 @@ return value_create_throwable(th); \ } while (0) -#define EXTENSION_FUNCTION_CHECK_ITERATOR(value, iterator, error) \ +#define EXTENSION_FUNCTION_CHECK_ITERATOR(error, iterator, value) \ if (metacall_value_id(args[iterator]) != value) \ { \ std::stringstream ss; \ @@ -79,9 +79,6 @@ EXTENSION_FUNCTION_THROW(error_msg.c_str()); \ } -/* TODO: */ -#define PREPROCESSOR_FOR(macro, context, ...) - #define EXTENSION_FUNCTION_CHECK(error, ...) \ do \ { \ diff --git a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp index 72715c094..c7c6ab649 100644 --- a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp +++ b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp @@ -25,7 +25,7 @@ #include /* TODO: Use SCMP_ACT_KILL_PROCESS instead of SCMP_ACT_KILL for catching the signal and showing the stack trace? */ -/* TODO: We can disable bool (true/false) for string ("allow"/"disable") */ +/* TODO: We can disable bool (true/false) for string ("allow"/"kill") */ #define SANDBOX_ACTION(value) \ metacall_value_to_bool(value) == 0L ? SCMP_ACT_KILL : SCMP_ACT_ALLOW diff --git a/source/preprocessor/cmake/preprocessor_for.cmake b/source/preprocessor/cmake/preprocessor_for.cmake index c3ee2d116..9355ef4d5 100644 --- a/source/preprocessor/cmake/preprocessor_for.cmake +++ b/source/preprocessor/cmake/preprocessor_for.cmake @@ -74,6 +74,36 @@ function(preprocessor_for_generate _for_size) endforeach() + # Definition implementation: PREPROCESSOR_FOR_IMPL + set(PREPROCESSOR_FOR_IMPL_BODY "") + + foreach(iterator RANGE 3 ${PREPROCESSOR_FOR_SIZE}) + + math(EXPR prev "${iterator} - 1") + + set(PREPROCESSOR_FOR_IMPL_BODY "${PREPROCESSOR_FOR_IMPL_BODY}#define PREPROCESSOR_FOR_IMPL_${iterator}(expr, context, element, ...) expr(context, ${prev}, element)") + + set(PREPROCESSOR_FOR_IMPL_BODY "${PREPROCESSOR_FOR_IMPL_BODY} PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_${prev}(expr, context, __VA_ARGS__))\n") + + endforeach() + + # Definition implementation: PREPROCESSOR_FOR_IMPL_GNUC + set(PREPROCESSOR_FOR_IMPL_GNUC_BODY "") + + math(EXPR preprocessor_for_limit "${PREPROCESSOR_FOR_SIZE} - 1") + + foreach(iterator RANGE ${preprocessor_for_limit} 1) + + math(EXPR iterator_modulo "${iterator} % ${preprocessor_for_line_align}") + + if(${iterator_modulo} EQUAL 0) + set(PREPROCESSOR_FOR_IMPL_GNUC_BODY "${PREPROCESSOR_FOR_IMPL_GNUC_BODY}PREPROCESSOR_FOR_IMPL_${iterator}, \\\n\t\t") + else() + set(PREPROCESSOR_FOR_IMPL_GNUC_BODY "${PREPROCESSOR_FOR_IMPL_GNUC_BODY}PREPROCESSOR_FOR_IMPL_${iterator}, ") + endif() + + endforeach() + # Configure for template headers string(CONFIGURE ${preprocessor_for_headers_in} preprocessor_for_headers @ONLY) diff --git a/source/preprocessor/cmake/preprocessor_for_body.h.in b/source/preprocessor/cmake/preprocessor_for_body.h.in index b787c0219..2b428394f 100644 --- a/source/preprocessor/cmake/preprocessor_for_body.h.in +++ b/source/preprocessor/cmake/preprocessor_for_body.h.in @@ -4,6 +4,7 @@ /* -- Macros -- */ +/* Preprocessor foreach, it has a callback like: macro(value) for each element of the variadic arguments */ #define PREPROCESSOR_FOR_EACH_EVAL(expr) expr #define PREPROCESSOR_FOR_EACH_IMPL_0(expr, ...) @@ -33,3 +34,38 @@ #else # error "Unkwnown preprocessor implementation for foreach." #endif + +/* + * Preprocessor for, it has a callback like: macro(context, iterator, element) for each element of the variadic arguments, + * where context is the second value passed to PREPROCESSOR_FOR, iterator is an integer indicating the current iteration, + * and element is the current element being iterated + */ +#define PREPROCESSOR_FOR_EVAL(expr) expr + +#define PREPROCESSOR_FOR_IMPL_0(expr, context, ...) +#define PREPROCESSOR_FOR_IMPL_1(expr, context, element, ...) expr(context, 0, element) +#if (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + (defined(__STDC__) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) +# define PREPROCESSOR_FOR_IMPL_2(expr, context, element, ...) \ + expr(context, 1, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_1(expr, context, __VA_ARGS__, ~)) +#else +# define PREPROCESSOR_FOR_IMPL_2(expr, context, element, ...) \ + expr(context, 1, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_1(expr, context, __VA_ARGS__)) +#endif +@PREPROCESSOR_FOR_IMPL_BODY@ +#if defined(__GNUC__) || defined(__clang__) +# define PREPROCESSOR_FOR(expr, context, ...) \ + PREPROCESSOR_ARGS_N_IMPL(__VA_ARGS__, \ + @PREPROCESSOR_FOR_IMPL_GNUC_BODY@\ + PREPROCESSOR_FOR_IMPL_0)(expr, context, __VA_ARGS__) +#elif defined(_MSC_VER) && !defined(__clang__) +# define PREPROCESSOR_FOR_IMPL_COUNT(count) \ + PREPROCESSOR_CONCAT(PREPROCESSOR_FOR_IMPL_, count) +# define PREPROCESSOR_FOR_IMPL_EXPR(...) \ + PREPROCESSOR_FOR_IMPL_COUNT(PREPROCESSOR_ARGS_COUNT(__VA_ARGS__)) +# define PREPROCESSOR_FOR_EXPAND(expr, args) expr ## args +# define PREPROCESSOR_FOR(expr, context, ...) \ + PREPROCESSOR_FOR_EXPAND(PREPROCESSOR_FOR_IMPL_EXPR(__VA_ARGS__), (expr, context, __VA_ARGS__)) +#else +# error "Unkwnown preprocessor implementation for for." +#endif diff --git a/source/preprocessor/include/preprocessor/preprocessor_for.h b/source/preprocessor/include/preprocessor/preprocessor_for.h index 7edd0b020..98fe25ff1 100644 --- a/source/preprocessor/include/preprocessor/preprocessor_for.h +++ b/source/preprocessor/include/preprocessor/preprocessor_for.h @@ -38,6 +38,7 @@ extern "C" { /* -- Macros -- */ +/* Preprocessor foreach, it has a callback like: macro(value) for each element of the variadic arguments */ #define PREPROCESSOR_FOR_EACH_EVAL(expr) expr #define PREPROCESSOR_FOR_EACH_IMPL_0(expr, ...) @@ -136,6 +137,109 @@ extern "C" { # error "Unkwnown preprocessor implementation for foreach." #endif +/* + * Preprocessor for, it has a callback like: macro(context, iterator, element) for each element of the variadic arguments, + * where context is the second value passed to PREPROCESSOR_FOR, iterator is an integer indicating the current iteration, + * and element is the current element being iterated + */ +#define PREPROCESSOR_FOR_EVAL(expr) expr + +#define PREPROCESSOR_FOR_IMPL_0(expr, context, ...) +#define PREPROCESSOR_FOR_IMPL_1(expr, context, element, ...) expr(context, 0, element) +#if (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + (defined(__STDC__) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) +# define PREPROCESSOR_FOR_IMPL_2(expr, context, element, ...) \ + expr(context, 1, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_1(expr, context, __VA_ARGS__, ~)) +#else +# define PREPROCESSOR_FOR_IMPL_2(expr, context, element, ...) \ + expr(context, 1, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_1(expr, context, __VA_ARGS__)) +#endif +#define PREPROCESSOR_FOR_IMPL_3(expr, context, element, ...) expr(context, 2, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_2(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_4(expr, context, element, ...) expr(context, 3, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_3(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_5(expr, context, element, ...) expr(context, 4, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_4(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_6(expr, context, element, ...) expr(context, 5, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_5(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_7(expr, context, element, ...) expr(context, 6, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_6(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_8(expr, context, element, ...) expr(context, 7, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_7(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_9(expr, context, element, ...) expr(context, 8, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_8(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_10(expr, context, element, ...) expr(context, 9, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_9(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_11(expr, context, element, ...) expr(context, 10, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_10(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_12(expr, context, element, ...) expr(context, 11, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_11(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_13(expr, context, element, ...) expr(context, 12, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_12(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_14(expr, context, element, ...) expr(context, 13, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_13(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_15(expr, context, element, ...) expr(context, 14, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_14(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_16(expr, context, element, ...) expr(context, 15, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_15(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_17(expr, context, element, ...) expr(context, 16, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_16(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_18(expr, context, element, ...) expr(context, 17, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_17(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_19(expr, context, element, ...) expr(context, 18, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_18(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_20(expr, context, element, ...) expr(context, 19, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_19(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_21(expr, context, element, ...) expr(context, 20, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_20(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_22(expr, context, element, ...) expr(context, 21, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_21(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_23(expr, context, element, ...) expr(context, 22, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_22(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_24(expr, context, element, ...) expr(context, 23, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_23(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_25(expr, context, element, ...) expr(context, 24, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_24(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_26(expr, context, element, ...) expr(context, 25, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_25(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_27(expr, context, element, ...) expr(context, 26, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_26(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_28(expr, context, element, ...) expr(context, 27, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_27(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_29(expr, context, element, ...) expr(context, 28, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_28(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_30(expr, context, element, ...) expr(context, 29, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_29(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_31(expr, context, element, ...) expr(context, 30, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_30(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_32(expr, context, element, ...) expr(context, 31, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_31(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_33(expr, context, element, ...) expr(context, 32, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_32(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_34(expr, context, element, ...) expr(context, 33, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_33(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_35(expr, context, element, ...) expr(context, 34, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_34(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_36(expr, context, element, ...) expr(context, 35, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_35(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_37(expr, context, element, ...) expr(context, 36, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_36(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_38(expr, context, element, ...) expr(context, 37, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_37(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_39(expr, context, element, ...) expr(context, 38, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_38(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_40(expr, context, element, ...) expr(context, 39, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_39(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_41(expr, context, element, ...) expr(context, 40, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_40(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_42(expr, context, element, ...) expr(context, 41, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_41(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_43(expr, context, element, ...) expr(context, 42, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_42(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_44(expr, context, element, ...) expr(context, 43, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_43(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_45(expr, context, element, ...) expr(context, 44, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_44(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_46(expr, context, element, ...) expr(context, 45, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_45(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_47(expr, context, element, ...) expr(context, 46, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_46(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_48(expr, context, element, ...) expr(context, 47, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_47(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_49(expr, context, element, ...) expr(context, 48, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_48(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_50(expr, context, element, ...) expr(context, 49, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_49(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_51(expr, context, element, ...) expr(context, 50, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_50(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_52(expr, context, element, ...) expr(context, 51, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_51(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_53(expr, context, element, ...) expr(context, 52, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_52(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_54(expr, context, element, ...) expr(context, 53, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_53(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_55(expr, context, element, ...) expr(context, 54, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_54(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_56(expr, context, element, ...) expr(context, 55, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_55(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_57(expr, context, element, ...) expr(context, 56, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_56(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_58(expr, context, element, ...) expr(context, 57, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_57(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_59(expr, context, element, ...) expr(context, 58, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_58(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_60(expr, context, element, ...) expr(context, 59, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_59(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_61(expr, context, element, ...) expr(context, 60, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_60(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_62(expr, context, element, ...) expr(context, 61, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_61(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_63(expr, context, element, ...) expr(context, 62, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_62(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_64(expr, context, element, ...) expr(context, 63, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_63(expr, context, __VA_ARGS__)) + +#if defined(__GNUC__) || defined(__clang__) +# define PREPROCESSOR_FOR(expr, context, ...) \ + PREPROCESSOR_ARGS_N_IMPL(__VA_ARGS__, \ + PREPROCESSOR_FOR_IMPL_63, PREPROCESSOR_FOR_IMPL_62, PREPROCESSOR_FOR_IMPL_61, PREPROCESSOR_FOR_IMPL_60, \ + PREPROCESSOR_FOR_IMPL_59, PREPROCESSOR_FOR_IMPL_58, PREPROCESSOR_FOR_IMPL_57, PREPROCESSOR_FOR_IMPL_56, PREPROCESSOR_FOR_IMPL_55, PREPROCESSOR_FOR_IMPL_54, PREPROCESSOR_FOR_IMPL_53, PREPROCESSOR_FOR_IMPL_52, PREPROCESSOR_FOR_IMPL_51, PREPROCESSOR_FOR_IMPL_50, \ + PREPROCESSOR_FOR_IMPL_49, PREPROCESSOR_FOR_IMPL_48, PREPROCESSOR_FOR_IMPL_47, PREPROCESSOR_FOR_IMPL_46, PREPROCESSOR_FOR_IMPL_45, PREPROCESSOR_FOR_IMPL_44, PREPROCESSOR_FOR_IMPL_43, PREPROCESSOR_FOR_IMPL_42, PREPROCESSOR_FOR_IMPL_41, PREPROCESSOR_FOR_IMPL_40, \ + PREPROCESSOR_FOR_IMPL_39, PREPROCESSOR_FOR_IMPL_38, PREPROCESSOR_FOR_IMPL_37, PREPROCESSOR_FOR_IMPL_36, PREPROCESSOR_FOR_IMPL_35, PREPROCESSOR_FOR_IMPL_34, PREPROCESSOR_FOR_IMPL_33, PREPROCESSOR_FOR_IMPL_32, PREPROCESSOR_FOR_IMPL_31, PREPROCESSOR_FOR_IMPL_30, \ + PREPROCESSOR_FOR_IMPL_29, PREPROCESSOR_FOR_IMPL_28, PREPROCESSOR_FOR_IMPL_27, PREPROCESSOR_FOR_IMPL_26, PREPROCESSOR_FOR_IMPL_25, PREPROCESSOR_FOR_IMPL_24, PREPROCESSOR_FOR_IMPL_23, PREPROCESSOR_FOR_IMPL_22, PREPROCESSOR_FOR_IMPL_21, PREPROCESSOR_FOR_IMPL_20, \ + PREPROCESSOR_FOR_IMPL_19, PREPROCESSOR_FOR_IMPL_18, PREPROCESSOR_FOR_IMPL_17, PREPROCESSOR_FOR_IMPL_16, PREPROCESSOR_FOR_IMPL_15, PREPROCESSOR_FOR_IMPL_14, PREPROCESSOR_FOR_IMPL_13, PREPROCESSOR_FOR_IMPL_12, PREPROCESSOR_FOR_IMPL_11, PREPROCESSOR_FOR_IMPL_10, \ + PREPROCESSOR_FOR_IMPL_9, PREPROCESSOR_FOR_IMPL_8, PREPROCESSOR_FOR_IMPL_7, PREPROCESSOR_FOR_IMPL_6, PREPROCESSOR_FOR_IMPL_5, PREPROCESSOR_FOR_IMPL_4, PREPROCESSOR_FOR_IMPL_3, PREPROCESSOR_FOR_IMPL_2, PREPROCESSOR_FOR_IMPL_1, \ + PREPROCESSOR_FOR_IMPL_0)(expr, context, __VA_ARGS__) +#elif defined(_MSC_VER) && !defined(__clang__) +# define PREPROCESSOR_FOR_IMPL_COUNT(count) \ + PREPROCESSOR_CONCAT(PREPROCESSOR_FOR_IMPL_, count) +# define PREPROCESSOR_FOR_IMPL_EXPR(...) \ + PREPROCESSOR_FOR_IMPL_COUNT(PREPROCESSOR_ARGS_COUNT(__VA_ARGS__)) +# define PREPROCESSOR_FOR_EXPAND(expr, args) expr ## args +# define PREPROCESSOR_FOR(expr, context, ...) \ + PREPROCESSOR_FOR_EXPAND(PREPROCESSOR_FOR_IMPL_EXPR(__VA_ARGS__), (expr, context, __VA_ARGS__)) +#else +# error "Unkwnown preprocessor implementation for for." +#endif + #ifdef __cplusplus } #endif diff --git a/source/tests/preprocessor_test/source/preprocessor_test.cpp b/source/tests/preprocessor_test/source/preprocessor_test.cpp index 442f74de8..b6483c3dd 100644 --- a/source/tests/preprocessor_test/source/preprocessor_test.cpp +++ b/source/tests/preprocessor_test/source/preprocessor_test.cpp @@ -22,8 +22,6 @@ #include -#include - class preprocessor_test : public testing::Test { public: @@ -114,14 +112,15 @@ TEST_F(preprocessor_test, empty) { const char empty_str[] = ""; - EXPECT_EQ((int)0, (int)strcmp(empty_str, PREPROCESSOR_STRINGIFY_OR_EMPTY(PREPROCESSOR_EMPTY_SYMBOL()))); + EXPECT_STREQ("", PREPROCESSOR_STRINGIFY_OR_EMPTY(PREPROCESSOR_EMPTY_SYMBOL())); + EXPECT_STREQ(empty_str, PREPROCESSOR_STRINGIFY_OR_EMPTY(PREPROCESSOR_EMPTY_SYMBOL())); PREPROCESSOR_EMPTY_EXPANSION(this must compile) PREPROCESSOR_EMPTY_EXPANSION_VARIADIC(this, must, compile) } -TEST_F(preprocessor_test, for) +TEST_F(preprocessor_test, foreach) { #define PREPROCESSOR_TEST_FOR_EACH_STR_SIZE 0x04 @@ -137,7 +136,22 @@ TEST_F(preprocessor_test, for) #undef PREPROCESSOR_TEST_FOR_EACH_STR_SIZE - EXPECT_EQ((int)0, (int)strcmp(for_each_str, "abc")); + EXPECT_STREQ(for_each_str, "abc"); +} + +TEST_F(preprocessor_test, for) +{ +#define PREPROCESSOR_TEST_FOR(context, iterator, element) \ + context \ + PREPROCESSOR_STRINGIFY(iterator) \ + element \ + "-" + + const char for_str[] = PREPROCESSOR_FOR(PREPROCESSOR_TEST_FOR, "yeet", "a", "b", "c", "d", "e", "f"); + +#undef PREPROCESSOR_TEST_FOR + + EXPECT_STREQ(for_str, "yeet0a-yeet1b-yeet2c-yeet3d-yeet4e-yeet5f-"); } TEST_F(preprocessor_test, if) @@ -155,7 +169,7 @@ TEST_F(preprocessor_test, serial) const char serial_id_b[] = PREPROCESSOR_STRINGIFY(PREPROCESSOR_SERIAL_ID(PREPROCESSOR_TEST_SERIAL_TAG)); - EXPECT_NE((int)0, (int)strcmp(serial_id_a, serial_id_b)); + EXPECT_STRNE(serial_id_a, serial_id_b); #undef PREPROCESSOR_TEST_SERIAL_TAG } @@ -166,9 +180,9 @@ TEST_F(preprocessor_test, stringify) const char stringify_tag[] = "abc"; - EXPECT_EQ((int)0, (int)strcmp(stringify_tag, PREPROCESSOR_STRINGIFY(PREPROCESSOR_TEST_STRINGIFY_TAG))); + EXPECT_STREQ(stringify_tag, PREPROCESSOR_STRINGIFY(PREPROCESSOR_TEST_STRINGIFY_TAG)); - EXPECT_EQ((int)0, (int)strcmp(stringify_tag, PREPROCESSOR_STRINGIFY_VARIADIC(a, b, c))); + EXPECT_STREQ(stringify_tag, PREPROCESSOR_STRINGIFY_VARIADIC(a, b, c)); #undef PREPROCESSOR_TEST_STRINGIFY_TAG } From 03cc14718f3e22b05eabefa736bd758af36af1be Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 5 Oct 2023 22:41:52 +0200 Subject: [PATCH 022/615] New extension / plugin API working properly. --- .../include/plugin/plugin_interface.hpp | 2 +- .../preprocessor/cmake/preprocessor_for.cmake | 4 +- .../cmake/preprocessor_for_body.h.in | 16 +- .../include/preprocessor/preprocessor_for.h | 140 +++++++++--------- .../source/metacall_sandbox_plugin_test.cpp | 23 +++ 5 files changed, 104 insertions(+), 81 deletions(-) diff --git a/source/plugin/include/plugin/plugin_interface.hpp b/source/plugin/include/plugin/plugin_interface.hpp index 83d41bba6..db8e2b1ee 100644 --- a/source/plugin/include/plugin/plugin_interface.hpp +++ b/source/plugin/include/plugin/plugin_interface.hpp @@ -74,7 +74,7 @@ if (metacall_value_id(args[iterator]) != value) \ { \ std::stringstream ss; \ - ss << error ". The parameter number " PREPROCESSOR_STRINGIFY(PREPROCESSOR_ARGS_COUNT(iterator)) " requires a value of type " metacall_value_id_name(value) ", received: " << metacall_value_type_name(args[iterator]); \ + ss << error ". The parameter number " PREPROCESSOR_STRINGIFY(PREPROCESSOR_ARGS_COUNT(iterator)) " requires a value of type " << metacall_value_id_name(value) << ", received: " << metacall_value_type_name(args[iterator]); \ std::string error_msg = ss.str(); \ EXTENSION_FUNCTION_THROW(error_msg.c_str()); \ } diff --git a/source/preprocessor/cmake/preprocessor_for.cmake b/source/preprocessor/cmake/preprocessor_for.cmake index 9355ef4d5..b09ad63ea 100644 --- a/source/preprocessor/cmake/preprocessor_for.cmake +++ b/source/preprocessor/cmake/preprocessor_for.cmake @@ -81,9 +81,9 @@ function(preprocessor_for_generate _for_size) math(EXPR prev "${iterator} - 1") - set(PREPROCESSOR_FOR_IMPL_BODY "${PREPROCESSOR_FOR_IMPL_BODY}#define PREPROCESSOR_FOR_IMPL_${iterator}(expr, context, element, ...) expr(context, ${prev}, element)") + set(PREPROCESSOR_FOR_IMPL_BODY "${PREPROCESSOR_FOR_IMPL_BODY}#define PREPROCESSOR_FOR_IMPL_${iterator}(expr, context, iterator, element, ...) expr(context, iterator, element)") - set(PREPROCESSOR_FOR_IMPL_BODY "${PREPROCESSOR_FOR_IMPL_BODY} PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_${prev}(expr, context, __VA_ARGS__))\n") + set(PREPROCESSOR_FOR_IMPL_BODY "${PREPROCESSOR_FOR_IMPL_BODY} PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_${prev}(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__))\n") endforeach() diff --git a/source/preprocessor/cmake/preprocessor_for_body.h.in b/source/preprocessor/cmake/preprocessor_for_body.h.in index 2b428394f..85eced21e 100644 --- a/source/preprocessor/cmake/preprocessor_for_body.h.in +++ b/source/preprocessor/cmake/preprocessor_for_body.h.in @@ -42,22 +42,22 @@ */ #define PREPROCESSOR_FOR_EVAL(expr) expr -#define PREPROCESSOR_FOR_IMPL_0(expr, context, ...) -#define PREPROCESSOR_FOR_IMPL_1(expr, context, element, ...) expr(context, 0, element) +#define PREPROCESSOR_FOR_IMPL_0(expr, context, iterator, ...) +#define PREPROCESSOR_FOR_IMPL_1(expr, context, iterator, element, ...) expr(context, iterator, element) #if (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ (defined(__STDC__) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) -# define PREPROCESSOR_FOR_IMPL_2(expr, context, element, ...) \ - expr(context, 1, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_1(expr, context, __VA_ARGS__, ~)) +# define PREPROCESSOR_FOR_IMPL_2(expr, context, iterator, element, ...) \ + expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_1(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__, ~)) #else -# define PREPROCESSOR_FOR_IMPL_2(expr, context, element, ...) \ - expr(context, 1, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_1(expr, context, __VA_ARGS__)) +# define PREPROCESSOR_FOR_IMPL_2(expr, context, iterator, element, ...) \ + expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_1(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) #endif @PREPROCESSOR_FOR_IMPL_BODY@ #if defined(__GNUC__) || defined(__clang__) # define PREPROCESSOR_FOR(expr, context, ...) \ PREPROCESSOR_ARGS_N_IMPL(__VA_ARGS__, \ @PREPROCESSOR_FOR_IMPL_GNUC_BODY@\ - PREPROCESSOR_FOR_IMPL_0)(expr, context, __VA_ARGS__) + PREPROCESSOR_FOR_IMPL_0)(expr, context, 0, __VA_ARGS__) #elif defined(_MSC_VER) && !defined(__clang__) # define PREPROCESSOR_FOR_IMPL_COUNT(count) \ PREPROCESSOR_CONCAT(PREPROCESSOR_FOR_IMPL_, count) @@ -65,7 +65,7 @@ PREPROCESSOR_FOR_IMPL_COUNT(PREPROCESSOR_ARGS_COUNT(__VA_ARGS__)) # define PREPROCESSOR_FOR_EXPAND(expr, args) expr ## args # define PREPROCESSOR_FOR(expr, context, ...) \ - PREPROCESSOR_FOR_EXPAND(PREPROCESSOR_FOR_IMPL_EXPR(__VA_ARGS__), (expr, context, __VA_ARGS__)) + PREPROCESSOR_FOR_EXPAND(PREPROCESSOR_FOR_IMPL_EXPR(__VA_ARGS__), (expr, context, 0, __VA_ARGS__)) #else # error "Unkwnown preprocessor implementation for for." #endif diff --git a/source/preprocessor/include/preprocessor/preprocessor_for.h b/source/preprocessor/include/preprocessor/preprocessor_for.h index 98fe25ff1..3df40de63 100644 --- a/source/preprocessor/include/preprocessor/preprocessor_for.h +++ b/source/preprocessor/include/preprocessor/preprocessor_for.h @@ -144,78 +144,78 @@ extern "C" { */ #define PREPROCESSOR_FOR_EVAL(expr) expr -#define PREPROCESSOR_FOR_IMPL_0(expr, context, ...) -#define PREPROCESSOR_FOR_IMPL_1(expr, context, element, ...) expr(context, 0, element) +#define PREPROCESSOR_FOR_IMPL_0(expr, context, iterator, ...) +#define PREPROCESSOR_FOR_IMPL_1(expr, context, iterator, element, ...) expr(context, iterator, element) #if (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ (defined(__STDC__) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) -# define PREPROCESSOR_FOR_IMPL_2(expr, context, element, ...) \ - expr(context, 1, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_1(expr, context, __VA_ARGS__, ~)) +# define PREPROCESSOR_FOR_IMPL_2(expr, context, iterator, element, ...) \ + expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_1(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__, ~)) #else -# define PREPROCESSOR_FOR_IMPL_2(expr, context, element, ...) \ - expr(context, 1, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_1(expr, context, __VA_ARGS__)) +# define PREPROCESSOR_FOR_IMPL_2(expr, context, iterator, element, ...) \ + expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_1(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) #endif -#define PREPROCESSOR_FOR_IMPL_3(expr, context, element, ...) expr(context, 2, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_2(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_4(expr, context, element, ...) expr(context, 3, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_3(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_5(expr, context, element, ...) expr(context, 4, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_4(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_6(expr, context, element, ...) expr(context, 5, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_5(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_7(expr, context, element, ...) expr(context, 6, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_6(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_8(expr, context, element, ...) expr(context, 7, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_7(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_9(expr, context, element, ...) expr(context, 8, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_8(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_10(expr, context, element, ...) expr(context, 9, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_9(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_11(expr, context, element, ...) expr(context, 10, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_10(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_12(expr, context, element, ...) expr(context, 11, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_11(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_13(expr, context, element, ...) expr(context, 12, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_12(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_14(expr, context, element, ...) expr(context, 13, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_13(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_15(expr, context, element, ...) expr(context, 14, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_14(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_16(expr, context, element, ...) expr(context, 15, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_15(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_17(expr, context, element, ...) expr(context, 16, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_16(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_18(expr, context, element, ...) expr(context, 17, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_17(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_19(expr, context, element, ...) expr(context, 18, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_18(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_20(expr, context, element, ...) expr(context, 19, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_19(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_21(expr, context, element, ...) expr(context, 20, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_20(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_22(expr, context, element, ...) expr(context, 21, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_21(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_23(expr, context, element, ...) expr(context, 22, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_22(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_24(expr, context, element, ...) expr(context, 23, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_23(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_25(expr, context, element, ...) expr(context, 24, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_24(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_26(expr, context, element, ...) expr(context, 25, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_25(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_27(expr, context, element, ...) expr(context, 26, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_26(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_28(expr, context, element, ...) expr(context, 27, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_27(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_29(expr, context, element, ...) expr(context, 28, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_28(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_30(expr, context, element, ...) expr(context, 29, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_29(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_31(expr, context, element, ...) expr(context, 30, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_30(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_32(expr, context, element, ...) expr(context, 31, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_31(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_33(expr, context, element, ...) expr(context, 32, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_32(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_34(expr, context, element, ...) expr(context, 33, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_33(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_35(expr, context, element, ...) expr(context, 34, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_34(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_36(expr, context, element, ...) expr(context, 35, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_35(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_37(expr, context, element, ...) expr(context, 36, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_36(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_38(expr, context, element, ...) expr(context, 37, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_37(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_39(expr, context, element, ...) expr(context, 38, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_38(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_40(expr, context, element, ...) expr(context, 39, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_39(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_41(expr, context, element, ...) expr(context, 40, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_40(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_42(expr, context, element, ...) expr(context, 41, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_41(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_43(expr, context, element, ...) expr(context, 42, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_42(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_44(expr, context, element, ...) expr(context, 43, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_43(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_45(expr, context, element, ...) expr(context, 44, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_44(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_46(expr, context, element, ...) expr(context, 45, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_45(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_47(expr, context, element, ...) expr(context, 46, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_46(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_48(expr, context, element, ...) expr(context, 47, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_47(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_49(expr, context, element, ...) expr(context, 48, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_48(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_50(expr, context, element, ...) expr(context, 49, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_49(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_51(expr, context, element, ...) expr(context, 50, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_50(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_52(expr, context, element, ...) expr(context, 51, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_51(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_53(expr, context, element, ...) expr(context, 52, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_52(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_54(expr, context, element, ...) expr(context, 53, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_53(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_55(expr, context, element, ...) expr(context, 54, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_54(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_56(expr, context, element, ...) expr(context, 55, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_55(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_57(expr, context, element, ...) expr(context, 56, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_56(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_58(expr, context, element, ...) expr(context, 57, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_57(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_59(expr, context, element, ...) expr(context, 58, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_58(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_60(expr, context, element, ...) expr(context, 59, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_59(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_61(expr, context, element, ...) expr(context, 60, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_60(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_62(expr, context, element, ...) expr(context, 61, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_61(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_63(expr, context, element, ...) expr(context, 62, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_62(expr, context, __VA_ARGS__)) -#define PREPROCESSOR_FOR_IMPL_64(expr, context, element, ...) expr(context, 63, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_63(expr, context, __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_3(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_2(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_4(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_3(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_5(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_4(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_6(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_5(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_7(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_6(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_8(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_7(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_9(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_8(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_10(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_9(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_11(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_10(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_12(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_11(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_13(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_12(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_14(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_13(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_15(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_14(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_16(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_15(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_17(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_16(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_18(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_17(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_19(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_18(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_20(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_19(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_21(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_20(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_22(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_21(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_23(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_22(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_24(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_23(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_25(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_24(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_26(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_25(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_27(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_26(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_28(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_27(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_29(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_28(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_30(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_29(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_31(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_30(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_32(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_31(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_33(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_32(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_34(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_33(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_35(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_34(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_36(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_35(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_37(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_36(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_38(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_37(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_39(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_38(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_40(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_39(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_41(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_40(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_42(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_41(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_43(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_42(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_44(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_43(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_45(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_44(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_46(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_45(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_47(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_46(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_48(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_47(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_49(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_48(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_50(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_49(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_51(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_50(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_52(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_51(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_53(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_52(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_54(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_53(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_55(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_54(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_56(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_55(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_57(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_56(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_58(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_57(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_59(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_58(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_60(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_59(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_61(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_60(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_62(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_61(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_63(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_62(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) +#define PREPROCESSOR_FOR_IMPL_64(expr, context, iterator, element, ...) expr(context, iterator, element) PREPROCESSOR_FOR_EVAL(PREPROCESSOR_FOR_IMPL_63(expr, context, PREPROCESSOR_INCREMENT(iterator), __VA_ARGS__)) #if defined(__GNUC__) || defined(__clang__) # define PREPROCESSOR_FOR(expr, context, ...) \ @@ -227,7 +227,7 @@ extern "C" { PREPROCESSOR_FOR_IMPL_29, PREPROCESSOR_FOR_IMPL_28, PREPROCESSOR_FOR_IMPL_27, PREPROCESSOR_FOR_IMPL_26, PREPROCESSOR_FOR_IMPL_25, PREPROCESSOR_FOR_IMPL_24, PREPROCESSOR_FOR_IMPL_23, PREPROCESSOR_FOR_IMPL_22, PREPROCESSOR_FOR_IMPL_21, PREPROCESSOR_FOR_IMPL_20, \ PREPROCESSOR_FOR_IMPL_19, PREPROCESSOR_FOR_IMPL_18, PREPROCESSOR_FOR_IMPL_17, PREPROCESSOR_FOR_IMPL_16, PREPROCESSOR_FOR_IMPL_15, PREPROCESSOR_FOR_IMPL_14, PREPROCESSOR_FOR_IMPL_13, PREPROCESSOR_FOR_IMPL_12, PREPROCESSOR_FOR_IMPL_11, PREPROCESSOR_FOR_IMPL_10, \ PREPROCESSOR_FOR_IMPL_9, PREPROCESSOR_FOR_IMPL_8, PREPROCESSOR_FOR_IMPL_7, PREPROCESSOR_FOR_IMPL_6, PREPROCESSOR_FOR_IMPL_5, PREPROCESSOR_FOR_IMPL_4, PREPROCESSOR_FOR_IMPL_3, PREPROCESSOR_FOR_IMPL_2, PREPROCESSOR_FOR_IMPL_1, \ - PREPROCESSOR_FOR_IMPL_0)(expr, context, __VA_ARGS__) + PREPROCESSOR_FOR_IMPL_0)(expr, context, 0, __VA_ARGS__) #elif defined(_MSC_VER) && !defined(__clang__) # define PREPROCESSOR_FOR_IMPL_COUNT(count) \ PREPROCESSOR_CONCAT(PREPROCESSOR_FOR_IMPL_, count) @@ -235,7 +235,7 @@ extern "C" { PREPROCESSOR_FOR_IMPL_COUNT(PREPROCESSOR_ARGS_COUNT(__VA_ARGS__)) # define PREPROCESSOR_FOR_EXPAND(expr, args) expr ## args # define PREPROCESSOR_FOR(expr, context, ...) \ - PREPROCESSOR_FOR_EXPAND(PREPROCESSOR_FOR_IMPL_EXPR(__VA_ARGS__), (expr, context, __VA_ARGS__)) + PREPROCESSOR_FOR_EXPAND(PREPROCESSOR_FOR_IMPL_EXPR(__VA_ARGS__), (expr, context, 0, __VA_ARGS__)) #else # error "Unkwnown preprocessor implementation for for." #endif diff --git a/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp b/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp index 9e075cd3b..ffb4e7dfa 100644 --- a/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp +++ b/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp @@ -83,5 +83,28 @@ TEST_F(metacall_sandbox_plugin_test, DefaultConstructor) metacall_value_destroy(args[0]); } + /* Testing invalid number of parameters */ + { + void *ret = metacallhv_s(handle, "sandbox_destroy", metacall_null_args, 0); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((enum metacall_value_id)metacall_value_id(ret), (enum metacall_value_id)METACALL_THROWABLE); + + metacall_value_destroy(ret); + } + + /* Testing correct number of parameters but invalid type */ + { + void *args[1] = { metacall_value_create_long(2343) }; + + void *ret = metacallhv_s(handle, "sandbox_destroy", args, 1); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((enum metacall_value_id)metacall_value_id(ret), (enum metacall_value_id)METACALL_THROWABLE); + + metacall_value_destroy(ret); + metacall_value_destroy(args[0]); + } + EXPECT_EQ((int)0, (int)metacall_destroy()); } From 67a87fa2c3ca34e555f77d158d71ad6c2267e06b Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Fri, 6 Oct 2023 00:25:16 +0200 Subject: [PATCH 023/615] Solved issues with for and foreach on preprocessor module when passing empty args, improved cli core plugin with new api. --- .../source/cli_core_plugin.cpp | 304 +++++++----------- .../preprocessor/cmake/preprocessor_for.cmake | 4 +- .../cmake/preprocessor_for_body.h.in | 24 +- .../cmake/preprocessor_for_headers.h.in | 1 + .../include/preprocessor/preprocessor_for.h | 48 +-- .../source/metacall_cli_core_plugin_test.cpp | 8 + .../source/preprocessor_test.cpp | 18 ++ 7 files changed, 198 insertions(+), 209 deletions(-) diff --git a/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp b/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp index ecc7d5757..3530f7575 100644 --- a/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp +++ b/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp @@ -22,121 +22,153 @@ #include -#include - #include #include +#include #include #include +#include + +/* Error messages */ +#define LOAD_ERROR "Failed to load a script" +#define INSPECT_ERROR "Failed to inspect MetaCall context" +#define EVAL_ERROR "Failed to evaluate the expression" +#define CALL_ERROR "Failed to call the function" +#define AWAIT_ERROR "Failed to await the function" +#define CLEAR_ERROR "Failed to clear the handle" void *load(size_t argc, void *args[], void *data) { - (void)argc; - (void)data; - - if (argc < 2) - { - return metacall_value_create_int(1); - } - - void **script_val = NULL; - char **scripts = NULL; + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(LOAD_ERROR, METACALL_STRING, METACALL_ARRAY); char *tag = metacall_value_to_string(args[0]); - if (tag == NULL) - { - return metacall_value_create_int(1); - } + size_t size = metacall_value_count(args[1]); + void **script_values = metacall_value_to_array(args[1]); + std::vector scripts; + std::vector scripts_cstr; - size_t size = 0; - if (metacall_value_id(args[1]) == METACALL_ARRAY) - { - size = metacall_value_count(args[1]); - script_val = metacall_value_to_array(args[1]); - if (script_val == NULL) - { - return metacall_value_create_int(1); - } - } - else - { - script_val = (args + 1); - size = argc - 1; - } - - scripts = (char **)malloc(sizeof(char *) * size); + scripts.reserve(size); + scripts_cstr.reserve(size); for (size_t i = 0; i < size; ++i) { - if (metacall_value_id(script_val[i]) == METACALL_STRING) + if (metacall_value_id(script_values[i]) != METACALL_STRING) { - scripts[i] = metacall_value_to_string(script_val[i]); - } - else - { - log_write("metacall", LOG_LEVEL_ERROR, "Calling load with wrong type of argument at argument position %" PRIuS ", expected %s, got %s", - i + 1, metacall_value_id_name(METACALL_STRING), metacall_value_type_name(script_val[i])); - return metacall_value_create_int(1); + std::stringstream ss; + + ss << LOAD_ERROR ", calling load with wrong type of argument at argument position " + << (i + 1) << ", expected " << metacall_value_id_name(METACALL_STRING) + << ", got " << metacall_value_type_name(script_values[i]); + + EXTENSION_FUNCTION_THROW(ss.str().c_str()); } - } - int ret = metacall_load_from_file(tag, const_cast(scripts), size, NULL); + scripts.push_back(metacall_value_to_string(script_values[i])); + scripts_cstr.push_back(const_cast(scripts[i].c_str())); + } - free(scripts); + int ret = metacall_load_from_file(tag, scripts_cstr.data(), size, NULL); return metacall_value_create_int(ret); } -void *eval(size_t argc, void *args[], void *data) +void *inspect(size_t argc, void *args[], void *data) { - (void)data; + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(INSPECT_ERROR); - if (argc != 2) - { - log_write("metacall", LOG_LEVEL_ERROR, "Calling eval with wrong number of arguments, expected 2 arguments, got %" PRIuS " arguments", argc); - return metacall_value_create_int(1); - } + size_t size = 0; - if (metacall_value_id(args[0]) == METACALL_STRING && metacall_value_id(args[1]) == METACALL_STRING) - { - char *tag = metacall_value_to_string(args[0]); - char *script = metacall_value_to_string(args[1]); + struct metacall_allocator_std_type std_ctx = { &std::malloc, &std::realloc, &std::free }; + void *allocator = metacall_allocator_create(METACALL_ALLOCATOR_STD, (void *)&std_ctx); - return metacall_value_create_int(metacall_load_from_memory(tag, script, strlen(script) + 1, NULL)); - } - else - { - log_write("metacall", LOG_LEVEL_ERROR, "Calling eval with wrong type of arguments, expected two %s, got %s and %s", - metacall_value_id_name(METACALL_STRING), metacall_value_type_name(args[0]), metacall_value_type_name(args[1])); - } + char *inspect_str = metacall_inspect(&size, allocator); + + void *inspect_value_str = metacall_value_create_string(inspect_str, size > 0 ? size - 1 : 0); + + metacall_allocator_free(allocator, inspect_str); + + metacall_allocator_destroy(allocator); - return metacall_value_create_int(1); + return inspect_value_str; } -void *await(size_t argc, void *args[], void *data) +void *eval(size_t argc, void *args[], void *data) { - (void)argc; - (void)data; + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(EVAL_ERROR, METACALL_STRING, METACALL_STRING); + + char *tag = metacall_value_to_string(args[0]); + char *script = metacall_value_to_string(args[1]); + size_t size = metacall_value_size(args[1]); + + return metacall_value_create_int(metacall_load_from_memory(tag, script, size, NULL)); +} - if (argc != 1) +void *call(size_t argc, void *args[], void *data) +{ + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(CALL_ERROR, METACALL_STRING); + + /* Parse function call */ + std::string func_str = metacall_value_to_string(args[0]); + + if (func_str.find('(') == std::string::npos || func_str.find(')') == std::string::npos) { - log_write("metacall", LOG_LEVEL_ERROR, "Calling await with wrong number of arguments, expected 1 arguments, got %" PRIuS " arguments", argc); - return metacall_value_create_int(1); + std::stringstream ss; + + ss << CALL_ERROR ", calling function with malformed function call string: " << func_str; + + EXTENSION_FUNCTION_THROW(ss.str().c_str()); } - if (metacall_value_id(args[0]) != METACALL_STRING) + std::string::size_type idx = func_str.find_first_of('('); + std::string func_name = func_str.substr(0, idx); + + /* Convert arguments into an array */ + std::string func_args = "["; + func_args += func_str.substr(idx + 1, func_str.size() - (idx + 2)); + func_args += "]"; + + /* Check if function is loaded */ + const char *func_name_str = const_cast(func_name.c_str()); + void *func = metacall_function(func_name_str); + + if (func == NULL) { - log_write("metacall", LOG_LEVEL_ERROR, "Calling await with wrong type of arguments, expected %s, got %s", - metacall_value_id_name(METACALL_STRING), metacall_value_type_name(args[0])); - return metacall_value_create_int(1); + std::stringstream ss; + + ss << CALL_ERROR ", function '" << func_name << "' does not exist"; + + EXTENSION_FUNCTION_THROW(ss.str().c_str()); } + struct metacall_allocator_std_type std_ctx = { &std::malloc, &std::realloc, &std::free }; + void *allocator = metacall_allocator_create(METACALL_ALLOCATOR_STD, (void *)&std_ctx); + + void *result = metacallfs(func, func_args.c_str(), func_args.length() + 1, allocator); + + metacall_allocator_destroy(allocator); + + return result; +} + +void *await(size_t argc, void *args[], void *data) +{ + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(CALL_ERROR, METACALL_STRING); + /* Parse function call */ std::string func_str = metacall_value_to_string(args[0]); + if (func_str.find('(') == std::string::npos || func_str.find(')') == std::string::npos) { - log_write("metacall", LOG_LEVEL_ERROR, "'await' called with mangled function call string: %s", func_str.c_str()); - return metacall_value_create_int(1); + std::stringstream ss; + + ss << CALL_ERROR ", calling function with malformed function call string: " << func_str; + + EXTENSION_FUNCTION_THROW(ss.str().c_str()); } std::string::size_type idx = func_str.find_first_of('('); @@ -150,18 +182,21 @@ void *await(size_t argc, void *args[], void *data) /* Check if function is loaded */ const char *func_name_str = const_cast(func_name.c_str()); void *func = metacall_function(func_name_str); + if (func == NULL) { - log_write("metacall", LOG_LEVEL_ERROR, "Function %s does not exist", func_name_str); - return metacall_value_create_int(1); + std::stringstream ss; + + ss << CALL_ERROR ", function '" << func_name << "' does not exist"; + + EXTENSION_FUNCTION_THROW(ss.str().c_str()); } struct metacall_allocator_std_type std_ctx = { &std::malloc, &std::realloc, &std::free }; - void *allocator = metacall_allocator_create(METACALL_ALLOCATOR_STD, (void *)&std_ctx); - std::mutex await_mutex; /**< Mutex for blocking the process until await is resolved */ - std::condition_variable await_cond; /**< Condition to be fired once await method is resolved or rejected */ + std::mutex await_mutex; /* Mutex for blocking the process until await is resolved */ + std::condition_variable await_cond; /* Condition to be fired once await method is resolved or rejected */ std::unique_lock lock(await_mutex); @@ -204,75 +239,10 @@ void *await(size_t argc, void *args[], void *data) return fdata.v; } -void *call(size_t argc, void *args[], void *data) -{ - (void)argc; - (void)data; - - if (argc != 1) - { - log_write("metacall", LOG_LEVEL_ERROR, "Calling call with wrong number of arguments, expected 1 arguments, got %" PRIuS " arguments", argc); - return metacall_value_create_int(1); - } - - if (metacall_value_id(args[0]) != METACALL_STRING) - { - log_write("metacall", LOG_LEVEL_ERROR, "Calling call with wrong type of arguments, expected %s, got %s", - metacall_value_id_name(METACALL_STRING), metacall_value_type_name(args[0])); - return metacall_value_create_int(1); - } - - /* Parse function call */ - std::string func_str = metacall_value_to_string(args[0]); - if (func_str.find('(') == std::string::npos || func_str.find(')') == std::string::npos) - { - log_write("metacall", LOG_LEVEL_ERROR, "'call' called with mangled function call string: %s", func_str.c_str()); - return metacall_value_create_int(1); - } - - std::string::size_type idx = func_str.find_first_of('('); - std::string func_name = func_str.substr(0, idx); - - /* Convert arguments into an array */ - std::string func_args = "["; - func_args += func_str.substr(idx + 1, func_str.size() - (idx + 2)); - func_args += "]"; - - /* Check if function is loaded */ - const char *func_name_str = const_cast(func_name.c_str()); - void *func = metacall_function(func_name_str); - if (func == NULL) - { - log_write("metacall", LOG_LEVEL_ERROR, "Function %s does not exist", func_name_str); - return metacall_value_create_int(1); - } - - struct metacall_allocator_std_type std_ctx = { &std::malloc, &std::realloc, &std::free }; - - void *allocator = metacall_allocator_create(METACALL_ALLOCATOR_STD, (void *)&std_ctx); - - void *result = metacallfs(func, func_args.c_str(), func_args.length() + 1, allocator); - - metacall_allocator_destroy(allocator); - return result; -} - void *clear(size_t argc, void *args[], void *data) { - (void)data; - - if (argc != 2) - { - log_write("metacall", LOG_LEVEL_ERROR, "Calling call with wrong number of arguments, expected 2 arguments, got %" PRIuS " arguments", argc); - return metacall_value_create_int(1); - } - - if (metacall_value_id(args[0]) != METACALL_STRING && metacall_value_id(args[1]) != METACALL_STRING) - { - log_write("metacall", LOG_LEVEL_ERROR, "Calling clear with wrong type of arguments, expected two %s, got %s and %s", - metacall_value_id_name(METACALL_STRING), metacall_value_type_name(args[0]), metacall_value_type_name(args[1])); - return metacall_value_create_int(1); - } + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(CLEAR_ERROR, METACALL_STRING, METACALL_STRING); char *tag = metacall_value_to_string(args[0]); char *script = metacall_value_to_string(args[1]); @@ -281,50 +251,26 @@ void *clear(size_t argc, void *args[], void *data) if (handle == NULL) { - log_write("metacall", LOG_LEVEL_ERROR, "Handle %s not found in loader (%s)", script, tag); - return metacall_value_create_int(1); - } - - if (metacall_clear(handle) != 0) - { - return metacall_value_create_int(1); - } - - return metacall_value_create_int(0); -} + std::stringstream ss; -void *inspect(size_t argc, void *args[], void *data) -{ - (void)argc; - (void)args; - (void)data; + ss << CLEAR_ERROR ", handle '" << script << "' was not found in loader with tag: " << tag; - size_t size = 0; - - struct metacall_allocator_std_type std_ctx = { &std::malloc, &std::realloc, &std::free }; - void *allocator = metacall_allocator_create(METACALL_ALLOCATOR_STD, (void *)&std_ctx); - - char *inspect_str = metacall_inspect(&size, allocator); - - void *inspect_value_str = metacall_value_create_string(inspect_str, size > 0 ? size - 1 : 0); - - metacall_allocator_free(allocator, inspect_str); - - metacall_allocator_destroy(allocator); + EXTENSION_FUNCTION_THROW(ss.str().c_str()); + } - return inspect_value_str; + return metacall_value_create_int(metacall_clear(handle)); } int cli_core_plugin(void *loader, void *handle, void *context) { (void)handle; + EXTENSION_FUNCTION(METACALL_INT, load, METACALL_STRING, METACALL_ARRAY); EXTENSION_FUNCTION(METACALL_STRING, inspect); - EXTENSION_FUNCTION(METACALL_INT, clear, METACALL_STRING, METACALL_STRING); + EXTENSION_FUNCTION(METACALL_INT, eval, METACALL_STRING, METACALL_STRING); EXTENSION_FUNCTION(METACALL_PTR, call, METACALL_STRING); EXTENSION_FUNCTION(METACALL_PTR, await, METACALL_STRING); - EXTENSION_FUNCTION(METACALL_INT, eval, METACALL_STRING, METACALL_STRING); - EXTENSION_FUNCTION(METACALL_INT, load, METACALL_STRING, METACALL_ARRAY); + EXTENSION_FUNCTION(METACALL_INT, clear, METACALL_STRING, METACALL_STRING); return 0; } diff --git a/source/preprocessor/cmake/preprocessor_for.cmake b/source/preprocessor/cmake/preprocessor_for.cmake index b09ad63ea..44e41aa3c 100644 --- a/source/preprocessor/cmake/preprocessor_for.cmake +++ b/source/preprocessor/cmake/preprocessor_for.cmake @@ -67,7 +67,7 @@ function(preprocessor_for_generate _for_size) math(EXPR iterator_modulo "${iterator} % ${preprocessor_for_line_align}") if(${iterator_modulo} EQUAL 0) - set(PREPROCESSOR_FOR_EACH_IMPL_GNUC_BODY "${PREPROCESSOR_FOR_EACH_IMPL_GNUC_BODY}PREPROCESSOR_FOR_EACH_IMPL_${iterator}, \\\n\t\t") + set(PREPROCESSOR_FOR_EACH_IMPL_GNUC_BODY "${PREPROCESSOR_FOR_EACH_IMPL_GNUC_BODY}PREPROCESSOR_FOR_EACH_IMPL_${iterator}, \\\n\t\t\t") else() set(PREPROCESSOR_FOR_EACH_IMPL_GNUC_BODY "${PREPROCESSOR_FOR_EACH_IMPL_GNUC_BODY}PREPROCESSOR_FOR_EACH_IMPL_${iterator}, ") endif() @@ -97,7 +97,7 @@ function(preprocessor_for_generate _for_size) math(EXPR iterator_modulo "${iterator} % ${preprocessor_for_line_align}") if(${iterator_modulo} EQUAL 0) - set(PREPROCESSOR_FOR_IMPL_GNUC_BODY "${PREPROCESSOR_FOR_IMPL_GNUC_BODY}PREPROCESSOR_FOR_IMPL_${iterator}, \\\n\t\t") + set(PREPROCESSOR_FOR_IMPL_GNUC_BODY "${PREPROCESSOR_FOR_IMPL_GNUC_BODY}PREPROCESSOR_FOR_IMPL_${iterator}, \\\n\t\t\t") else() set(PREPROCESSOR_FOR_IMPL_GNUC_BODY "${PREPROCESSOR_FOR_IMPL_GNUC_BODY}PREPROCESSOR_FOR_IMPL_${iterator}, ") endif() diff --git a/source/preprocessor/cmake/preprocessor_for_body.h.in b/source/preprocessor/cmake/preprocessor_for_body.h.in index 85eced21e..57e9977b5 100644 --- a/source/preprocessor/cmake/preprocessor_for_body.h.in +++ b/source/preprocessor/cmake/preprocessor_for_body.h.in @@ -20,9 +20,11 @@ @PREPROCESSOR_FOR_EACH_IMPL_BODY@ #if defined(__GNUC__) || defined(__clang__) # define PREPROCESSOR_FOR_EACH(expr, ...) \ - PREPROCESSOR_ARGS_N_IMPL(__VA_ARGS__, \ - @PREPROCESSOR_FOR_EACH_IMPL_GNUC_BODY@\ - PREPROCESSOR_FOR_EACH_IMPL_0)(expr, __VA_ARGS__) + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + PREPROCESSOR_EMPTY_SYMBOL(), \ + PREPROCESSOR_ARGS_N_IMPL(__VA_ARGS__, \ + @PREPROCESSOR_FOR_EACH_IMPL_GNUC_BODY@\ + PREPROCESSOR_FOR_EACH_IMPL_0)(expr, __VA_ARGS__)) #elif defined(_MSC_VER) && !defined(__clang__) # define PREPROCESSOR_FOR_EACH_IMPL_COUNT(count) \ PREPROCESSOR_CONCAT(PREPROCESSOR_FOR_EACH_IMPL_, count) @@ -30,7 +32,9 @@ PREPROCESSOR_FOR_EACH_IMPL_COUNT(PREPROCESSOR_ARGS_COUNT(__VA_ARGS__)) # define PREPROCESSOR_FOR_EACH_EXPAND(expr, args) expr ## args # define PREPROCESSOR_FOR_EACH(expr, ...) \ - PREPROCESSOR_FOR_EACH_EXPAND(PREPROCESSOR_FOR_EACH_IMPL_EXPR(__VA_ARGS__), (expr, __VA_ARGS__)) + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + PREPROCESSOR_EMPTY_SYMBOL(), \ + PREPROCESSOR_FOR_EACH_EXPAND(PREPROCESSOR_FOR_EACH_IMPL_EXPR(__VA_ARGS__), (expr, __VA_ARGS__))) #else # error "Unkwnown preprocessor implementation for foreach." #endif @@ -55,9 +59,11 @@ @PREPROCESSOR_FOR_IMPL_BODY@ #if defined(__GNUC__) || defined(__clang__) # define PREPROCESSOR_FOR(expr, context, ...) \ - PREPROCESSOR_ARGS_N_IMPL(__VA_ARGS__, \ - @PREPROCESSOR_FOR_IMPL_GNUC_BODY@\ - PREPROCESSOR_FOR_IMPL_0)(expr, context, 0, __VA_ARGS__) + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + PREPROCESSOR_EMPTY_SYMBOL(), \ + PREPROCESSOR_ARGS_N_IMPL(__VA_ARGS__, \ + @PREPROCESSOR_FOR_IMPL_GNUC_BODY@\ + PREPROCESSOR_FOR_IMPL_0)(expr, context, 0, __VA_ARGS__)) #elif defined(_MSC_VER) && !defined(__clang__) # define PREPROCESSOR_FOR_IMPL_COUNT(count) \ PREPROCESSOR_CONCAT(PREPROCESSOR_FOR_IMPL_, count) @@ -65,7 +71,9 @@ PREPROCESSOR_FOR_IMPL_COUNT(PREPROCESSOR_ARGS_COUNT(__VA_ARGS__)) # define PREPROCESSOR_FOR_EXPAND(expr, args) expr ## args # define PREPROCESSOR_FOR(expr, context, ...) \ - PREPROCESSOR_FOR_EXPAND(PREPROCESSOR_FOR_IMPL_EXPR(__VA_ARGS__), (expr, context, 0, __VA_ARGS__)) + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + PREPROCESSOR_EMPTY_SYMBOL(), \ + PREPROCESSOR_FOR_EXPAND(PREPROCESSOR_FOR_IMPL_EXPR(__VA_ARGS__), (expr, context, 0, __VA_ARGS__))) #else # error "Unkwnown preprocessor implementation for for." #endif diff --git a/source/preprocessor/cmake/preprocessor_for_headers.h.in b/source/preprocessor/cmake/preprocessor_for_headers.h.in index 2257211b7..609fcf026 100644 --- a/source/preprocessor/cmake/preprocessor_for_headers.h.in +++ b/source/preprocessor/cmake/preprocessor_for_headers.h.in @@ -1,2 +1,3 @@ #include #include +#include diff --git a/source/preprocessor/include/preprocessor/preprocessor_for.h b/source/preprocessor/include/preprocessor/preprocessor_for.h index 3df40de63..0f2a566cc 100644 --- a/source/preprocessor/include/preprocessor/preprocessor_for.h +++ b/source/preprocessor/include/preprocessor/preprocessor_for.h @@ -116,15 +116,17 @@ extern "C" { #if defined(__GNUC__) || defined(__clang__) # define PREPROCESSOR_FOR_EACH(expr, ...) \ - PREPROCESSOR_ARGS_N_IMPL(__VA_ARGS__, \ - PREPROCESSOR_FOR_EACH_IMPL_63, PREPROCESSOR_FOR_EACH_IMPL_62, PREPROCESSOR_FOR_EACH_IMPL_61, PREPROCESSOR_FOR_EACH_IMPL_60, \ - PREPROCESSOR_FOR_EACH_IMPL_59, PREPROCESSOR_FOR_EACH_IMPL_58, PREPROCESSOR_FOR_EACH_IMPL_57, PREPROCESSOR_FOR_EACH_IMPL_56, PREPROCESSOR_FOR_EACH_IMPL_55, PREPROCESSOR_FOR_EACH_IMPL_54, PREPROCESSOR_FOR_EACH_IMPL_53, PREPROCESSOR_FOR_EACH_IMPL_52, PREPROCESSOR_FOR_EACH_IMPL_51, PREPROCESSOR_FOR_EACH_IMPL_50, \ - PREPROCESSOR_FOR_EACH_IMPL_49, PREPROCESSOR_FOR_EACH_IMPL_48, PREPROCESSOR_FOR_EACH_IMPL_47, PREPROCESSOR_FOR_EACH_IMPL_46, PREPROCESSOR_FOR_EACH_IMPL_45, PREPROCESSOR_FOR_EACH_IMPL_44, PREPROCESSOR_FOR_EACH_IMPL_43, PREPROCESSOR_FOR_EACH_IMPL_42, PREPROCESSOR_FOR_EACH_IMPL_41, PREPROCESSOR_FOR_EACH_IMPL_40, \ - PREPROCESSOR_FOR_EACH_IMPL_39, PREPROCESSOR_FOR_EACH_IMPL_38, PREPROCESSOR_FOR_EACH_IMPL_37, PREPROCESSOR_FOR_EACH_IMPL_36, PREPROCESSOR_FOR_EACH_IMPL_35, PREPROCESSOR_FOR_EACH_IMPL_34, PREPROCESSOR_FOR_EACH_IMPL_33, PREPROCESSOR_FOR_EACH_IMPL_32, PREPROCESSOR_FOR_EACH_IMPL_31, PREPROCESSOR_FOR_EACH_IMPL_30, \ - PREPROCESSOR_FOR_EACH_IMPL_29, PREPROCESSOR_FOR_EACH_IMPL_28, PREPROCESSOR_FOR_EACH_IMPL_27, PREPROCESSOR_FOR_EACH_IMPL_26, PREPROCESSOR_FOR_EACH_IMPL_25, PREPROCESSOR_FOR_EACH_IMPL_24, PREPROCESSOR_FOR_EACH_IMPL_23, PREPROCESSOR_FOR_EACH_IMPL_22, PREPROCESSOR_FOR_EACH_IMPL_21, PREPROCESSOR_FOR_EACH_IMPL_20, \ - PREPROCESSOR_FOR_EACH_IMPL_19, PREPROCESSOR_FOR_EACH_IMPL_18, PREPROCESSOR_FOR_EACH_IMPL_17, PREPROCESSOR_FOR_EACH_IMPL_16, PREPROCESSOR_FOR_EACH_IMPL_15, PREPROCESSOR_FOR_EACH_IMPL_14, PREPROCESSOR_FOR_EACH_IMPL_13, PREPROCESSOR_FOR_EACH_IMPL_12, PREPROCESSOR_FOR_EACH_IMPL_11, PREPROCESSOR_FOR_EACH_IMPL_10, \ - PREPROCESSOR_FOR_EACH_IMPL_9, PREPROCESSOR_FOR_EACH_IMPL_8, PREPROCESSOR_FOR_EACH_IMPL_7, PREPROCESSOR_FOR_EACH_IMPL_6, PREPROCESSOR_FOR_EACH_IMPL_5, PREPROCESSOR_FOR_EACH_IMPL_4, PREPROCESSOR_FOR_EACH_IMPL_3, PREPROCESSOR_FOR_EACH_IMPL_2, PREPROCESSOR_FOR_EACH_IMPL_1, \ - PREPROCESSOR_FOR_EACH_IMPL_0)(expr, __VA_ARGS__) + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + PREPROCESSOR_EMPTY_SYMBOL(), \ + PREPROCESSOR_ARGS_N_IMPL(__VA_ARGS__, \ + PREPROCESSOR_FOR_EACH_IMPL_63, PREPROCESSOR_FOR_EACH_IMPL_62, PREPROCESSOR_FOR_EACH_IMPL_61, PREPROCESSOR_FOR_EACH_IMPL_60, \ + PREPROCESSOR_FOR_EACH_IMPL_59, PREPROCESSOR_FOR_EACH_IMPL_58, PREPROCESSOR_FOR_EACH_IMPL_57, PREPROCESSOR_FOR_EACH_IMPL_56, PREPROCESSOR_FOR_EACH_IMPL_55, PREPROCESSOR_FOR_EACH_IMPL_54, PREPROCESSOR_FOR_EACH_IMPL_53, PREPROCESSOR_FOR_EACH_IMPL_52, PREPROCESSOR_FOR_EACH_IMPL_51, PREPROCESSOR_FOR_EACH_IMPL_50, \ + PREPROCESSOR_FOR_EACH_IMPL_49, PREPROCESSOR_FOR_EACH_IMPL_48, PREPROCESSOR_FOR_EACH_IMPL_47, PREPROCESSOR_FOR_EACH_IMPL_46, PREPROCESSOR_FOR_EACH_IMPL_45, PREPROCESSOR_FOR_EACH_IMPL_44, PREPROCESSOR_FOR_EACH_IMPL_43, PREPROCESSOR_FOR_EACH_IMPL_42, PREPROCESSOR_FOR_EACH_IMPL_41, PREPROCESSOR_FOR_EACH_IMPL_40, \ + PREPROCESSOR_FOR_EACH_IMPL_39, PREPROCESSOR_FOR_EACH_IMPL_38, PREPROCESSOR_FOR_EACH_IMPL_37, PREPROCESSOR_FOR_EACH_IMPL_36, PREPROCESSOR_FOR_EACH_IMPL_35, PREPROCESSOR_FOR_EACH_IMPL_34, PREPROCESSOR_FOR_EACH_IMPL_33, PREPROCESSOR_FOR_EACH_IMPL_32, PREPROCESSOR_FOR_EACH_IMPL_31, PREPROCESSOR_FOR_EACH_IMPL_30, \ + PREPROCESSOR_FOR_EACH_IMPL_29, PREPROCESSOR_FOR_EACH_IMPL_28, PREPROCESSOR_FOR_EACH_IMPL_27, PREPROCESSOR_FOR_EACH_IMPL_26, PREPROCESSOR_FOR_EACH_IMPL_25, PREPROCESSOR_FOR_EACH_IMPL_24, PREPROCESSOR_FOR_EACH_IMPL_23, PREPROCESSOR_FOR_EACH_IMPL_22, PREPROCESSOR_FOR_EACH_IMPL_21, PREPROCESSOR_FOR_EACH_IMPL_20, \ + PREPROCESSOR_FOR_EACH_IMPL_19, PREPROCESSOR_FOR_EACH_IMPL_18, PREPROCESSOR_FOR_EACH_IMPL_17, PREPROCESSOR_FOR_EACH_IMPL_16, PREPROCESSOR_FOR_EACH_IMPL_15, PREPROCESSOR_FOR_EACH_IMPL_14, PREPROCESSOR_FOR_EACH_IMPL_13, PREPROCESSOR_FOR_EACH_IMPL_12, PREPROCESSOR_FOR_EACH_IMPL_11, PREPROCESSOR_FOR_EACH_IMPL_10, \ + PREPROCESSOR_FOR_EACH_IMPL_9, PREPROCESSOR_FOR_EACH_IMPL_8, PREPROCESSOR_FOR_EACH_IMPL_7, PREPROCESSOR_FOR_EACH_IMPL_6, PREPROCESSOR_FOR_EACH_IMPL_5, PREPROCESSOR_FOR_EACH_IMPL_4, PREPROCESSOR_FOR_EACH_IMPL_3, PREPROCESSOR_FOR_EACH_IMPL_2, PREPROCESSOR_FOR_EACH_IMPL_1, \ + PREPROCESSOR_FOR_EACH_IMPL_0)(expr, __VA_ARGS__)) #elif defined(_MSC_VER) && !defined(__clang__) # define PREPROCESSOR_FOR_EACH_IMPL_COUNT(count) \ PREPROCESSOR_CONCAT(PREPROCESSOR_FOR_EACH_IMPL_, count) @@ -132,7 +134,9 @@ extern "C" { PREPROCESSOR_FOR_EACH_IMPL_COUNT(PREPROCESSOR_ARGS_COUNT(__VA_ARGS__)) # define PREPROCESSOR_FOR_EACH_EXPAND(expr, args) expr ## args # define PREPROCESSOR_FOR_EACH(expr, ...) \ - PREPROCESSOR_FOR_EACH_EXPAND(PREPROCESSOR_FOR_EACH_IMPL_EXPR(__VA_ARGS__), (expr, __VA_ARGS__)) + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + PREPROCESSOR_EMPTY_SYMBOL(), \ + PREPROCESSOR_FOR_EACH_EXPAND(PREPROCESSOR_FOR_EACH_IMPL_EXPR(__VA_ARGS__), (expr, __VA_ARGS__))) #else # error "Unkwnown preprocessor implementation for foreach." #endif @@ -219,15 +223,17 @@ extern "C" { #if defined(__GNUC__) || defined(__clang__) # define PREPROCESSOR_FOR(expr, context, ...) \ - PREPROCESSOR_ARGS_N_IMPL(__VA_ARGS__, \ - PREPROCESSOR_FOR_IMPL_63, PREPROCESSOR_FOR_IMPL_62, PREPROCESSOR_FOR_IMPL_61, PREPROCESSOR_FOR_IMPL_60, \ - PREPROCESSOR_FOR_IMPL_59, PREPROCESSOR_FOR_IMPL_58, PREPROCESSOR_FOR_IMPL_57, PREPROCESSOR_FOR_IMPL_56, PREPROCESSOR_FOR_IMPL_55, PREPROCESSOR_FOR_IMPL_54, PREPROCESSOR_FOR_IMPL_53, PREPROCESSOR_FOR_IMPL_52, PREPROCESSOR_FOR_IMPL_51, PREPROCESSOR_FOR_IMPL_50, \ - PREPROCESSOR_FOR_IMPL_49, PREPROCESSOR_FOR_IMPL_48, PREPROCESSOR_FOR_IMPL_47, PREPROCESSOR_FOR_IMPL_46, PREPROCESSOR_FOR_IMPL_45, PREPROCESSOR_FOR_IMPL_44, PREPROCESSOR_FOR_IMPL_43, PREPROCESSOR_FOR_IMPL_42, PREPROCESSOR_FOR_IMPL_41, PREPROCESSOR_FOR_IMPL_40, \ - PREPROCESSOR_FOR_IMPL_39, PREPROCESSOR_FOR_IMPL_38, PREPROCESSOR_FOR_IMPL_37, PREPROCESSOR_FOR_IMPL_36, PREPROCESSOR_FOR_IMPL_35, PREPROCESSOR_FOR_IMPL_34, PREPROCESSOR_FOR_IMPL_33, PREPROCESSOR_FOR_IMPL_32, PREPROCESSOR_FOR_IMPL_31, PREPROCESSOR_FOR_IMPL_30, \ - PREPROCESSOR_FOR_IMPL_29, PREPROCESSOR_FOR_IMPL_28, PREPROCESSOR_FOR_IMPL_27, PREPROCESSOR_FOR_IMPL_26, PREPROCESSOR_FOR_IMPL_25, PREPROCESSOR_FOR_IMPL_24, PREPROCESSOR_FOR_IMPL_23, PREPROCESSOR_FOR_IMPL_22, PREPROCESSOR_FOR_IMPL_21, PREPROCESSOR_FOR_IMPL_20, \ - PREPROCESSOR_FOR_IMPL_19, PREPROCESSOR_FOR_IMPL_18, PREPROCESSOR_FOR_IMPL_17, PREPROCESSOR_FOR_IMPL_16, PREPROCESSOR_FOR_IMPL_15, PREPROCESSOR_FOR_IMPL_14, PREPROCESSOR_FOR_IMPL_13, PREPROCESSOR_FOR_IMPL_12, PREPROCESSOR_FOR_IMPL_11, PREPROCESSOR_FOR_IMPL_10, \ - PREPROCESSOR_FOR_IMPL_9, PREPROCESSOR_FOR_IMPL_8, PREPROCESSOR_FOR_IMPL_7, PREPROCESSOR_FOR_IMPL_6, PREPROCESSOR_FOR_IMPL_5, PREPROCESSOR_FOR_IMPL_4, PREPROCESSOR_FOR_IMPL_3, PREPROCESSOR_FOR_IMPL_2, PREPROCESSOR_FOR_IMPL_1, \ - PREPROCESSOR_FOR_IMPL_0)(expr, context, 0, __VA_ARGS__) + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + PREPROCESSOR_EMPTY_SYMBOL(), \ + PREPROCESSOR_ARGS_N_IMPL(__VA_ARGS__, \ + PREPROCESSOR_FOR_IMPL_63, PREPROCESSOR_FOR_IMPL_62, PREPROCESSOR_FOR_IMPL_61, PREPROCESSOR_FOR_IMPL_60, \ + PREPROCESSOR_FOR_IMPL_59, PREPROCESSOR_FOR_IMPL_58, PREPROCESSOR_FOR_IMPL_57, PREPROCESSOR_FOR_IMPL_56, PREPROCESSOR_FOR_IMPL_55, PREPROCESSOR_FOR_IMPL_54, PREPROCESSOR_FOR_IMPL_53, PREPROCESSOR_FOR_IMPL_52, PREPROCESSOR_FOR_IMPL_51, PREPROCESSOR_FOR_IMPL_50, \ + PREPROCESSOR_FOR_IMPL_49, PREPROCESSOR_FOR_IMPL_48, PREPROCESSOR_FOR_IMPL_47, PREPROCESSOR_FOR_IMPL_46, PREPROCESSOR_FOR_IMPL_45, PREPROCESSOR_FOR_IMPL_44, PREPROCESSOR_FOR_IMPL_43, PREPROCESSOR_FOR_IMPL_42, PREPROCESSOR_FOR_IMPL_41, PREPROCESSOR_FOR_IMPL_40, \ + PREPROCESSOR_FOR_IMPL_39, PREPROCESSOR_FOR_IMPL_38, PREPROCESSOR_FOR_IMPL_37, PREPROCESSOR_FOR_IMPL_36, PREPROCESSOR_FOR_IMPL_35, PREPROCESSOR_FOR_IMPL_34, PREPROCESSOR_FOR_IMPL_33, PREPROCESSOR_FOR_IMPL_32, PREPROCESSOR_FOR_IMPL_31, PREPROCESSOR_FOR_IMPL_30, \ + PREPROCESSOR_FOR_IMPL_29, PREPROCESSOR_FOR_IMPL_28, PREPROCESSOR_FOR_IMPL_27, PREPROCESSOR_FOR_IMPL_26, PREPROCESSOR_FOR_IMPL_25, PREPROCESSOR_FOR_IMPL_24, PREPROCESSOR_FOR_IMPL_23, PREPROCESSOR_FOR_IMPL_22, PREPROCESSOR_FOR_IMPL_21, PREPROCESSOR_FOR_IMPL_20, \ + PREPROCESSOR_FOR_IMPL_19, PREPROCESSOR_FOR_IMPL_18, PREPROCESSOR_FOR_IMPL_17, PREPROCESSOR_FOR_IMPL_16, PREPROCESSOR_FOR_IMPL_15, PREPROCESSOR_FOR_IMPL_14, PREPROCESSOR_FOR_IMPL_13, PREPROCESSOR_FOR_IMPL_12, PREPROCESSOR_FOR_IMPL_11, PREPROCESSOR_FOR_IMPL_10, \ + PREPROCESSOR_FOR_IMPL_9, PREPROCESSOR_FOR_IMPL_8, PREPROCESSOR_FOR_IMPL_7, PREPROCESSOR_FOR_IMPL_6, PREPROCESSOR_FOR_IMPL_5, PREPROCESSOR_FOR_IMPL_4, PREPROCESSOR_FOR_IMPL_3, PREPROCESSOR_FOR_IMPL_2, PREPROCESSOR_FOR_IMPL_1, \ + PREPROCESSOR_FOR_IMPL_0)(expr, context, 0, __VA_ARGS__)) #elif defined(_MSC_VER) && !defined(__clang__) # define PREPROCESSOR_FOR_IMPL_COUNT(count) \ PREPROCESSOR_CONCAT(PREPROCESSOR_FOR_IMPL_, count) @@ -235,7 +241,9 @@ extern "C" { PREPROCESSOR_FOR_IMPL_COUNT(PREPROCESSOR_ARGS_COUNT(__VA_ARGS__)) # define PREPROCESSOR_FOR_EXPAND(expr, args) expr ## args # define PREPROCESSOR_FOR(expr, context, ...) \ - PREPROCESSOR_FOR_EXPAND(PREPROCESSOR_FOR_IMPL_EXPR(__VA_ARGS__), (expr, context, 0, __VA_ARGS__)) + PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \ + PREPROCESSOR_EMPTY_SYMBOL(), \ + PREPROCESSOR_FOR_EXPAND(PREPROCESSOR_FOR_IMPL_EXPR(__VA_ARGS__), (expr, context, 0, __VA_ARGS__))) #else # error "Unkwnown preprocessor implementation for for." #endif diff --git a/source/tests/metacall_cli_core_plugin_test/source/metacall_cli_core_plugin_test.cpp b/source/tests/metacall_cli_core_plugin_test/source/metacall_cli_core_plugin_test.cpp index 6afd28504..fe57f5553 100644 --- a/source/tests/metacall_cli_core_plugin_test/source/metacall_cli_core_plugin_test.cpp +++ b/source/tests/metacall_cli_core_plugin_test/source/metacall_cli_core_plugin_test.cpp @@ -42,6 +42,7 @@ TEST_F(metacall_cli_core_plugin_test, DefaultConstructor) void *handle = NULL; EXPECT_EQ((int)0, (int)metacall_load_from_configuration(CLI_CORE_PLUGIN_PATH, &handle, allocator)); + /* Test load */ { void *args[2]; @@ -61,6 +62,7 @@ TEST_F(metacall_cli_core_plugin_test, DefaultConstructor) metacall_value_destroy(args[1]); } + /* Test load */ { void *args[2]; args[0] = metacall_value_create_string("node", 4); @@ -79,6 +81,7 @@ TEST_F(metacall_cli_core_plugin_test, DefaultConstructor) metacall_value_destroy(args[1]); } + /* Test eval */ { void *args[2]; @@ -97,6 +100,7 @@ TEST_F(metacall_cli_core_plugin_test, DefaultConstructor) metacall_value_destroy(args[1]); } + /* Test call */ { char func_call[] = "multiply(7, 3)"; void *args[] = { metacall_value_create_string(func_call, strlen(func_call)) }; @@ -122,6 +126,7 @@ TEST_F(metacall_cli_core_plugin_test, DefaultConstructor) metacall_value_destroy(args[0]); } + /* Test await */ { char func_call[] = "hello_boy_await(2, 2)"; void *args[] = { metacall_value_create_string(func_call, strlen(func_call)) }; @@ -135,6 +140,7 @@ TEST_F(metacall_cli_core_plugin_test, DefaultConstructor) metacall_value_destroy(args[0]); } + /* Test await */ { char func_call[] = "return_await()"; void *args[] = { metacall_value_create_string(func_call, strlen(func_call)) }; @@ -148,6 +154,7 @@ TEST_F(metacall_cli_core_plugin_test, DefaultConstructor) metacall_value_destroy(args[0]); } + /* Test clear */ { void *args[2]; @@ -166,6 +173,7 @@ TEST_F(metacall_cli_core_plugin_test, DefaultConstructor) metacall_value_destroy(args[1]); } + /* Test inspect */ { void *ret = metacallhv_s(handle, "inspect", metacall_null_args, 0); diff --git a/source/tests/preprocessor_test/source/preprocessor_test.cpp b/source/tests/preprocessor_test/source/preprocessor_test.cpp index b6483c3dd..1d344a4b0 100644 --- a/source/tests/preprocessor_test/source/preprocessor_test.cpp +++ b/source/tests/preprocessor_test/source/preprocessor_test.cpp @@ -139,6 +139,24 @@ TEST_F(preprocessor_test, foreach) EXPECT_STREQ(for_each_str, "abc"); } +TEST_F(preprocessor_test, foreach_empty) +{ +#define PREPROCESSOR_TEST_FOR_EACH(expr) "33434" + + EXPECT_EQ((int)1, (int)PREPROCESSOR_ARGS_EMPTY(PREPROCESSOR_FOR_EACH(PREPROCESSOR_TEST_FOR_EACH))); + +#undef PREPROCESSOR_TEST_FOR_EACH +} + +TEST_F(preprocessor_test, for_empty) +{ +#define PREPROCESSOR_TEST_FOR(context, iterator, element) "33434" + + EXPECT_EQ((int)1, (int)PREPROCESSOR_ARGS_EMPTY(PREPROCESSOR_FOR(PREPROCESSOR_TEST_FOR, "yeet"))); + +#undef PREPROCESSOR_TEST_FOR +} + TEST_F(preprocessor_test, for) { #define PREPROCESSOR_TEST_FOR(context, iterator, element) \ From 8ee3fadd8310d0b7a6816a64f1cc75fc9adad651 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Wed, 11 Oct 2023 00:29:22 +0200 Subject: [PATCH 024/615] Add base for all commands in cli core plugin test. --- .../source/cli_core_plugin.cpp | 606 +++++++++++++++--- .../include/plugin/plugin_interface.hpp | 3 +- .../include/preprocessor/preprocessor_for.h | 1 + .../source/metacall_cli_core_plugin_test.cpp | 199 +++++- 4 files changed, 716 insertions(+), 93 deletions(-) diff --git a/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp b/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp index 3530f7575..e0c47a6cc 100644 --- a/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp +++ b/source/cli/plugins/cli_core_plugin/source/cli_core_plugin.cpp @@ -22,7 +22,10 @@ #include +#include #include +#include +#include #include #include #include @@ -30,166 +33,336 @@ #include /* Error messages */ -#define LOAD_ERROR "Failed to load a script" -#define INSPECT_ERROR "Failed to inspect MetaCall context" -#define EVAL_ERROR "Failed to evaluate the expression" -#define CALL_ERROR "Failed to call the function" -#define AWAIT_ERROR "Failed to await the function" -#define CLEAR_ERROR "Failed to clear the handle" - -void *load(size_t argc, void *args[], void *data) +#define LOAD_ERROR "Failed to load a script" +#define INSPECT_ERROR "Failed to inspect MetaCall context" +#define EVAL_ERROR "Failed to evaluate the expression" +#define CALL_ERROR "Failed to call the function" +#define AWAIT_ERROR "Failed to await the function" +#define CLEAR_ERROR "Failed to clear the handle" +#define COPYRIGHT_ERROR "Failed to show the copyright" +#define HELP_ERROR "Failed to show the help" +#define DEBUG_ERROR "Failed to debug the command" +#define EXIT_ERROR "Failed to destroy MetaCall" + +#define COPYRIGHT_PRINT() \ + do \ + { \ + std::cout << "MetaCall Command Line Interface by Parra Studios" << std::endl; \ + std::cout << "A command line interface for MetaCall Core" << std::endl; \ + std::cout << std::endl; \ + std::cout << "Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia " << std::endl; \ + } while (0) + +template +void *extension_function_check_array(const char *error, void *v, std::vector &array, cast_func_type &cast_func, enum metacall_value_id id) { - /* Validate function parameters */ - EXTENSION_FUNCTION_CHECK(LOAD_ERROR, METACALL_STRING, METACALL_ARRAY); - - char *tag = metacall_value_to_string(args[0]); - size_t size = metacall_value_count(args[1]); - void **script_values = metacall_value_to_array(args[1]); - std::vector scripts; - std::vector scripts_cstr; + size_t size = metacall_value_count(v); + void **values = metacall_value_to_array(v); - scripts.reserve(size); - scripts_cstr.reserve(size); + array.reserve(size); for (size_t i = 0; i < size; ++i) { - if (metacall_value_id(script_values[i]) != METACALL_STRING) + if (metacall_value_id(values[i]) != id) { std::stringstream ss; - ss << LOAD_ERROR ", calling load with wrong type of argument at argument position " - << (i + 1) << ", expected " << metacall_value_id_name(METACALL_STRING) - << ", got " << metacall_value_type_name(script_values[i]); + ss << error << ", calling with wrong type of argument at argument position #" + << (i + 1) << ", expected " << metacall_value_id_name(id) + << ", got " << metacall_value_type_name(values[i]); EXTENSION_FUNCTION_THROW(ss.str().c_str()); } - scripts.push_back(metacall_value_to_string(script_values[i])); - scripts_cstr.push_back(const_cast(scripts[i].c_str())); + array.push_back(cast_func(values[i])); } - int ret = metacall_load_from_file(tag, scripts_cstr.data(), size, NULL); - - return metacall_value_create_int(ret); + return NULL; } -void *inspect(size_t argc, void *args[], void *data) +static const std::vector loader_tags(void) { - /* Validate function parameters */ - EXTENSION_FUNCTION_CHECK(INSPECT_ERROR); - - size_t size = 0; + static const std::vector loaders = { + "mock", "py", "node", "rb", "cs", "cob", + "ts", "js", "file", "wasm", "rs", "c", + "rpc", "ext", "java" + }; - struct metacall_allocator_std_type std_ctx = { &std::malloc, &std::realloc, &std::free }; - void *allocator = metacall_allocator_create(METACALL_ALLOCATOR_STD, (void *)&std_ctx); + return loaders; +} - char *inspect_str = metacall_inspect(&size, allocator); +static bool loader_tag_is_valid(const char *tag) +{ + static const std::vector loaders = loader_tags(); - void *inspect_value_str = metacall_value_create_string(inspect_str, size > 0 ? size - 1 : 0); + /* Check if invalid loader tag */ + return std::find(std::begin(loaders), std::end(loaders), tag) != std::end(loaders); +} - metacall_allocator_free(allocator, inspect_str); +static void *throw_invalid_tag(const char *error, const char *tag) +{ + static const std::vector loaders = loader_tags(); + auto it = std::begin(loaders); + std::stringstream ss; + ss << error << ", " << tag << " is not a valid tag, use: " << *it; - metacall_allocator_destroy(allocator); + do + { + ++it; + ss << ", " << *it; + } while (it != std::end(loaders)); - return inspect_value_str; + EXTENSION_FUNCTION_THROW(ss.str().c_str()); } -void *eval(size_t argc, void *args[], void *data) +static void value_array_for_each(void *v, const std::function &lambda) { - /* Validate function parameters */ - EXTENSION_FUNCTION_CHECK(EVAL_ERROR, METACALL_STRING, METACALL_STRING); - - char *tag = metacall_value_to_string(args[0]); - char *script = metacall_value_to_string(args[1]); - size_t size = metacall_value_size(args[1]); + void **v_array = static_cast(metacall_value_to_array(v)); + size_t count = metacall_value_count(v); - return metacall_value_create_int(metacall_load_from_memory(tag, script, size, NULL)); + std::for_each(v_array, v_array + count, lambda); } -void *call(size_t argc, void *args[], void *data) +static void value_map_for_each(void *v, const std::function &lambda) { - /* Validate function parameters */ - EXTENSION_FUNCTION_CHECK(CALL_ERROR, METACALL_STRING); + void **v_map = static_cast(metacall_value_to_map(v)); + size_t count = metacall_value_count(v); - /* Parse function call */ - std::string func_str = metacall_value_to_string(args[0]); + std::for_each(v_map, v_map + count, [&lambda](void *element) { + void **v_element = metacall_value_to_array(element); + lambda(metacall_value_to_string(v_element[0]), v_element[1]); + }); +} + +static void *parse_function_call(const char *error, void *func_str_value, void **func, std::string &func_args) +{ + std::string func_str = metacall_value_to_string(func_str_value); if (func_str.find('(') == std::string::npos || func_str.find(')') == std::string::npos) { std::stringstream ss; - ss << CALL_ERROR ", calling function with malformed function call string: " << func_str; + ss << error << ", calling function with malformed function call string: " << func_str; EXTENSION_FUNCTION_THROW(ss.str().c_str()); } - std::string::size_type idx = func_str.find_first_of('('); - std::string func_name = func_str.substr(0, idx); + std::string::size_type first_parenthesis = func_str.find_first_of('('); + std::string::size_type last_parenthesis = func_str.find_first_of(')'); + std::string func_name = func_str.substr(0, first_parenthesis); + + if (first_parenthesis != func_name.size() || last_parenthesis != (func_str.size() - 1)) + { + std::stringstream ss; + + ss << error << ", calling function with malformed parameters: " << func_str; + + EXTENSION_FUNCTION_THROW(ss.str().c_str()); + } /* Convert arguments into an array */ - std::string func_args = "["; - func_args += func_str.substr(idx + 1, func_str.size() - (idx + 2)); + func_args = "["; + func_args += func_str.substr(first_parenthesis + 1, func_str.size() - first_parenthesis - 2); func_args += "]"; /* Check if function is loaded */ const char *func_name_str = const_cast(func_name.c_str()); - void *func = metacall_function(func_name_str); + *func = metacall_function(func_name_str); - if (func == NULL) + if (*func == NULL) { std::stringstream ss; - ss << CALL_ERROR ", function '" << func_name << "' does not exist"; + ss << error << ", function '" << func_name << "' does not exist"; EXTENSION_FUNCTION_THROW(ss.str().c_str()); } - struct metacall_allocator_std_type std_ctx = { &std::malloc, &std::realloc, &std::free }; - void *allocator = metacall_allocator_create(METACALL_ALLOCATOR_STD, (void *)&std_ctx); + return NULL; +} - void *result = metacallfs(func, func_args.c_str(), func_args.length() + 1, allocator); +void *load(size_t argc, void *args[], void *data) +{ + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(LOAD_ERROR, METACALL_STRING, METACALL_ARRAY); - metacall_allocator_destroy(allocator); + char *tag = metacall_value_to_string(args[0]); - return result; + if (!loader_tag_is_valid(tag)) + { + return throw_invalid_tag(LOAD_ERROR, tag); + } + + std::vector scripts; + void *error = extension_function_check_array(LOAD_ERROR, args[1], scripts, metacall_value_to_string, METACALL_STRING); + + if (error != NULL) + { + return error; + } + + std::vector scripts_cstr; + + scripts_cstr.reserve(scripts.size()); + + for (auto it = std::begin(scripts); it != std::end(scripts); ++it) + { + scripts_cstr.push_back((*it).c_str()); + } + + int ret = metacall_load_from_file(tag, scripts_cstr.data(), scripts_cstr.size(), NULL); + + return metacall_value_create_int(ret); } -void *await(size_t argc, void *args[], void *data) +void *inspect(size_t argc, void *args[], void *data) { /* Validate function parameters */ - EXTENSION_FUNCTION_CHECK(CALL_ERROR, METACALL_STRING); + EXTENSION_FUNCTION_CHECK(INSPECT_ERROR); - /* Parse function call */ - std::string func_str = metacall_value_to_string(args[0]); + void *v = metacall_inspect_value(); - if (func_str.find('(') == std::string::npos || func_str.find(')') == std::string::npos) + if (v == NULL) { - std::stringstream ss; + EXTENSION_FUNCTION_THROW(INSPECT_ERROR ", inspect returned invalid value"); + } - ss << CALL_ERROR ", calling function with malformed function call string: " << func_str; + /* Print run-times */ + value_map_for_each(v, [](const char *key, void *modules) { + std::cout << "runtime " << key; - EXTENSION_FUNCTION_THROW(ss.str().c_str()); + if (metacall_value_count(modules) == 0) + { + std::cout << std::endl; + return; + } + + std::cout << " {" << std::endl; + + /* Print scripts */ + value_array_for_each(modules, [](void *module) { + /* Get module name */ + void **v_module_map = static_cast(metacall_value_to_map(module)); + void **v_module_name_tuple = metacall_value_to_array(v_module_map[0]); + const char *name = metacall_value_to_string(v_module_name_tuple[1]); + + std::cout << "\tmodule " << name << " { " << std::endl; + + /* Get module functions */ + void **v_module_scope_tuple = metacall_value_to_array(v_module_map[1]); + void **v_scope_map = metacall_value_to_map(v_module_scope_tuple[1]); + void **v_scope_funcs_tuple = metacall_value_to_array(v_scope_map[1]); + + if (metacall_value_count(v_scope_funcs_tuple[1]) != 0) + { + value_array_for_each(v_scope_funcs_tuple[1], [](void *func) { + /* Get function name */ + void **v_func_map = static_cast(metacall_value_to_map(func)); + void **v_func_tuple = metacall_value_to_array(v_func_map[0]); + const char *func_name = metacall_value_to_string(v_func_tuple[1]); + + std::cout << "\t\tfunction " << func_name << "("; + + /* Get function signature */ + void **v_signature_tuple = metacall_value_to_array(v_func_map[1]); + void **v_args_map = metacall_value_to_map(v_signature_tuple[1]); + void **v_args_tuple = metacall_value_to_array(v_args_map[1]); + void **v_args_array = metacall_value_to_array(v_args_tuple[1]); + + size_t iterator = 0, count = metacall_value_count(v_args_tuple[1]); + + value_array_for_each(v_args_array, [&iterator, &count](void *arg) { + void **v_arg_map = metacall_value_to_map(arg); + void **v_arg_name_tupla = metacall_value_to_array(v_arg_map[0]); + std::string parameter_name(metacall_value_to_string(v_arg_name_tupla[1])); + + if (parameter_name.empty()) + { + parameter_name += "arg"; + parameter_name += std::to_string(iterator); + } + + std::cout << parameter_name; + + if (iterator + 1 < count) + { + std::cout << ", "; + } + + ++iterator; + }); + + std::cout << ")" << std::endl; + }); + } + + std::cout << "\t}" << std::endl; + }); + + std::cout << "}" << std::endl; + }); + + metacall_value_destroy(v); + + return metacall_value_create_int(0); +} + +void *eval(size_t argc, void *args[], void *data) +{ + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(EVAL_ERROR, METACALL_STRING, METACALL_STRING); + + char *tag = metacall_value_to_string(args[0]); + + if (!loader_tag_is_valid(tag)) + { + return throw_invalid_tag(EVAL_ERROR, tag); } - std::string::size_type idx = func_str.find_first_of('('); - std::string func_name = func_str.substr(0, idx); + char *script = metacall_value_to_string(args[1]); + size_t size = metacall_value_size(args[1]); - /* Convert arguments into an array */ - std::string func_args = "["; - func_args += func_str.substr(idx + 1, func_str.size() - (idx + 2)); - func_args += "]"; + return metacall_value_create_int(metacall_load_from_memory(tag, script, size, NULL)); +} - /* Check if function is loaded */ - const char *func_name_str = const_cast(func_name.c_str()); - void *func = metacall_function(func_name_str); +void *call(size_t argc, void *args[], void *data) +{ + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(CALL_ERROR, METACALL_STRING); + + /* Parse function call */ + void *func = NULL; + std::string func_args; + void *error = parse_function_call(CALL_ERROR, args[0], &func, func_args); - if (func == NULL) + if (error != NULL) { - std::stringstream ss; + return error; + } - ss << CALL_ERROR ", function '" << func_name << "' does not exist"; + struct metacall_allocator_std_type std_ctx = { &std::malloc, &std::realloc, &std::free }; + void *allocator = metacall_allocator_create(METACALL_ALLOCATOR_STD, (void *)&std_ctx); - EXTENSION_FUNCTION_THROW(ss.str().c_str()); + void *result = metacallfs(func, func_args.c_str(), func_args.length() + 1, allocator); + + metacall_allocator_destroy(allocator); + + return result; +} + +void *await(size_t argc, void *args[], void *data) +{ + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(CALL_ERROR, METACALL_STRING); + + /* Parse function call */ + void *func = NULL; + std::string func_args; + void *error = parse_function_call(AWAIT_ERROR, args[0], &func, func_args); + + if (error != NULL) + { + return error; } struct metacall_allocator_std_type std_ctx = { &std::malloc, &std::realloc, &std::free }; @@ -245,8 +418,13 @@ void *clear(size_t argc, void *args[], void *data) EXTENSION_FUNCTION_CHECK(CLEAR_ERROR, METACALL_STRING, METACALL_STRING); char *tag = metacall_value_to_string(args[0]); - char *script = metacall_value_to_string(args[1]); + if (!loader_tag_is_valid(tag)) + { + return throw_invalid_tag(CLEAR_ERROR, tag); + } + + char *script = metacall_value_to_string(args[1]); void *handle = metacall_handle(tag, script); if (handle == NULL) @@ -261,16 +439,268 @@ void *clear(size_t argc, void *args[], void *data) return metacall_value_create_int(metacall_clear(handle)); } +void *copyright(size_t argc, void *args[], void *data) +{ + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(COPYRIGHT_ERROR); + + COPYRIGHT_PRINT(); + + return metacall_value_create_int(0); +} + +void *help(size_t argc, void *args[], void *data) +{ + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(HELP_ERROR); + + /* Print copyright first */ + COPYRIGHT_PRINT(); + + /* Command list */ + std::cout << std::endl + << "Command list:" << std::endl + << std::endl; + + /* Load command */ + std::cout << "\t┌────────────────────────────────────────────────────────────────────────────────────────┐" << std::endl; + std::cout << "\t│ Load a script from file into MetaCall │" << std::endl; + std::cout << "\t│────────────────────────────────────────────────────────────────────────────────────────│" << std::endl; + std::cout << "\t│ Usage: │" << std::endl; + std::cout << "\t│ load ... │" << std::endl; + std::cout << "\t│ : identifier to the type of script │" << std::endl; + std::cout << "\t│ options : │" << std::endl; + std::cout << "\t│ mock - Mock (for testing purposes) │" << std::endl; + std::cout << "\t│ py - Python │" << std::endl; + std::cout << "\t│ node - NodeJS │" << std::endl; + std::cout << "\t│ rb - Ruby │" << std::endl; + std::cout << "\t│ cs - C# NetCore │" << std::endl; + std::cout << "\t│ cob - Cobol │" << std::endl; + std::cout << "\t│ ts - TypeScript │" << std::endl; + std::cout << "\t│ js - V8 JavaScript Engine │" << std::endl; + std::cout << "\t│ file - Files (for handling file systems) │" << std::endl; + std::cout << "\t│ ... : relative or absolute path to the script(s) │" << std::endl; + std::cout << "\t│ │" << std::endl; + std::cout << "\t│ Example: │" << std::endl; + std::cout << "\t│ load node concat.js │" << std::endl; + std::cout << "\t│ load py example.py │" << std::endl; + std::cout << "\t│ load rb hello.rb │" << std::endl; + std::cout << "\t│ │" << std::endl; + std::cout << "\t│ Result: │" << std::endl; + std::cout << "\t│ Script (concat.js) loaded correctly │" << std::endl; + std::cout << "\t└────────────────────────────────────────────────────────────────────────────────────────┘" << std::endl + << std::endl; + + /* Inspect command */ + std::cout << "\t┌────────────────────────────────────────────────────────────────────────────────────────┐" << std::endl; + std::cout << "\t│ Show all runtimes, modules and functions (with their signature) loaded into MetaCall │" << std::endl; + std::cout << "\t│────────────────────────────────────────────────────────────────────────────────────────│" << std::endl; + std::cout << "\t│ Usage: │" << std::endl; + std::cout << "\t│ inspect │" << std::endl; + std::cout << "\t│ │" << std::endl; + std::cout << "\t│ Example: │" << std::endl; + std::cout << "\t│ inspect │" << std::endl; + std::cout << "\t│ │" << std::endl; + std::cout << "\t│ Result: │" << std::endl; + std::cout << "\t│ runtime node { │" << std::endl; + std::cout << "\t│ module concat { │" << std::endl; + std::cout << "\t│ function concat(left, right) │" << std::endl; + std::cout << "\t│ } │" << std::endl; + std::cout << "\t│ } │" << std::endl; + std::cout << "\t└────────────────────────────────────────────────────────────────────────────────────────┘" << std::endl + << std::endl; + + /* Eval command */ + std::cout << "\t┌────────────────────────────────────────────────────────────────────────────────────────┐" << std::endl; + std::cout << "\t│ Evaluate a code snippet with the specified runtime tag │" << std::endl; + std::cout << "\t│────────────────────────────────────────────────────────────────────────────────────────│" << std::endl; + std::cout << "\t│ Usage: │" << std::endl; + std::cout << "\t│ eval