diff --git a/core/src/linuxcnc_rs274_backend.cpp b/core/src/linuxcnc_rs274_backend.cpp index 4a7769c..351a574 100644 --- a/core/src/linuxcnc_rs274_backend.cpp +++ b/core/src/linuxcnc_rs274_backend.cpp @@ -82,6 +82,37 @@ bool file_mode_enabled() { return std::getenv("CNC_SIM_RS274_FILE_MODE") != nullptr; } +class ScopedEnvironmentVariable { +public: + ScopedEnvironmentVariable(const char *name, const std::string &value) : name_(name), active_(!value.empty()) { + if (!active_) { + return; + } + if (const char *old = std::getenv(name_)) { + had_old_ = true; + old_ = old; + } + setenv(name_, value.c_str(), 1); + } + + ~ScopedEnvironmentVariable() { + if (!active_) { + return; + } + if (had_old_) { + setenv(name_, old_.c_str(), 1); + } else { + unsetenv(name_); + } + } + +private: + const char *name_; + bool active_; + bool had_old_ = false; + std::string old_; +}; + #ifndef CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE bool write_temp_program(const char *program, size_t program_len, @@ -197,6 +228,9 @@ int parse_linuxcnc_rs274_backend(CanonEventSink &sink, sink.clear_callback_status(); cnc_sim_linuxcnc_set_canon_sink(&sink); + // LinuxCNC source basis: rs274ngc_pre.cc and interp_namedparams.cc read + // INI_FILE_NAME for startup and #<_ini[section]key> named parameters. + ScopedEnvironmentVariable ini_file_env("INI_FILE_NAME", options.ini_file_name); InterpBase *interp = makeInterp(); if (!options.ini_file_name.empty()) { // LinuxCNC source basis: emctask.cc calls Interp::ini_load() before diff --git a/core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp b/core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp index c33733f..6275864 100644 --- a/core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp +++ b/core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp @@ -240,6 +240,8 @@ int main() { std::ofstream ini_file(rs274_ini_path); ini_file << "[RS274NGC]\n"; ini_file << "PARAMETER_FILE = " << ini_parameter_var_path << "\n"; + ini_file << "[SETUP]\n"; + ini_file << "XPOS = 12\n"; } std::vector ini_events; CncSimHandle *ini_sim = cnc_sim_create(); @@ -255,23 +257,33 @@ int main() { const char ini_parameter_check_program[] = "G21 G90 G17\n" "F100\n" - "G1 X#5001\n"; + "G1 X#5001\n" + "G1 X#<_ini[setup]xpos>\n"; ini_ok &= expect(cnc_sim_parse_program(ini_sim, ini_parameter_check_program, sizeof(ini_parameter_check_program) - 1) == 0, cnc_sim_last_error(ini_sim)); bool saw_ini_parameter_restore = false; + bool saw_ini_named_parameter = false; for (const auto &event : ini_events) { saw_ini_parameter_restore = saw_ini_parameter_restore || (event.type == CNC_SIM_EVENT_LINEAR_FEED && event.line == 3 && near(event.end.x, 44.0)); + saw_ini_named_parameter = saw_ini_named_parameter || + (event.type == CNC_SIM_EVENT_LINEAR_FEED && + event.line == 4 && + near(event.end.x, 12.0)); } // LinuxCNC source basis: emctask.cc calls interp.ini_load(), and // rs274ngc_pre.cc ini_load() maps [RS274NGC] PARAMETER_FILE through // SET_PARAMETER_FILE_NAME before rs274_ngc_init() restores parameters. ini_ok &= expect(saw_ini_parameter_restore, "expected LinuxCNC INI PARAMETER_FILE to restore numbered parameters"); + // LinuxCNC source basis: rs274ngc_pre.cc and interp_namedparams.cc + // read INI_FILE_NAME for #<_ini[section]key> lookups. + ini_ok &= expect(saw_ini_named_parameter, + "expected LinuxCNC config INI_FILE_NAME to back #<_ini[]> named parameters"); cnc_sim_destroy(ini_sim); if (!ini_ok) { return 1; diff --git a/test-native.sh b/test-native.sh index babbf77..6ac7229 100755 --- a/test-native.sh +++ b/test-native.sh @@ -82,7 +82,9 @@ grep -F 'blocked:src/emc/rs274ngc/gcodemodule.cc:Python gcode module binding, tr grep -F 'expected LinuxCNC parameter env override not to leak into default parses' core/tests/cnc_sim_api_smoke.cpp >/dev/null grep -F 'SET_PARAMETER_FILE_NAME("rs274ngc.var")' core/src/linuxcnc_rs274_backend.cpp >/dev/null grep -F 'expected LinuxCNC INI PARAMETER_FILE to restore numbered parameters' core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp >/dev/null +grep -F 'expected LinuxCNC config INI_FILE_NAME to back #<_ini[]> named parameters' core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp >/dev/null grep -F 'interp->ini_load(options.ini_file_name.c_str())' core/src/linuxcnc_rs274_backend.cpp >/dev/null +grep -F 'ScopedEnvironmentVariable ini_file_env("INI_FILE_NAME", options.ini_file_name)' core/src/linuxcnc_rs274_backend.cpp >/dev/null grep -F 'metadata:src/emc/nml_intf/emcops.cc:source basis for native source-link EMC status constructor support object' linuxcnc-rs274-source-files.txt >/dev/null grep -F 'metadata:src/emc/sai/dummyemcstat.cc:source basis for native source-link emcStatus singleton support object' linuxcnc-rs274-source-files.txt >/dev/null grep -F 'metadata:src/emc/sai/Submakefile:LinuxCNC SAI build metadata defining dummyemcstat support object' linuxcnc-rs274-source-files.txt >/dev/null