Compare commits
4 Commits
d807464cf7
...
67154a70fa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67154a70fa | ||
|
|
5c7093ba39 | ||
|
|
0e1e22a864 | ||
|
|
cee1bf3a3f |
@@ -3,6 +3,9 @@ set -euo pipefail
|
|||||||
|
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: link probe modes reuse wasm-safe objects built from
|
||||||
|
# linuxcnc-rs274-wasm-source-files.txt and add only a narrow probe main that
|
||||||
|
# asserts LinuxCNC rs274ngc_pre/runtime symbols stay linked.
|
||||||
usage() {
|
usage() {
|
||||||
echo "usage: $0 --mode rs274ngc-pre|runtime [manifest]" >&2
|
echo "usage: $0 --mode rs274ngc-pre|runtime [manifest]" >&2
|
||||||
}
|
}
|
||||||
@@ -82,6 +85,9 @@ target_name=rs274ngc_pre_probe
|
|||||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh --profile core20-sections)
|
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh --profile core20-sections)
|
||||||
mapfile -t common_flags <<<"$common_flag_output"
|
mapfile -t common_flags <<<"$common_flag_output"
|
||||||
case "$mode" in
|
case "$mode" in
|
||||||
|
rs274ngc-pre)
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc provides' "$main_source" >/dev/null
|
||||||
|
;;
|
||||||
runtime)
|
runtime)
|
||||||
object_mode=runtime
|
object_mode=runtime
|
||||||
main_source=core/wasm_shims/cnc_sim_wasm_runtime_probe_main.cc
|
main_source=core/wasm_shims/cnc_sim_wasm_runtime_probe_main.cc
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ set -euo pipefail
|
|||||||
|
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: standalone probe modes either compile LinuxCNC
|
||||||
|
# rs274/tooldata sources directly or link wasm-safe shims whose source basis is
|
||||||
|
# checked against LinuxCNC source comments before building.
|
||||||
usage() {
|
usage() {
|
||||||
echo "usage: $0 --mode tooldata-link|tooldata-common-link|interp-base-link|python-plugin-link|rs274ngc-pre-object" >&2
|
echo "usage: $0 --mode tooldata-link|tooldata-common-link|interp-base-link|python-plugin-link|rs274ngc-pre-object" >&2
|
||||||
}
|
}
|
||||||
@@ -122,6 +125,7 @@ case "$mode" in
|
|||||||
;;
|
;;
|
||||||
rs274ngc-pre-object)
|
rs274ngc-pre-object)
|
||||||
rs274ngc_pre_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/rs274ngc/rs274ngc_pre.cc)
|
rs274ngc_pre_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/rs274ngc/rs274ngc_pre.cc)
|
||||||
|
grep -F 'core:src/emc/rs274ngc/rs274ngc_pre.cc:Interp implementation covered by rs274ngc_pre link probe' linuxcnc-rs274-wasm-source-files.txt >/dev/null
|
||||||
sources+=("$rs274ngc_pre_source")
|
sources+=("$rs274ngc_pre_source")
|
||||||
target_name=rs274ngc_pre.o
|
target_name=rs274ngc_pre.o
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
struct CncSimHandle {
|
struct CncSimHandle {
|
||||||
CncSimDialect dialect = CNC_SIM_DIALECT_LINUXCNC;
|
CncSimDialect dialect = CNC_SIM_DIALECT_LINUXCNC;
|
||||||
GcodeBackendKind backend = GcodeBackendKind::LinuxCncRs274;
|
GcodeBackendKind backend = GcodeBackendKind::LinuxCncRs274;
|
||||||
|
GcodeBackendOptions backend_options;
|
||||||
std::string last_error;
|
std::string last_error;
|
||||||
CanonEventSink sink;
|
CanonEventSink sink;
|
||||||
};
|
};
|
||||||
@@ -96,6 +97,72 @@ bool contains_string_value(const std::string &compact, const char *key, const ch
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool find_json_string_value(const std::string &json, const char *key, std::string *value) {
|
||||||
|
const std::string needle = std::string("\"") + key + "\"";
|
||||||
|
size_t pos = 0;
|
||||||
|
while ((pos = json.find(needle, pos)) != std::string::npos) {
|
||||||
|
pos += needle.size();
|
||||||
|
while (pos < json.size() && std::isspace(static_cast<unsigned char>(json[pos]))) {
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
if (pos >= json.size() || json[pos] != ':') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++pos;
|
||||||
|
while (pos < json.size() && std::isspace(static_cast<unsigned char>(json[pos]))) {
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
if (pos >= json.size() || json[pos] != '"') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++pos;
|
||||||
|
std::string parsed;
|
||||||
|
bool escaped = false;
|
||||||
|
for (; pos < json.size(); ++pos) {
|
||||||
|
const char ch = json[pos];
|
||||||
|
if (escaped) {
|
||||||
|
switch (ch) {
|
||||||
|
case '"':
|
||||||
|
case '\\':
|
||||||
|
case '/':
|
||||||
|
parsed.push_back(ch);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
parsed.push_back('\n');
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
parsed.push_back('\r');
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
parsed.push_back('\t');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
parsed.push_back(ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
escaped = false;
|
||||||
|
} else if (ch == '\\') {
|
||||||
|
escaped = true;
|
||||||
|
} else if (ch == '"') {
|
||||||
|
*value = parsed;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
parsed.push_back(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool find_json_string_any(const std::string &json, std::string *value, const char *first) {
|
||||||
|
return find_json_string_value(json, first, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Keys>
|
||||||
|
bool find_json_string_any(const std::string &json, std::string *value, const char *first, Keys... rest) {
|
||||||
|
return find_json_string_value(json, first, value) || find_json_string_any(json, value, rest...);
|
||||||
|
}
|
||||||
|
|
||||||
bool contains_switchkins_config_alias(const std::string &compact, const char *alias) {
|
bool contains_switchkins_config_alias(const std::string &compact, const char *alias) {
|
||||||
return contains_string_value(compact, "switchkins", alias) ||
|
return contains_string_value(compact, "switchkins", alias) ||
|
||||||
contains_string_value(compact, "remap", alias) ||
|
contains_string_value(compact, "remap", alias) ||
|
||||||
@@ -300,6 +367,20 @@ int apply_config(CncSimHandle *handle, const std::string &json) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ini_file_name;
|
||||||
|
if (find_json_string_any(json,
|
||||||
|
&ini_file_name,
|
||||||
|
"ini",
|
||||||
|
"iniFile",
|
||||||
|
"inifile",
|
||||||
|
"iniFileName",
|
||||||
|
"inifilename",
|
||||||
|
"ini_file",
|
||||||
|
"ini_file_name",
|
||||||
|
"INI_FILE_NAME")) {
|
||||||
|
handle->backend_options.ini_file_name = ini_file_name;
|
||||||
|
}
|
||||||
|
|
||||||
bool rtcp_enabled = false;
|
bool rtcp_enabled = false;
|
||||||
double tool_length = 0.0;
|
double tool_length = 0.0;
|
||||||
const bool has_rtcp_enabled = contains_bool_value(compact, "rtcp", &rtcp_enabled) ||
|
const bool has_rtcp_enabled = contains_bool_value(compact, "rtcp", &rtcp_enabled) ||
|
||||||
@@ -383,7 +464,12 @@ int cnc_sim_parse_program(CncSimHandle *handle, const char *program, size_t prog
|
|||||||
}
|
}
|
||||||
|
|
||||||
handle->last_error.clear();
|
handle->last_error.clear();
|
||||||
const int rc = parse_gcode_with_backend(handle->backend, handle->sink, program, program_len, &handle->last_error);
|
const int rc = parse_gcode_with_backend(handle->backend,
|
||||||
|
handle->sink,
|
||||||
|
program,
|
||||||
|
program_len,
|
||||||
|
handle->backend_options,
|
||||||
|
&handle->last_error);
|
||||||
if (rc != 0 && handle->last_error.empty()) {
|
if (rc != 0 && handle->last_error.empty()) {
|
||||||
handle->last_error = "program parse failed";
|
handle->last_error = "program parse failed";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ int parse_gcode_with_backend(GcodeBackendKind backend,
|
|||||||
CanonEventSink &sink,
|
CanonEventSink &sink,
|
||||||
const char *program,
|
const char *program,
|
||||||
size_t program_len,
|
size_t program_len,
|
||||||
|
const GcodeBackendOptions &options,
|
||||||
std::string *error) {
|
std::string *error) {
|
||||||
switch (backend) {
|
switch (backend) {
|
||||||
case GcodeBackendKind::Smoke: {
|
case GcodeBackendKind::Smoke: {
|
||||||
@@ -37,7 +38,7 @@ int parse_gcode_with_backend(GcodeBackendKind backend,
|
|||||||
}
|
}
|
||||||
case GcodeBackendKind::LinuxCncRs274:
|
case GcodeBackendKind::LinuxCncRs274:
|
||||||
#ifdef CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND
|
#ifdef CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND
|
||||||
return parse_linuxcnc_rs274_backend(sink, program, program_len, error);
|
return parse_linuxcnc_rs274_backend(sink, program, program_len, options, error);
|
||||||
#else
|
#else
|
||||||
if (error) {
|
if (error) {
|
||||||
*error = "linuxcnc-rs274 backend is not compiled into this build";
|
*error = "linuxcnc-rs274 backend is not compiled into this build";
|
||||||
|
|||||||
@@ -10,11 +10,15 @@ enum class GcodeBackendKind {
|
|||||||
LinuxCncRs274,
|
LinuxCncRs274,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GcodeBackendOptions {
|
||||||
|
std::string ini_file_name;
|
||||||
|
};
|
||||||
|
|
||||||
const char *gcode_backend_name(GcodeBackendKind backend);
|
const char *gcode_backend_name(GcodeBackendKind backend);
|
||||||
|
|
||||||
int parse_gcode_with_backend(GcodeBackendKind backend,
|
int parse_gcode_with_backend(GcodeBackendKind backend,
|
||||||
CanonEventSink &sink,
|
CanonEventSink &sink,
|
||||||
const char *program,
|
const char *program,
|
||||||
size_t program_len,
|
size_t program_len,
|
||||||
|
const GcodeBackendOptions &options,
|
||||||
std::string *error);
|
std::string *error);
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,37 @@ bool file_mode_enabled() {
|
|||||||
return std::getenv("CNC_SIM_RS274_FILE_MODE") != nullptr;
|
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
|
#ifndef CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE
|
||||||
bool write_temp_program(const char *program,
|
bool write_temp_program(const char *program,
|
||||||
size_t program_len,
|
size_t program_len,
|
||||||
@@ -175,6 +206,7 @@ int execute_file_mode(InterpBase *interp,
|
|||||||
int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
||||||
const char *program,
|
const char *program,
|
||||||
size_t program_len,
|
size_t program_len,
|
||||||
|
const GcodeBackendOptions &options,
|
||||||
std::string *error) {
|
std::string *error) {
|
||||||
if (!program && program_len != 0) {
|
if (!program && program_len != 0) {
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -183,14 +215,39 @@ int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LinuxCNC source basis: rs274ngc_pre.cc uses
|
||||||
|
// RS274NGC_PARAMETER_FILE_NAME_DEFAULT when the external parameter file
|
||||||
|
// name is empty. Reset the bridge every parse so a prior native env
|
||||||
|
// override does not leak into later default parses.
|
||||||
if (const char *parameter_file = std::getenv("CNC_SIM_RS274_VAR")) {
|
if (const char *parameter_file = std::getenv("CNC_SIM_RS274_VAR")) {
|
||||||
SET_PARAMETER_FILE_NAME(parameter_file);
|
SET_PARAMETER_FILE_NAME(parameter_file);
|
||||||
|
} else {
|
||||||
|
SET_PARAMETER_FILE_NAME("rs274ngc.var");
|
||||||
}
|
}
|
||||||
cnc_sim_init_minimal_linuxcnc_tooldata();
|
cnc_sim_init_minimal_linuxcnc_tooldata();
|
||||||
sink.clear_callback_status();
|
sink.clear_callback_status();
|
||||||
cnc_sim_linuxcnc_set_canon_sink(&sink);
|
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();
|
InterpBase *interp = makeInterp();
|
||||||
|
if (!options.ini_file_name.empty()) {
|
||||||
|
// LinuxCNC source basis: emctask.cc calls Interp::ini_load() before
|
||||||
|
// Interp::init(), and rs274ngc_pre.cc ini_load() maps
|
||||||
|
// [RS274NGC] PARAMETER_FILE through SET_PARAMETER_FILE_NAME().
|
||||||
|
if (interp->ini_load(options.ini_file_name.c_str()) != INTERP_OK) {
|
||||||
|
if (error) {
|
||||||
|
*error = "ini_load failed: " + options.ini_file_name;
|
||||||
|
}
|
||||||
|
delete interp;
|
||||||
|
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (const char *parameter_file = std::getenv("CNC_SIM_RS274_VAR")) {
|
||||||
|
SET_PARAMETER_FILE_NAME(parameter_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
int status = interp->init();
|
int status = interp->init();
|
||||||
if (status != INTERP_OK) {
|
if (status != INTERP_OK) {
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "canon_event_sink.h"
|
#include "canon_event_sink.h"
|
||||||
|
#include "gcode_backend.h"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -8,5 +9,5 @@
|
|||||||
int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
||||||
const char *program,
|
const char *program,
|
||||||
size_t program_len,
|
size_t program_len,
|
||||||
|
const GcodeBackendOptions &options,
|
||||||
std::string *error);
|
std::string *error);
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,11 @@
|
|||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <system_error>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -61,6 +64,34 @@ private:
|
|||||||
std::string old_;
|
std::string old_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ScopedTempDir {
|
||||||
|
public:
|
||||||
|
explicit ScopedTempDir(const char *prefix) {
|
||||||
|
const char *tmpdir = std::getenv("TMPDIR");
|
||||||
|
std::string tmpl = std::string(tmpdir ? tmpdir : "/tmp") + "/" + prefix + ".XXXXXX";
|
||||||
|
std::vector<char> buffer(tmpl.begin(), tmpl.end());
|
||||||
|
buffer.push_back('\0');
|
||||||
|
char *dir = mkdtemp(buffer.data());
|
||||||
|
if (!dir) {
|
||||||
|
std::perror("mkdtemp");
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
path_ = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ScopedTempDir() {
|
||||||
|
std::error_code error;
|
||||||
|
std::filesystem::remove_all(path_, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string file(const char *name) const {
|
||||||
|
return path_ + "/" + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string path_;
|
||||||
|
};
|
||||||
|
|
||||||
bool saw_comment_state(const std::vector<CncSimEvent> &events,
|
bool saw_comment_state(const std::vector<CncSimEvent> &events,
|
||||||
int line,
|
int line,
|
||||||
int reserved,
|
int reserved,
|
||||||
@@ -168,6 +199,8 @@ bool expect_switchkins_remap_config(const std::string &json,
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
ScopedTempDir temp_dir("cnc_sim_api_linuxcnc_rs274_smoke");
|
||||||
|
|
||||||
{
|
{
|
||||||
std::vector<CncSimEvent> default_events;
|
std::vector<CncSimEvent> default_events;
|
||||||
CncSimHandle *default_sim = cnc_sim_create();
|
CncSimHandle *default_sim = cnc_sim_create();
|
||||||
@@ -196,6 +229,67 @@ int main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string ini_parameter_var_path = temp_dir.file("ini_parameter.var");
|
||||||
|
{
|
||||||
|
std::ofstream var_file(ini_parameter_var_path);
|
||||||
|
var_file << "5001\t44.000000\n";
|
||||||
|
}
|
||||||
|
const std::string rs274_ini_path = temp_dir.file("rs274_parameter.ini");
|
||||||
|
{
|
||||||
|
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<CncSimEvent> ini_events;
|
||||||
|
CncSimHandle *ini_sim = cnc_sim_create();
|
||||||
|
cnc_sim_set_event_callback(ini_sim, collect_event, &ini_events);
|
||||||
|
const std::string ini_config =
|
||||||
|
std::string("{\"backend\":\"linuxcnc-rs274\",\"iniFileName\":\"") +
|
||||||
|
rs274_ini_path +
|
||||||
|
"\"}";
|
||||||
|
bool ini_ok = true;
|
||||||
|
ini_ok &= expect(cnc_sim_load_config_json(ini_sim, ini_config.c_str(), ini_config.size()) == 0,
|
||||||
|
cnc_sim_last_error(ini_sim));
|
||||||
|
ScopedEnv file_mode_env("CNC_SIM_RS274_FILE_MODE", "1");
|
||||||
|
const char ini_parameter_check_program[] =
|
||||||
|
"G21 G90 G17\n"
|
||||||
|
"F100\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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char config[] =
|
const char config[] =
|
||||||
"{\"backend\":\"linuxcnc-rs274\",\"rtcp\":{\"enabled\":true,\"toolLength\":100,\"toolLengths\":{\"7\":125}}}";
|
"{\"backend\":\"linuxcnc-rs274\",\"rtcp\":{\"enabled\":true,\"toolLength\":100,\"toolLengths\":{\"7\":125}}}";
|
||||||
const char program[] =
|
const char program[] =
|
||||||
|
|||||||
@@ -6163,6 +6163,48 @@ int main() {
|
|||||||
"expected LinuxCNC rotary/UVW persistent numbered parameters to reload from parameter file");
|
"expected LinuxCNC rotary/UVW persistent numbered parameters to reload from parameter file");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string parameter_env_leak_guard_var_path = temp_dir.file("parameter_env_leak_guard.var");
|
||||||
|
{
|
||||||
|
std::ofstream var_file(parameter_env_leak_guard_var_path);
|
||||||
|
var_file << "5001\t17.000000\n";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ScopedEnv var_env("CNC_SIM_RS274_VAR", parameter_env_leak_guard_var_path.c_str());
|
||||||
|
const char parameter_env_leak_guard_set_program[] =
|
||||||
|
"#5001 = 91\n"
|
||||||
|
"M30\n";
|
||||||
|
events.clear();
|
||||||
|
ok &= expect(cnc_sim_parse_program(sim,
|
||||||
|
parameter_env_leak_guard_set_program,
|
||||||
|
sizeof(parameter_env_leak_guard_set_program) - 1) == 0,
|
||||||
|
cnc_sim_last_error(sim));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const char parameter_env_default_check_program[] =
|
||||||
|
"F100\n"
|
||||||
|
"O10 if [#5001 EQ 91]\n"
|
||||||
|
"G1 X1\n"
|
||||||
|
"O10 endif\n";
|
||||||
|
events.clear();
|
||||||
|
ok &= expect(cnc_sim_parse_program(sim,
|
||||||
|
parameter_env_default_check_program,
|
||||||
|
sizeof(parameter_env_default_check_program) - 1) == 0,
|
||||||
|
cnc_sim_last_error(sim));
|
||||||
|
bool saw_stale_env_parameter = false;
|
||||||
|
for (const auto &event : events) {
|
||||||
|
saw_stale_env_parameter = saw_stale_env_parameter ||
|
||||||
|
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||||
|
event.line == 3 &&
|
||||||
|
near(event.end.x, 1.0));
|
||||||
|
}
|
||||||
|
// LinuxCNC source basis: rs274ngc_pre.cc rs274_ngc_init() falls back
|
||||||
|
// to RS274NGC_PARAMETER_FILE_NAME_DEFAULT when the external parameter
|
||||||
|
// file name is empty. The project env override must not persist after
|
||||||
|
// CNC_SIM_RS274_VAR is unset.
|
||||||
|
ok &= expect(!saw_stale_env_parameter,
|
||||||
|
"expected LinuxCNC parameter env override not to leak into default parses");
|
||||||
|
}
|
||||||
|
|
||||||
const char volatile_global_set_program[] =
|
const char volatile_global_set_program[] =
|
||||||
"#31 = 7\n"
|
"#31 = 7\n"
|
||||||
"M30\n";
|
"M30\n";
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ set -euo pipefail
|
|||||||
|
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc and
|
||||||
|
# python_plugin.hh define the PythonPlugin API covered by this wrapper.
|
||||||
probe=$(./build-linuxcnc-wasm-standalone-probe.sh --mode python-plugin-link)
|
probe=$(./build-linuxcnc-wasm-standalone-probe.sh --mode python-plugin-link)
|
||||||
|
|
||||||
"$probe"
|
"$probe"
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ set -euo pipefail
|
|||||||
|
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc provides the Interp
|
||||||
|
# init/read/execute path exercised by the source-linked probe main.
|
||||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||||
|
|
||||||
preflight_cache_dir=${CNC_SIM_PREFLIGHT_CACHE_DIR:-build/wasm-probe-preflight-cache}
|
preflight_cache_dir=${CNC_SIM_PREFLIGHT_CACHE_DIR:-build/wasm-probe-preflight-cache}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ set -euo pipefail
|
|||||||
|
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc is compiled directly
|
||||||
|
# here so wasm-safe object coverage cannot drift away from the Interp source.
|
||||||
./build-linuxcnc-wasm-standalone-probe.sh --mode rs274ngc-pre-object >/dev/null
|
./build-linuxcnc-wasm-standalone-probe.sh --mode rs274ngc-pre-object >/dev/null
|
||||||
|
|
||||||
echo "linuxcnc wasm rs274ngc_pre object probe passed"
|
echo "linuxcnc wasm rs274ngc_pre object probe passed"
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ set -euo pipefail
|
|||||||
|
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc provides read() and
|
||||||
|
# execute(), interp_convert.cc converts G0/G2/M30, and emcops.cc/dummyemcstat.cc
|
||||||
|
# provide the EMC status symbols required by this runtime link probe.
|
||||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||||
|
|
||||||
preflight_cache_dir=${CNC_SIM_PREFLIGHT_CACHE_DIR:-build/wasm-probe-preflight-cache}
|
preflight_cache_dir=${CNC_SIM_PREFLIGHT_CACHE_DIR:-build/wasm-probe-preflight-cache}
|
||||||
|
|||||||
@@ -54,6 +54,14 @@ grep -F 'metadata:src/emc/tooldata/tooldata_nml.cc:source basis for wasm-safe to
|
|||||||
grep -F 'LinuxCNC source basis: this probe derives required Python C API exports from' test-linuxcnc-wasm-python-c-api-symbols.sh >/dev/null
|
grep -F 'LinuxCNC source basis: this probe derives required Python C API exports from' test-linuxcnc-wasm-python-c-api-symbols.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: this probe compares wasm-safe tooldata runtime stubs' test-linuxcnc-wasm-tooldata-runtime-symbols.sh >/dev/null
|
grep -F 'LinuxCNC source basis: this probe compares wasm-safe tooldata runtime stubs' test-linuxcnc-wasm-tooldata-runtime-symbols.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: the standalone probe links src/emc/rs274ngc/interp_base.cc' test-linuxcnc-wasm-interp-base-link.sh >/dev/null
|
grep -F 'LinuxCNC source basis: the standalone probe links src/emc/rs274ngc/interp_base.cc' test-linuxcnc-wasm-interp-base-link.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc and' test-linuxcnc-wasm-python-plugin-link.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc is compiled directly' test-linuxcnc-wasm-rs274ngc-pre-object.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc provides the Interp' test-linuxcnc-wasm-rs274ngc-pre-link.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc provides read()' test-linuxcnc-wasm-runtime-link.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: standalone probe modes either compile LinuxCNC' build-linuxcnc-wasm-standalone-probe.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: link probe modes reuse wasm-safe objects built from' build-linuxcnc-wasm-link-probe.sh >/dev/null
|
||||||
|
grep -F 'grep -F '\''LinuxCNC source basis: src/emc/rs274ngc/rs274ngc_pre.cc provides'\'' "$main_source" >/dev/null' build-linuxcnc-wasm-link-probe.sh >/dev/null
|
||||||
|
grep -F 'core:src/emc/rs274ngc/rs274ngc_pre.cc:Interp implementation covered by rs274ngc_pre link probe' build-linuxcnc-wasm-standalone-probe.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: linuxcnc-rs274-source-files.txt enumerates the native' list-linuxcnc-source-manifest-sources.sh >/dev/null
|
grep -F 'LinuxCNC source basis: linuxcnc-rs274-source-files.txt enumerates the native' list-linuxcnc-source-manifest-sources.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: native source-link support objects come from the' list-linuxcnc-source-support-objects.sh >/dev/null
|
grep -F 'LinuxCNC source basis: native source-link support objects come from the' list-linuxcnc-source-support-objects.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: this probe compiles the core RS274 interpreter sources' test-linuxcnc-source-objects.sh >/dev/null
|
grep -F 'LinuxCNC source basis: this probe compiles the core RS274 interpreter sources' test-linuxcnc-source-objects.sh >/dev/null
|
||||||
@@ -79,6 +87,12 @@ grep -F 'metadata:src/emc/task/taskclass.cc:source basis for wasm-safe builtin P
|
|||||||
grep -F 'metadata:src/emc/task/emccanon.cc:source basis for wasm-safe tooldata API declaration shim' linuxcnc-rs274-wasm-source-files.txt >/dev/null
|
grep -F 'metadata:src/emc/task/emccanon.cc:source basis for wasm-safe tooldata API declaration shim' linuxcnc-rs274-wasm-source-files.txt >/dev/null
|
||||||
grep -F 'metadata:src/emc/sai/dummyemcstat.cc:source basis for wasm-safe emcStatus singleton shim' linuxcnc-rs274-wasm-source-files.txt >/dev/null
|
grep -F 'metadata:src/emc/sai/dummyemcstat.cc:source basis for wasm-safe emcStatus singleton shim' linuxcnc-rs274-wasm-source-files.txt >/dev/null
|
||||||
grep -F 'blocked:src/emc/rs274ngc/gcodemodule.cc:Python gcode module binding, tracked for full rs274ngc source coverage' linuxcnc-rs274-wasm-source-files.txt >/dev/null
|
grep -F 'blocked:src/emc/rs274ngc/gcodemodule.cc:Python gcode module binding, tracked for full rs274ngc source coverage' linuxcnc-rs274-wasm-source-files.txt >/dev/null
|
||||||
|
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/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/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
|
grep -F 'metadata:src/emc/sai/Submakefile:LinuxCNC SAI build metadata defining dummyemcstat support object' linuxcnc-rs274-source-files.txt >/dev/null
|
||||||
|
|||||||
Reference in New Issue
Block a user