diff --git a/compiler/code-gen/files/init-scripts.cpp b/compiler/code-gen/files/init-scripts.cpp index 816f2d1ce5..006e1f32d3 100644 --- a/compiler/code-gen/files/init-scripts.cpp +++ b/compiler/code-gen/files/init-scripts.cpp @@ -65,6 +65,14 @@ void StaticInit::compile(CodeGenerator &W) const { W << END << NL << NL; } + if (G->is_output_mode_k2()) { + W << "namespace kphp::compiler_interface {" << NL; + FunctionSignatureGenerator(W) << ("std::string_view get_main_file_name() ") << BEGIN; + W << "return {\"" << G->get_main_file()->short_file_name << ".php\"};"; + W << END << NL; + W << "}" << NL; + } + FunctionSignatureGenerator(W) << ("void init_php_scripts_once_in_master() ") << BEGIN; if (!G->settings().tl_schema_file.get().empty()) { diff --git a/runtime-light/core/compiler-info/compiler_interface.h b/runtime-light/core/compiler-info/compiler_interface.h new file mode 100644 index 0000000000..a7df429a01 --- /dev/null +++ b/runtime-light/core/compiler-info/compiler_interface.h @@ -0,0 +1,13 @@ +// Compiler for PHP (aka KPHP) +// Copyright (c) 2025 LLC «V Kontakte» +// Distributed under the GPL v3 License, see LICENSE.notice.txt + +#pragma once + +#include + +namespace kphp::compiler_interface { + +std::string_view get_main_file_name() noexcept; + +} // namespace kphp::compiler_interface diff --git a/runtime-light/state/component-state.cpp b/runtime-light/state/component-state.cpp index 4bbf460660..f693e21d10 100644 --- a/runtime-light/state/component-state.cpp +++ b/runtime-light/state/component-state.cpp @@ -4,6 +4,7 @@ #include "runtime-light/state/component-state.h" +#include #include #include #include @@ -13,6 +14,7 @@ #include "runtime-common/core/runtime-core.h" #include "runtime-common/core/utils/kphp-assert-core.h" #include "runtime-common/stdlib/serialization/json-functions.h" +#include "runtime-light/core/compiler-info/compiler_interface.h" #include "runtime-light/k2-platform/k2-api.h" void ComponentState::parse_env() noexcept { @@ -54,6 +56,40 @@ void ComponentState::parse_runtime_config_arg(std::string_view value_view) noexc } } +void ComponentState::parse_command_line_arg(std::string_view value_view) noexcept { + if (value_view.empty()) [[unlikely]] { + php_warning("command line argument is empty"); + return; + } + + if (!command_line_argv.empty()) [[unlikely]] { + php_warning("command line argument support no more one usage"); + return; + } + + const auto& main_file_view{kphp::compiler_interface::get_main_file_name()}; + command_line_argv.push_back(string(main_file_view.data(), main_file_view.size())); + + bool in_quote{}; + string current_arg{}; + for (char letter : value_view) { + if (std::isspace(letter) && !in_quote && !current_arg.empty()) { + command_line_argv.push_back(std::move(current_arg)); + current_arg = string(); + } else if (letter == '"') { + in_quote = !in_quote; + } else if (letter == '\'') { + php_warning("in command line arg supported only \" quote"); + } else { + current_arg.push_back(letter); + } + } + + if (!current_arg.empty()) { + command_line_argv.push_back(std::move(current_arg)); + } +} + void ComponentState::parse_args() noexcept { for (auto i = 0; i < argc; ++i) { const auto [arg_key, arg_value]{k2::arg_fetch(i)}; @@ -64,10 +100,13 @@ void ComponentState::parse_args() noexcept { parse_ini_arg(key_view, value_view); } else if (key_view == RUNTIME_CONFIG_ARG) { parse_runtime_config_arg(value_view); + } else if (key_view == COMMAND_LINE_ARG) { + parse_command_line_arg(value_view); } else { php_warning("unknown argument: %s", key_view.data()); } } + command_line_argv.set_reference_counter_to(ExtraRefCnt::for_global_const); runtime_config.set_reference_counter_to(ExtraRefCnt::for_global_const); ini_opts.set_reference_counter_to(ExtraRefCnt::for_global_const); } diff --git a/runtime-light/state/component-state.h b/runtime-light/state/component-state.h index 14e8786086..ea9e4a5d13 100644 --- a/runtime-light/state/component-state.h +++ b/runtime-light/state/component-state.h @@ -19,6 +19,7 @@ struct ComponentState final : private vk::not_copyable { const uint32_t argc; const uint32_t envc; mixed runtime_config; + array command_line_argv; array ini_opts; array env; @@ -43,6 +44,7 @@ struct ComponentState final : private vk::not_copyable { private: static constexpr std::string_view INI_ARG_PREFIX = "ini "; + static constexpr std::string_view COMMAND_LINE_ARG = "command-line"; static constexpr std::string_view RUNTIME_CONFIG_ARG = "runtime-config"; static constexpr auto INIT_COMPONENT_ALLOCATOR_SIZE = static_cast(512U * 1024U); // 512KB @@ -53,4 +55,6 @@ struct ComponentState final : private vk::not_copyable { void parse_ini_arg(std::string_view, std::string_view) noexcept; void parse_runtime_config_arg(std::string_view) noexcept; + + void parse_command_line_arg(std::string_view) noexcept; }; diff --git a/runtime-light/state/init-functions.cpp b/runtime-light/state/init-functions.cpp index 30764ce6f7..ee16bbc379 100644 --- a/runtime-light/state/init-functions.cpp +++ b/runtime-light/state/init-functions.cpp @@ -14,6 +14,7 @@ #include "runtime-light/server/http/init-functions.h" #include "runtime-light/server/init-functions.h" #include "runtime-light/server/job-worker/job-worker-server-state.h" +#include "runtime-light/state/component-state.h" #include "runtime-light/state/instance-state.h" #include "runtime-light/streams/streams.h" #include "runtime-light/tl/tl-core.h" @@ -44,8 +45,9 @@ kphp::coro::task init_kphp_cli_component() noexcept { { // TODO superglobals init auto& superglobals{InstanceState::get().php_script_mutable_globals_singleton.get_superglobals()}; using namespace PhpServerSuperGlobalIndices; - superglobals.v$argc = static_cast(0); - superglobals.v$argv = array{}; + const auto& command_line_argv{ComponentState::get().command_line_argv}; + superglobals.v$argv = command_line_argv; + superglobals.v$argc = command_line_argv.size().size; superglobals.v$_SERVER.set_value(string{ARGC.data(), ARGC.size()}, superglobals.v$argc); superglobals.v$_SERVER.set_value(string{ARGV.data(), ARGV.size()}, superglobals.v$argv); superglobals.v$_SERVER.set_value(string{PHP_SELF.data(), PHP_SELF.size()}, string{});