按规划持续工作

结论:已接通 vendored LinuxCNC interp_remap.cc 的 NGC REMAP 描述符解析路径,新增 native harness 验证 xyzac/xyzbc 的 M428/M429/M430 映射,未实现自写 M 码语义。
This commit is contained in:
2026-06-08 15:54:07 +08:00
parent 5df62ad60a
commit 3a58f1e495
9 changed files with 300 additions and 11 deletions

View File

@@ -0,0 +1,41 @@
#include <string>
#define private public
#include "emc/rs274ngc/rs274ngc_interp.hh"
#undef private
#include "emc/rs274ngc/rs274ngc_return.hh"
#include "interp_python.hh"
#include "pythonplugin/python_plugin.hh"
PythonPlugin *python_plugin = nullptr;
int _task = 0;
struct _inittab {
const char *name;
void *initfunc;
};
_inittab builtin_modules[] = {{nullptr, nullptr}};
InterpBase::~InterpBase() {}
PythonPlugin *PythonPlugin::instantiate(struct _inittab *)
{
static PythonPlugin standalone_plugin;
python_plugin = &standalone_plugin;
return python_plugin;
}
std::string handle_pyerror()
{
return {};
}
bool Interp::is_pycallable(setup_pointer, const char *, const char *) { return false; }
int Interp::pycall(setup_pointer, context_pointer, const char *, const char *, int)
{
return INTERP_ERROR;
}
int Interp::py_execute(const char *, bool) { return INTERP_ERROR; }
int Interp::py_reload() { return INTERP_OK; }

View File

@@ -0,0 +1,146 @@
#define private public
#include "emc/rs274ngc/rs274ngc_interp.hh"
#undef private
#include <cstring>
#include <cstdio>
#include <filesystem>
#include <iostream>
#include <string>
#include <vector>
#include "emc/ini/inifile.hh"
#include "emc/rs274ngc/interp_internal.hh"
#include "emc/rs274ngc/rs274ngc_return.hh"
#ifndef LINUXCNC_VENDOR_DIR
#error "LINUXCNC_VENDOR_DIR must point at wasm-port/vendor/linuxcnc"
#endif
namespace {
struct ExpectedRemap {
int mcode;
const char *name;
const char *ngc;
};
struct MachineCase {
const char *label;
const char *ini_rel;
std::vector<ExpectedRemap> expected;
};
std::filesystem::path vendor_path(const std::string &rel)
{
return std::filesystem::path(LINUXCNC_VENDOR_DIR) / rel;
}
void print_bool(const std::string &name, bool value)
{
std::cout << name << "=" << (value ? 1 : 0) << "\n";
}
bool check_remap(Interp &interp, const std::string &label, const ExpectedRemap &expected)
{
const auto by_name = interp.remapping(expected.name);
const auto by_mcode = interp._setup.m_remapped[expected.mcode];
const bool name_ok = by_name != nullptr;
const bool mcode_ok = by_mcode != nullptr && by_mcode == by_name;
const bool ngc_ok = by_mcode != nullptr && by_mcode->remap_ngc != nullptr &&
std::strcmp(by_mcode->remap_ngc, expected.ngc) == 0;
const bool modal_group_ok = by_mcode != nullptr && by_mcode->modal_group == 10;
const bool no_python_ok = by_mcode != nullptr && by_mcode->remap_py == nullptr &&
by_mcode->prolog_func == nullptr &&
by_mcode->epilog_func == nullptr;
const bool mcode_remappable = interp.is_m_code_remappable(expected.mcode);
const std::string prefix = label + "_" + expected.name;
print_bool(prefix + "_name_lookup", name_ok);
print_bool(prefix + "_mcode_lookup", mcode_ok);
print_bool(prefix + "_ngc", ngc_ok);
print_bool(prefix + "_modalgroup10", modal_group_ok);
print_bool(prefix + "_no_python", no_python_ok);
print_bool(prefix + "_linuxcnc_mcode_remappable", mcode_remappable);
return name_ok && mcode_ok && ngc_ok && modal_group_ok && no_python_ok &&
mcode_remappable;
}
bool check_machine(const MachineCase &machine)
{
const auto ini_path = vendor_path(machine.ini_rel);
const auto machine_dir = ini_path.parent_path();
const auto remap_dir = machine_dir / "remap_subs";
linuxcnc::IniFile ini(ini_path.string());
const bool opened = static_cast<bool>(ini);
print_bool(std::string(machine.label) + "_ini_open", opened);
if (!opened) {
return false;
}
Interp interp;
std::snprintf(interp._setup.program_prefix, sizeof(interp._setup.program_prefix), "%s",
machine_dir.c_str());
interp._setup.subroutines[0] = strstore(remap_dir.c_str());
bool ok = true;
int remap_count = 0;
int line_number = 0;
while (auto remap = ini.findString(++remap_count, "REMAP", "RS274NGC")) {
line_number = ini.lineOf(remap_count, "REMAP", "RS274NGC").second;
const int rc = interp.parse_remap(remap->c_str(), line_number);
std::cout << machine.label << "_parse_remap_" << remap_count << "=" << rc << "\n";
ok &= rc == INTERP_OK;
}
remap_count -= 1;
std::cout << machine.label << "_parsed_remap_count=" << remap_count << "\n";
ok &= remap_count == static_cast<int>(machine.expected.size());
std::cout << machine.label << "_m_remapped_count=" << interp._setup.m_remapped.size()
<< "\n";
ok &= interp._setup.m_remapped.size() == machine.expected.size();
for (const auto &expected : machine.expected) {
ok &= check_remap(interp, machine.label, expected);
}
print_bool(std::string(machine.label) + "_linuxcnc_ngc_remaps_parsed", ok);
return ok;
}
} // namespace
int main()
{
const MachineCase cases[] = {
{
"xyzac_trt",
"configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini",
{
{428, "M428", "428remap"},
{429, "M429", "429remap"},
{430, "M430", "430remap"},
},
},
{
"xyzbc_trt",
"configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini",
{
{428, "M428", "428remap"},
{429, "M429", "429remap"},
{430, "M430", "430remap"},
},
},
};
bool ok = true;
for (const auto &machine : cases) {
ok &= check_machine(machine);
}
print_bool("fiveaxis_linuxcnc_remap_parse_path", ok);
return ok ? 0 : 1;
}