继续把 interp_execute.cc、interp_queue.cc、interp_find.cc 等 LinuxCNC 源文件纳入直接编译/链接路径,逐步删除临时 convert_g() wrapper 行为
结论:已将核心 LinuxCNC interpreter 源接入 standalone native 编译链接路径,移除 minimal runtime 中的手写 convert_g 行为,并通过 native probe 验证。
This commit is contained in:
12
wasm-port/runtime/core/include/canon_event_sink.hh
Normal file
12
wasm-port/runtime/core/include/canon_event_sink.hh
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace standalone {
|
||||
|
||||
void reset_canon_events();
|
||||
void push_canon_event(const std::string &event);
|
||||
const std::vector<std::string> &canon_events();
|
||||
|
||||
} // namespace standalone
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "nml_intf/emc.hh"
|
||||
|
||||
static EMC_STAT standalone_emc_status;
|
||||
EMC_STAT *emcStatus = &standalone_emc_status;
|
||||
32
wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_ini_probe.cpp
Normal file
32
wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_ini_probe.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "emc/ini/inifile.hh"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "usage: linuxcnc_ini_probe <ini-file>\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
const char *ini_path = argv[1];
|
||||
linuxcnc::IniFile ini(ini_path);
|
||||
if (!ini) {
|
||||
std::cerr << "failed to open ini file: " << ini_path << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const auto machine = ini.findString("MACHINE", "EMC");
|
||||
const auto display = ini.findString("DISPLAY", "DISPLAY");
|
||||
const auto kins = ini.findString("KINEMATICS", "KINS");
|
||||
const auto coords = ini.findString("COORDINATES", "TRAJ");
|
||||
const auto parameter_file = ini.findString("PARAMETER_FILE", "RS274NGC");
|
||||
|
||||
std::cout << "EMC.MACHINE=" << (machine ? *machine : "<missing>") << "\n";
|
||||
std::cout << "DISPLAY.DISPLAY=" << (display ? *display : "<missing>") << "\n";
|
||||
std::cout << "KINS.KINEMATICS=" << (kins ? *kins : "<missing>") << "\n";
|
||||
std::cout << "TRAJ.COORDINATES=" << (coords ? *coords : "<missing>") << "\n";
|
||||
std::cout << "RS274NGC.PARAMETER_FILE=" << (parameter_file ? *parameter_file : "<missing>") << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
21
wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_ini_wasm.cpp
Normal file
21
wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_ini_wasm.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <emscripten/emscripten.h>
|
||||
|
||||
#include "emc/ini/inifile.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int lcini_get_string(const char *inipath,
|
||||
const char *section,
|
||||
const char *tag,
|
||||
char *buf,
|
||||
int bufsize) {
|
||||
return iniFindString(inipath, tag, section, buf, static_cast<size_t>(bufsize));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int lcini_tilde_expand(const char *path, char *buf, int bufsize) {
|
||||
return TildeExpansion(path, buf, static_cast<size_t>(bufsize));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
#define private public
|
||||
#include "emc/rs274ngc/rs274ngc_interp.hh"
|
||||
#undef private
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "canon_event_sink.hh"
|
||||
|
||||
namespace {
|
||||
|
||||
void initialize_minimal_interp(Interp &interp)
|
||||
{
|
||||
interp._setup.length_units = CANON_UNITS_MM;
|
||||
interp._setup.distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
interp._setup.ijk_distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
interp._setup.feed_mode = FEED_MODE::UNITS_PER_MINUTE;
|
||||
interp._setup.plane = CANON_PLANE::XY;
|
||||
interp._setup.motion_mode = G_0;
|
||||
interp._setup.percent_flag = false;
|
||||
interp._setup.sequence_number = 0;
|
||||
interp._setup.parameter_occurrence = 0;
|
||||
std::memcpy(interp._readers, Interp::default_readers, sizeof(Interp::default_readers));
|
||||
}
|
||||
|
||||
std::vector<std::string> load_program(int argc, char **argv)
|
||||
{
|
||||
if (argc <= 1) {
|
||||
return {
|
||||
"G0 X1.0 Y2.0 (Comment)\n",
|
||||
"G1 X3.0 Y4.0 F120.0\n",
|
||||
};
|
||||
}
|
||||
|
||||
std::ifstream input(argv[1]);
|
||||
if (!input) {
|
||||
std::cerr << "failed to open fixture: " << argv[1] << "\n";
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
std::vector<std::string> lines;
|
||||
std::string line;
|
||||
while (std::getline(input, line)) {
|
||||
if (!line.empty()) {
|
||||
lines.push_back(line + "\n");
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Interp interp;
|
||||
standalone::reset_canon_events();
|
||||
initialize_minimal_interp(interp);
|
||||
|
||||
const std::vector<std::string> program = load_program(argc, argv);
|
||||
if (program.empty()) {
|
||||
std::cerr << "empty fixture\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
char line[LINELEN] = {0};
|
||||
std::strncpy(line, program.front().c_str(), sizeof(line) - 1);
|
||||
char raw_line[LINELEN] = {0};
|
||||
char cooked_line[LINELEN] = {0};
|
||||
int length = -1;
|
||||
|
||||
const int read_text_rc = interp.read_text(line, nullptr, raw_line, cooked_line, &length);
|
||||
const int downcase_rc = interp.close_and_downcase(line);
|
||||
const int read_rc = interp.read(program.front().c_str());
|
||||
|
||||
initialize_minimal_interp(interp);
|
||||
for (std::size_t idx = 0; idx < program.size(); ++idx) {
|
||||
interp._setup.sequence_number = static_cast<int>(idx + 1);
|
||||
const int execute_rc = interp.execute(program[idx].c_str());
|
||||
std::cout << "execute_line_" << (idx + 1) << "=" << execute_rc << "\n";
|
||||
}
|
||||
|
||||
block block{};
|
||||
const int init_block_rc = interp.init_block(&block);
|
||||
int parse_line_rc = INTERP_ERROR;
|
||||
if (read_text_rc == INTERP_OK) {
|
||||
parse_line_rc = interp.parse_line(cooked_line, &block, &interp._setup);
|
||||
}
|
||||
|
||||
std::cout << "read_text=" << read_text_rc << "\n";
|
||||
std::cout << "raw_line=" << raw_line << "\n";
|
||||
std::cout << "cooked_line=" << cooked_line << "\n";
|
||||
std::cout << "line_length=" << length << "\n";
|
||||
std::cout << "read=" << read_rc << "\n";
|
||||
std::cout << "setup.linetext=" << interp._setup.linetext << "\n";
|
||||
std::cout << "setup.blocktext=" << interp._setup.blocktext << "\n";
|
||||
std::cout << "setup.line_length=" << interp._setup.line_length << "\n";
|
||||
std::cout << "setup.sequence_number=" << interp._setup.sequence_number << "\n";
|
||||
std::cout << "setup.current_x=" << interp._setup.current_x << "\n";
|
||||
std::cout << "setup.current_y=" << interp._setup.current_y << "\n";
|
||||
std::cout << "setup.current_z=" << interp._setup.current_z << "\n";
|
||||
std::cout << "setup.parameter_5420=" << interp._setup.parameters[5420] << "\n";
|
||||
std::cout << "setup.parameter_5421=" << interp._setup.parameters[5421] << "\n";
|
||||
std::cout << "setup.parameter_5422=" << interp._setup.parameters[5422] << "\n";
|
||||
std::cout << "setup.feed_rate=" << interp._setup.feed_rate << "\n";
|
||||
std::cout << "close_and_downcase=" << downcase_rc << "\n";
|
||||
std::cout << "normalized_line=" << line << "\n";
|
||||
std::cout << "init_block=" << init_block_rc << "\n";
|
||||
std::cout << "parse_line=" << parse_line_rc << "\n";
|
||||
std::cout << "block.motion_to_be=" << block.motion_to_be << "\n";
|
||||
std::cout << "block.g_modes[GM_MOTION]=" << block.g_modes[GM_MOTION] << "\n";
|
||||
std::cout << "block.x_flag=" << block.x_flag << " x=" << block.x_number << "\n";
|
||||
std::cout << "block.y_flag=" << block.y_flag << " y=" << block.y_number << "\n";
|
||||
std::cout << "executing_block.motion_to_be=" << EXECUTING_BLOCK(interp._setup).motion_to_be << "\n";
|
||||
std::cout << "executing_block.g_modes[GM_MOTION]=" << EXECUTING_BLOCK(interp._setup).g_modes[GM_MOTION] << "\n";
|
||||
std::cout << "executing_block.x_flag=" << EXECUTING_BLOCK(interp._setup).x_flag
|
||||
<< " x=" << EXECUTING_BLOCK(interp._setup).x_number << "\n";
|
||||
std::cout << "executing_block.y_flag=" << EXECUTING_BLOCK(interp._setup).y_flag
|
||||
<< " y=" << EXECUTING_BLOCK(interp._setup).y_number << "\n";
|
||||
std::cout << "executing_block.f_flag=" << EXECUTING_BLOCK(interp._setup).f_flag
|
||||
<< " f=" << EXECUTING_BLOCK(interp._setup).f_number << "\n";
|
||||
std::cout << "call_level=" << interp.call_level() << "\n";
|
||||
std::cout << "loggingLevel=" << interp._setup.loggingLevel << "\n";
|
||||
std::cout << "canon_event_count=" << standalone::canon_events().size() << "\n";
|
||||
for (const auto &event : standalone::canon_events()) {
|
||||
std::cout << "canon_event=" << event << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,564 @@
|
||||
#include <cstdarg>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define private public
|
||||
#include "emc/rs274ngc/rs274ngc_interp.hh"
|
||||
#undef private
|
||||
|
||||
#include "emc/rs274ngc/rs274ngc_return.hh"
|
||||
#include "canon_event_sink.hh"
|
||||
|
||||
PythonPlugin *python_plugin = nullptr;
|
||||
|
||||
namespace standalone {
|
||||
|
||||
static std::vector<std::string> g_canon_events;
|
||||
|
||||
void reset_canon_events()
|
||||
{
|
||||
g_canon_events.clear();
|
||||
}
|
||||
|
||||
void push_canon_event(const std::string &event)
|
||||
{
|
||||
g_canon_events.push_back(event);
|
||||
}
|
||||
|
||||
const std::vector<std::string> &canon_events()
|
||||
{
|
||||
return g_canon_events;
|
||||
}
|
||||
|
||||
} // namespace standalone
|
||||
|
||||
bool GET_BLOCK_DELETE(void) { return false; }
|
||||
void FINISH(void) {}
|
||||
void ON_RESET(void) {}
|
||||
|
||||
USER_DEFINED_FUNCTION_TYPE USER_DEFINED_FUNCTION[USER_DEFINED_FUNCTION_NUM] = {};
|
||||
|
||||
int USER_DEFINED_FUNCTION_ADD(USER_DEFINED_FUNCTION_TYPE func, int num)
|
||||
{
|
||||
if ((num < 0) || (num >= USER_DEFINED_FUNCTION_NUM)) {
|
||||
return -1;
|
||||
}
|
||||
USER_DEFINED_FUNCTION[num] = func;
|
||||
return num;
|
||||
}
|
||||
|
||||
void INIT_CANON() {}
|
||||
void SET_G5X_OFFSET(int, double, double, double, double, double, double, double, double, double) {}
|
||||
void SET_G92_OFFSET(double, double, double, double, double, double, double, double, double) {}
|
||||
void SET_XY_ROTATION(double) {}
|
||||
void CANON_UPDATE_END_POINT(double, double, double, double, double, double, double, double, double) {}
|
||||
void USE_LENGTH_UNITS(CANON_UNITS) {}
|
||||
void SELECT_PLANE(CANON_PLANE) {}
|
||||
void SET_TRAVERSE_RATE(double) {}
|
||||
void SET_FEED_REFERENCE(CANON_FEED_REFERENCE) {}
|
||||
void SET_FEED_MODE(int, int) {}
|
||||
void SET_MOTION_CONTROL_MODE(CANON_MOTION_MODE, double) {}
|
||||
void SET_NAIVECAM_TOLERANCE(double) {}
|
||||
void SET_CUTTER_RADIUS_COMPENSATION(double) {}
|
||||
void START_CUTTER_RADIUS_COMPENSATION(int) {}
|
||||
void STOP_CUTTER_RADIUS_COMPENSATION() {}
|
||||
void START_SPEED_FEED_SYNCH(int, double, bool) {}
|
||||
void STOP_SPEED_FEED_SYNCH() {}
|
||||
void RIGID_TAP(int, double, double, double, double) {}
|
||||
void STRAIGHT_PROBE(int, double, double, double, double, double, double, double, double, double, unsigned char) {}
|
||||
void STOP() {}
|
||||
void DWELL(double) {}
|
||||
void SET_SPINDLE_MODE(int, double) {}
|
||||
void SPINDLE_RETRACT_TRAVERSE() {}
|
||||
void START_SPINDLE_CLOCKWISE(int, int) {}
|
||||
void START_SPINDLE_COUNTERCLOCKWISE(int, int) {}
|
||||
void SET_SPINDLE_SPEED(int, double) {}
|
||||
void STOP_SPINDLE_TURNING(int) {}
|
||||
void SPINDLE_RETRACT() {}
|
||||
void ORIENT_SPINDLE(int, double, int) {}
|
||||
void WAIT_SPINDLE_ORIENT_COMPLETE(int, double) {}
|
||||
void LOCK_SPINDLE_Z() {}
|
||||
void USE_SPINDLE_FORCE() {}
|
||||
void USE_NO_SPINDLE_FORCE() {}
|
||||
void SET_TOOL_TABLE_ENTRY(int, int, const EmcPose &, double, double, double, int) {}
|
||||
void USE_TOOL_LENGTH_OFFSET(const EmcPose &) {}
|
||||
void CHANGE_TOOL() {}
|
||||
void SELECT_TOOL(int) {}
|
||||
void CHANGE_TOOL_NUMBER(int) {}
|
||||
void RELOAD_TOOLDATA(void) {}
|
||||
void CLAMP_AXIS(CANON_AXIS) {}
|
||||
void DISABLE_ADAPTIVE_FEED() {}
|
||||
void ENABLE_ADAPTIVE_FEED() {}
|
||||
void DISABLE_FEED_OVERRIDE() {}
|
||||
void ENABLE_FEED_OVERRIDE() {}
|
||||
void DISABLE_SPEED_OVERRIDE(int) {}
|
||||
void ENABLE_SPEED_OVERRIDE(int) {}
|
||||
void DISABLE_FEED_HOLD() {}
|
||||
void ENABLE_FEED_HOLD() {}
|
||||
void FLOOD_OFF() {}
|
||||
void FLOOD_ON() {}
|
||||
void MIST_OFF() {}
|
||||
void MIST_ON() {}
|
||||
void PALLET_SHUTTLE() {}
|
||||
void TURN_PROBE_OFF() {}
|
||||
void TURN_PROBE_ON() {}
|
||||
void UNCLAMP_AXIS(CANON_AXIS) {}
|
||||
void NURB_KNOT_VECTOR() {}
|
||||
void NURB_CONTROL_POINT(int, double, double, double, double) {}
|
||||
void NURB_FEED(double, double) {}
|
||||
void SET_BLOCK_DELETE(bool) {}
|
||||
void OPTIONAL_PROGRAM_STOP() {}
|
||||
void SET_OPTIONAL_PROGRAM_STOP(bool) {}
|
||||
bool GET_OPTIONAL_PROGRAM_STOP() { return false; }
|
||||
void PROGRAM_END() {}
|
||||
void PROGRAM_STOP() {}
|
||||
void SET_MOTION_OUTPUT_BIT(int) {}
|
||||
void CLEAR_MOTION_OUTPUT_BIT(int) {}
|
||||
void SET_AUX_OUTPUT_BIT(int) {}
|
||||
void CLEAR_AUX_OUTPUT_BIT(int) {}
|
||||
void SET_MOTION_OUTPUT_VALUE(int, double) {}
|
||||
void SET_AUX_OUTPUT_VALUE(int, double) {}
|
||||
int WAIT(int, int, int, double) { return 0; }
|
||||
int UNLOCK_ROTARY(int, int) { return 0; }
|
||||
int LOCK_ROTARY(int, int) { return 0; }
|
||||
void UPDATE_TAG(const StateTag &) {}
|
||||
|
||||
void MESSAGE(char *s) { standalone::push_canon_event(std::string("MESSAGE: ") + (s ? s : "")); }
|
||||
void LOG(char *) {}
|
||||
void LOGOPEN(char *) {}
|
||||
void LOGAPPEND(char *) {}
|
||||
void LOGCLOSE() {}
|
||||
|
||||
void CANON_ERROR(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fputc('\n', stderr);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
double GET_EXTERNAL_FEED_RATE() { return 0.0; }
|
||||
int GET_EXTERNAL_FLOOD() { return 0; }
|
||||
double GET_EXTERNAL_LENGTH_UNITS() { return CANON_UNITS_MM; }
|
||||
double GET_EXTERNAL_ANGLE_UNITS() { return 1.0; }
|
||||
int GET_EXTERNAL_MIST() { return 0; }
|
||||
CANON_MOTION_MODE GET_EXTERNAL_MOTION_CONTROL_MODE() { return CANON_EXACT_STOP; }
|
||||
double GET_EXTERNAL_MOTION_CONTROL_TOLERANCE() { return 0.0; }
|
||||
double GET_EXTERNAL_MOTION_CONTROL_NAIVECAM_TOLERANCE() { return 0.0; }
|
||||
double GET_EXTERNAL_ORIGIN_A() { return 0.0; }
|
||||
double GET_EXTERNAL_ORIGIN_B() { return 0.0; }
|
||||
double GET_EXTERNAL_ORIGIN_C() { return 0.0; }
|
||||
double GET_EXTERNAL_ORIGIN_X() { return 0.0; }
|
||||
double GET_EXTERNAL_ORIGIN_Y() { return 0.0; }
|
||||
double GET_EXTERNAL_ORIGIN_Z() { return 0.0; }
|
||||
void GET_EXTERNAL_PARAMETER_FILE_NAME(char *filename, int max_size)
|
||||
{
|
||||
if (max_size > 0) {
|
||||
filename[0] = '\0';
|
||||
}
|
||||
}
|
||||
void SET_PARAMETER_FILE_NAME(const char *) {}
|
||||
CANON_PLANE GET_EXTERNAL_PLANE() { return CANON_PLANE::XY; }
|
||||
double GET_EXTERNAL_POSITION_A() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_B() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_C() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_X() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_Y() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_Z() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_U() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_V() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_W() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_A() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_B() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_C() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_X() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_Y() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_Z() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_U() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_V() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_W() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_VALUE() { return 0.0; }
|
||||
int GET_EXTERNAL_PROBE_TRIPPED_VALUE() { return 0; }
|
||||
int GET_EXTERNAL_QUEUE_EMPTY() { return 1; }
|
||||
double GET_EXTERNAL_SPEED(int) { return 0.0; }
|
||||
CANON_DIRECTION GET_EXTERNAL_SPINDLE(int) { return CANON_STOPPED; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_XOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_YOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_ZOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_AOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_BOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_COFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_UOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_VOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_WOFFSET() { return 0.0; }
|
||||
int GET_EXTERNAL_TOOL_SLOT() { return 0; }
|
||||
int GET_EXTERNAL_SELECTED_TOOL_SLOT() { return -1; }
|
||||
CANON_TOOL_TABLE GET_EXTERNAL_TOOL_TABLE(int) { return tooldata_entry_init(); }
|
||||
int GET_EXTERNAL_TC_FAULT() { return 0; }
|
||||
int GET_EXTERNAL_TC_REASON() { return 0; }
|
||||
double GET_EXTERNAL_TRAVERSE_RATE() { return 0.0; }
|
||||
int GET_EXTERNAL_FEED_OVERRIDE_ENABLE() { return 1; }
|
||||
int GET_EXTERNAL_SPINDLE_OVERRIDE_ENABLE(int) { return 1; }
|
||||
int GET_EXTERNAL_ADAPTIVE_FEED_ENABLE() { return 1; }
|
||||
int GET_EXTERNAL_FEED_HOLD_ENABLE() { return 1; }
|
||||
int GET_EXTERNAL_DIGITAL_INPUT(int, int def) { return def; }
|
||||
double GET_EXTERNAL_ANALOG_INPUT(int, double def) { return def; }
|
||||
int GET_EXTERNAL_AXIS_MASK() { return 7; }
|
||||
int GET_EXTERNAL_OFFSET_APPLIED() { return 0; }
|
||||
EmcPose GET_EXTERNAL_OFFSETS() { return {{0, 0, 0}, 0, 0, 0, 0, 0, 0}; }
|
||||
|
||||
void NURBS_G5_FEED(int, const std::vector<NURBS_CONTROL_POINT> &, unsigned int, CANON_PLANE) {}
|
||||
void NURBS_G6_FEED(int, const std::vector<NURBS_G6_CONTROL_POINT> &, unsigned int, double, int, CANON_PLANE) {}
|
||||
|
||||
void COMMENT(const char *s)
|
||||
{
|
||||
standalone::push_canon_event(std::string("COMMENT: ") + (s ? s : ""));
|
||||
}
|
||||
|
||||
void STRAIGHT_TRAVERSE(int lineno,
|
||||
double x, double y, double z,
|
||||
double a, double b, double c,
|
||||
double u, double v, double w)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "STRAIGHT_TRAVERSE line=" << lineno
|
||||
<< " x=" << x
|
||||
<< " y=" << y
|
||||
<< " z=" << z
|
||||
<< " a=" << a
|
||||
<< " b=" << b
|
||||
<< " c=" << c
|
||||
<< " u=" << u
|
||||
<< " v=" << v
|
||||
<< " w=" << w;
|
||||
standalone::push_canon_event(oss.str());
|
||||
}
|
||||
|
||||
void STRAIGHT_FEED(int lineno,
|
||||
double x, double y, double z,
|
||||
double a, double b, double c,
|
||||
double u, double v, double w)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "STRAIGHT_FEED line=" << lineno
|
||||
<< " x=" << x
|
||||
<< " y=" << y
|
||||
<< " z=" << z
|
||||
<< " a=" << a
|
||||
<< " b=" << b
|
||||
<< " c=" << c
|
||||
<< " u=" << u
|
||||
<< " v=" << v
|
||||
<< " w=" << w;
|
||||
standalone::push_canon_event(oss.str());
|
||||
}
|
||||
|
||||
void ARC_FEED(int lineno,
|
||||
double first_end, double second_end,
|
||||
double first_axis, double second_axis, int rotation,
|
||||
double axis_end_point,
|
||||
double a, double b, double c,
|
||||
double u, double v, double w)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "ARC_FEED line=" << lineno
|
||||
<< " first_end=" << first_end
|
||||
<< " second_end=" << second_end
|
||||
<< " first_axis=" << first_axis
|
||||
<< " second_axis=" << second_axis
|
||||
<< " rotation=" << rotation
|
||||
<< " axis_end_point=" << axis_end_point
|
||||
<< " a=" << a
|
||||
<< " b=" << b
|
||||
<< " c=" << c
|
||||
<< " u=" << u
|
||||
<< " v=" << v
|
||||
<< " w=" << w;
|
||||
standalone::push_canon_event(oss.str());
|
||||
}
|
||||
|
||||
void SET_FEED_RATE(double rate)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "SET_FEED_RATE rate=" << rate;
|
||||
standalone::push_canon_event(oss.str());
|
||||
}
|
||||
|
||||
InterpBase::~InterpBase() {}
|
||||
|
||||
Interp::Interp()
|
||||
: log_file(stderr),
|
||||
_setup{}
|
||||
{
|
||||
_setup.init_once = 1;
|
||||
memset(_readers, 0, sizeof(_readers));
|
||||
}
|
||||
|
||||
Interp::~Interp() {
|
||||
if (log_file && log_file != stderr) {
|
||||
fclose(log_file);
|
||||
}
|
||||
log_file = nullptr;
|
||||
}
|
||||
|
||||
void Interp::doLog(unsigned int, const char *, int, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
const char *Interp::interp_status(int status)
|
||||
{
|
||||
static char statustext[64];
|
||||
snprintf(statustext, sizeof(statustext), "%d", status);
|
||||
return statustext;
|
||||
}
|
||||
|
||||
const char *Interp::getSavedError()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int Interp::setSavedError(const char *)
|
||||
{
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
void Interp::setError(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fputc('\n', stderr);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int Interp::unwind_call(int status, const char *, int, const char *)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
int Interp::close() { return INTERP_OK; }
|
||||
int Interp::execute(const char *command)
|
||||
{
|
||||
int status = read(command);
|
||||
if (status != INTERP_OK) {
|
||||
if (status > INTERP_MIN_ERROR) {
|
||||
unwind_call(status, __FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
if (_setup.line_length != 0) {
|
||||
status = execute_block(&EXECUTING_BLOCK(_setup), &_setup);
|
||||
if (status > INTERP_MIN_ERROR) {
|
||||
unwind_call(status, __FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int Interp::execute() { return execute(nullptr); }
|
||||
|
||||
int Interp::execute(const char *command, int line_number)
|
||||
{
|
||||
if (command && line_number) {
|
||||
_setup.sequence_number = line_number;
|
||||
}
|
||||
int status = execute(command);
|
||||
if ((_setup.call_level == 0) &&
|
||||
(status == INTERP_EXECUTE_FINISH) &&
|
||||
(_setup.mdi_interrupt)) {
|
||||
_setup.mdi_interrupt = false;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
int Interp::exit() { return INTERP_OK; }
|
||||
int Interp::init() { return INTERP_OK; }
|
||||
void Interp::set_loop_on_main_m99(bool state) { _setup.loop_on_main_m99 = state; }
|
||||
int Interp::open(const char *) { return INTERP_ERROR; }
|
||||
|
||||
int Interp::read_inputs(setup_pointer)
|
||||
{
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int Interp::_read(const char *command)
|
||||
{
|
||||
int read_status = INTERP_OK;
|
||||
block_pointer eblock = &EXECUTING_BLOCK(_setup);
|
||||
|
||||
if ((_setup.call_state > CS_NORMAL) &&
|
||||
(eblock->call_type != CT_NGC_OWORD_SUB) &&
|
||||
(eblock->call_type != CT_NGC_M98_SUB) &&
|
||||
(eblock->call_type != CT_NONE) &&
|
||||
((eblock->o_type == O_call) ||
|
||||
(eblock->o_type == M_98) ||
|
||||
(eblock->o_type == O_return) ||
|
||||
(eblock->o_type == O_endsub) ||
|
||||
(eblock->o_type == M_99))) {
|
||||
_setup.line_length = 0;
|
||||
_setup.linetext[0] = 0;
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
_setup.call_state = CS_NORMAL;
|
||||
if (read_inputs(&_setup) != INTERP_OK) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
|
||||
if ((command == nullptr) && (_setup.file_pointer == nullptr)) {
|
||||
return INTERP_FILE_NOT_OPEN;
|
||||
}
|
||||
|
||||
_setup.parameters[5420] = _setup.current_x;
|
||||
_setup.parameters[5421] = _setup.current_y;
|
||||
_setup.parameters[5422] = _setup.current_z;
|
||||
_setup.parameters[5423] = _setup.AA_current;
|
||||
_setup.parameters[5424] = _setup.BB_current;
|
||||
_setup.parameters[5425] = _setup.CC_current;
|
||||
_setup.parameters[5426] = _setup.u_current;
|
||||
_setup.parameters[5427] = _setup.v_current;
|
||||
_setup.parameters[5428] = _setup.w_current;
|
||||
|
||||
if (_setup.file_pointer) {
|
||||
EXECUTING_BLOCK(_setup).offset = ftell(_setup.file_pointer);
|
||||
}
|
||||
|
||||
read_status = read_text(command, _setup.file_pointer, _setup.linetext,
|
||||
_setup.blocktext, &_setup.line_length);
|
||||
|
||||
if ((read_status == INTERP_EXECUTE_FINISH) || (read_status == INTERP_OK)) {
|
||||
if (_setup.line_length != 0) {
|
||||
if (parse_line(_setup.blocktext, &(EXECUTING_BLOCK(_setup)), &_setup) != INTERP_OK) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
} else {
|
||||
if (EXECUTING_BLOCK(_setup).o_type != O_none) {
|
||||
EXECUTING_BLOCK(_setup).o_type = 0;
|
||||
}
|
||||
}
|
||||
} else if (read_status == INTERP_ENDFILE) {
|
||||
if (_setup.skipping_o != nullptr) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
} else {
|
||||
return read_status;
|
||||
}
|
||||
|
||||
return read_status;
|
||||
}
|
||||
|
||||
int Interp::read(const char *command)
|
||||
{
|
||||
int status = _read(command);
|
||||
if (status > INTERP_MIN_ERROR) {
|
||||
unwind_call(status, __FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int Interp::read()
|
||||
{
|
||||
return read(nullptr);
|
||||
}
|
||||
|
||||
int Interp::reset() { return INTERP_OK; }
|
||||
int Interp::synch() { return INTERP_OK; }
|
||||
void Interp::active_g_codes(int *codes) { std::memcpy(codes, _setup.active_g_codes, sizeof(_setup.active_g_codes)); }
|
||||
void Interp::active_m_codes(int *codes) { std::memcpy(codes, _setup.active_m_codes, sizeof(_setup.active_m_codes)); }
|
||||
void Interp::active_settings(double *settings) { std::memcpy(settings, _setup.active_settings, sizeof(_setup.active_settings)); }
|
||||
int Interp::active_modes(int *, int *, double *, StateTag const &) { return INTERP_ERROR; }
|
||||
void Interp::print_state_tag(StateTag const &) {}
|
||||
char *Interp::error_text(int, char *buf, size_t max_size)
|
||||
{
|
||||
if (max_size) buf[0] = '\0';
|
||||
return buf;
|
||||
}
|
||||
char *Interp::file_name(char *buf, size_t max_size)
|
||||
{
|
||||
if (max_size) {
|
||||
std::strncpy(buf, _setup.filename, max_size - 1);
|
||||
buf[max_size - 1] = '\0';
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
size_t Interp::line_length() { return static_cast<size_t>(_setup.line_length); }
|
||||
char *Interp::line_text(char *buf, size_t max_size)
|
||||
{
|
||||
if (max_size) {
|
||||
std::strncpy(buf, _setup.linetext, max_size - 1);
|
||||
buf[max_size - 1] = '\0';
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
int Interp::sequence_number() { return _setup.sequence_number; }
|
||||
char *Interp::stack_name(int idx, char *buf, size_t max_size)
|
||||
{
|
||||
if (!max_size) return buf;
|
||||
if (idx < 0 || idx >= STACK_LEN) {
|
||||
buf[0] = '\0';
|
||||
return buf;
|
||||
}
|
||||
std::strncpy(buf, _setup.stack[idx], max_size - 1);
|
||||
buf[max_size - 1] = '\0';
|
||||
return buf;
|
||||
}
|
||||
int Interp::ini_load(const char *) { return INTERP_OK; }
|
||||
int Interp::on_abort(int, const char *) { return INTERP_OK; }
|
||||
void Interp::set_loglevel(int level) { _setup.loggingLevel = level; }
|
||||
|
||||
int Interp::find_remappings(block_pointer, setup_pointer) { return 0; }
|
||||
|
||||
int Interp::load_tool_table() { return INTERP_OK; }
|
||||
int Interp::init_tool_parameters() { return INTERP_OK; }
|
||||
int Interp::default_tool_parameters() { return INTERP_OK; }
|
||||
int Interp::set_tool_parameters() { return INTERP_OK; }
|
||||
bool Interp::is_pycallable(setup_pointer, const char *, const char *) { return false; }
|
||||
bool Interp::is_user_defined_g_code(int) { return false; }
|
||||
bool Interp::is_any_m_code_remapped(block_pointer, setup_pointer) { return false; }
|
||||
bool Interp::is_user_defined_m_code(block_pointer, setup_pointer, int) { return false; }
|
||||
void Interp::loop_to_beginning(setup_pointer) {}
|
||||
int Interp::convert_control_functions(block_pointer, setup_pointer) { return INTERP_OK; }
|
||||
int Interp::convert_remapped_code(block_pointer, setup_pointer, int, char, int) { return INTERP_ERROR; }
|
||||
int Interp::py_execute(const char *, bool) { return INTERP_OK; }
|
||||
int Interp::py_reload() { return INTERP_OK; }
|
||||
|
||||
const char *o_ops[] = {
|
||||
"O_none", "O_sub", "O_endsub", "O_call", "O_do", "O_while", "O_if",
|
||||
"O_elseif", "O_else", "O_endif", "O_break", "O_continue",
|
||||
"O_endwhile", "O_return", "O_repeat", "O_endrepeat", "M_98", "M_99", "O_"
|
||||
};
|
||||
|
||||
int Interp::read_named_parameter(char *, int *, double *double_ptr, double *, bool check_exists)
|
||||
{
|
||||
if (check_exists) {
|
||||
*double_ptr = 0.0;
|
||||
}
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
|
||||
int Interp::find_named_param(const char *, int *status, double *value)
|
||||
{
|
||||
*status = 0;
|
||||
*value = 0.0;
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int Interp::store_named_param(setup_pointer, const char *, double, int)
|
||||
{
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
|
||||
int Interp::add_named_param(const char *, int)
|
||||
{
|
||||
return INTERP_OK;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "emc/rs274ngc/interp_internal.hh"
|
||||
|
||||
int main() {
|
||||
std::cout << "RS274NGC_MAX_PARAMETERS="
|
||||
<< interp_param_global::RS274NGC_MAX_PARAMETERS << "\n";
|
||||
std::cout << "ACTIVE_G_CODES=" << ACTIVE_G_CODES << "\n";
|
||||
std::cout << "ACTIVE_M_CODES=" << ACTIVE_M_CODES << "\n";
|
||||
std::cout << "ACTIVE_SETTINGS=" << ACTIVE_SETTINGS << "\n";
|
||||
std::cout << "INTERP_SUB_ROUTINE_LEVELS=" << INTERP_SUB_ROUTINE_LEVELS << "\n";
|
||||
std::cout << "MAX_NAMED_PARAMETERS=" << MAX_NAMED_PARAMETERS << "\n";
|
||||
std::cout << "sizeof_setup=" << sizeof(setup) << "\n";
|
||||
std::cout << "sizeof_context=" << sizeof(context) << "\n";
|
||||
std::cout << "sizeof_parameter_value=" << sizeof(parameter_value) << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
#define private public
|
||||
#include "emc/rs274ngc/rs274ngc_interp.hh"
|
||||
#undef private
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "config.h"
|
||||
#include "emc/ini/inifile.hh"
|
||||
|
||||
namespace {
|
||||
|
||||
enum predefined_named_parameters {
|
||||
NP_LINE,
|
||||
NP_MOTION_MODE,
|
||||
NP_PLANE,
|
||||
NP_CCOMP,
|
||||
NP_METRIC,
|
||||
NP_IMPERIAL,
|
||||
NP_ABSOLUTE,
|
||||
NP_INCREMENTAL,
|
||||
NP_INVERSE_TIME,
|
||||
NP_UNITS_PER_MINUTE,
|
||||
NP_UNITS_PER_REV,
|
||||
NP_COORD_SYSTEM,
|
||||
NP_TOOL_OFFSET,
|
||||
NP_RETRACT_R_PLANE,
|
||||
NP_RETRACT_OLD_Z,
|
||||
NP_SPINDLE_RPM_MODE,
|
||||
NP_SPINDLE_CSS_MODE,
|
||||
NP_IJK_ABSOLUTE_MODE,
|
||||
NP_LATHE_DIAMETER_MODE,
|
||||
NP_LATHE_RADIUS_MODE,
|
||||
NP_SPINDLE_ON,
|
||||
NP_SPINDLE_CW,
|
||||
NP_MIST,
|
||||
NP_FLOOD,
|
||||
NP_SPEED_OVERRIDE,
|
||||
NP_FEED_OVERRIDE,
|
||||
NP_ADAPTIVE_FEED,
|
||||
NP_FEED_HOLD,
|
||||
NP_FEED,
|
||||
NP_RPM,
|
||||
NP_CURRENT_TOOL,
|
||||
NP_SELECTED_POCKET,
|
||||
NP_CURRENT_POCKET,
|
||||
NP_X,
|
||||
NP_Y,
|
||||
NP_Z,
|
||||
NP_A,
|
||||
NP_B,
|
||||
NP_C,
|
||||
NP_U,
|
||||
NP_V,
|
||||
NP_W,
|
||||
NP_ABS_X,
|
||||
NP_ABS_Y,
|
||||
NP_ABS_Z,
|
||||
NP_ABS_A,
|
||||
NP_ABS_B,
|
||||
NP_ABS_C,
|
||||
NP_VALUE,
|
||||
NP_CALL_LEVEL,
|
||||
NP_REMAP_LEVEL,
|
||||
NP_SELECTED_TOOL,
|
||||
NP_VALUE_RETURNED,
|
||||
NP_TASK,
|
||||
};
|
||||
|
||||
struct NamedParamRuntime {
|
||||
setup state;
|
||||
|
||||
int fetch_ini_param(const char *nameBuf, int *status, double *value) {
|
||||
*status = 0;
|
||||
const int n = static_cast<int>(strlen(nameBuf));
|
||||
if (n < 8) {
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
std::string sect = nameBuf + 5;
|
||||
for (auto &c : sect) {
|
||||
c = static_cast<char>(toupper(c));
|
||||
}
|
||||
const size_t i = sect.find(']');
|
||||
if (i == std::string::npos) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
std::string var = sect.substr(i + 1);
|
||||
sect.erase(i);
|
||||
|
||||
const char *iniFileName = getenv("INI_FILE_NAME");
|
||||
if (!iniFileName) {
|
||||
return INTERP_OK;
|
||||
}
|
||||
linuxcnc::IniFile inifile(iniFileName);
|
||||
if (!inifile) {
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
if (auto inival = inifile.findReal(var, sect)) {
|
||||
*value = *inival;
|
||||
*status = 1;
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int lookup_named_param(const char *nameBuf, double index, double *value) {
|
||||
const int cmd = round_to_int(index);
|
||||
switch (cmd) {
|
||||
case NP_LINE:
|
||||
*value = state.sequence_number;
|
||||
break;
|
||||
case NP_MOTION_MODE:
|
||||
*value = state.motion_mode;
|
||||
break;
|
||||
case NP_METRIC:
|
||||
*value = (state.length_units == CANON_UNITS_MM);
|
||||
break;
|
||||
case NP_IMPERIAL:
|
||||
*value = (state.length_units == CANON_UNITS_INCHES);
|
||||
break;
|
||||
case NP_ABSOLUTE:
|
||||
*value = (state.distance_mode == DISTANCE_MODE::ABSOLUTE);
|
||||
break;
|
||||
case NP_INCREMENTAL:
|
||||
*value = (state.distance_mode == DISTANCE_MODE::INCREMENTAL);
|
||||
break;
|
||||
case NP_FEED:
|
||||
*value = state.feed_rate;
|
||||
break;
|
||||
case NP_RPM:
|
||||
*value = state.speed[0];
|
||||
break;
|
||||
case NP_X:
|
||||
*value = state.current_x;
|
||||
break;
|
||||
case NP_Y:
|
||||
*value = state.current_y;
|
||||
break;
|
||||
case NP_Z:
|
||||
*value = state.current_z;
|
||||
break;
|
||||
case NP_CURRENT_TOOL:
|
||||
*value = state.parameters[interp_param_global::TOOL_NUMBER];
|
||||
break;
|
||||
case NP_CALL_LEVEL:
|
||||
*value = state.call_level;
|
||||
break;
|
||||
default:
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int find_named_param(const char *nameBuf, int *status, double *value) {
|
||||
const int level = (nameBuf[0] == '_') ? 0 : state.call_level;
|
||||
context_pointer frame = &state.sub_context[level];
|
||||
*status = 0;
|
||||
|
||||
auto pi = frame->named_params.find(nameBuf);
|
||||
if (pi == frame->named_params.end()) {
|
||||
int exists = 0;
|
||||
double inivalue = 0.0;
|
||||
if ((state.feature_set & FEATURE_INI_VARS) && (strncasecmp(nameBuf, "_ini[", 5) == 0)) {
|
||||
fetch_ini_param(nameBuf, &exists, &inivalue);
|
||||
if (exists) {
|
||||
*value = inivalue;
|
||||
*status = 1;
|
||||
parameter_value param;
|
||||
param.value = inivalue;
|
||||
param.attr = PA_GLOBAL | PA_READONLY | PA_FROM_INI;
|
||||
state.sub_context[0].named_params[strstore(nameBuf)] = param;
|
||||
return INTERP_OK;
|
||||
}
|
||||
}
|
||||
*value = 0.0;
|
||||
*status = 0;
|
||||
} else {
|
||||
parameter_pointer pv = &pi->second;
|
||||
if (pv->attr & PA_USE_LOOKUP) {
|
||||
if (lookup_named_param(nameBuf, pv->value, value) != INTERP_OK) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
*status = 1;
|
||||
} else {
|
||||
*value = pv->value;
|
||||
*status = 1;
|
||||
}
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int store_named_param(const char *nameBuf, double value, bool override_readonly) {
|
||||
const int level = (nameBuf[0] == '_') ? 0 : state.call_level;
|
||||
context_pointer frame = &state.sub_context[level];
|
||||
auto pi = frame->named_params.find(nameBuf);
|
||||
if (pi == frame->named_params.end()) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
parameter_pointer pv = &pi->second;
|
||||
if ((pv->attr & PA_READONLY) && !override_readonly) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
pv->value = value;
|
||||
pv->attr &= ~PA_UNSET;
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int add_named_param(const char *nameBuf, int attr) {
|
||||
int findStatus = 0;
|
||||
double value = 0.0;
|
||||
find_named_param(nameBuf, &findStatus, &value);
|
||||
if (findStatus) {
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int level = 0;
|
||||
if (nameBuf[0] != '_') {
|
||||
level = state.call_level;
|
||||
} else {
|
||||
level = 0;
|
||||
attr |= PA_GLOBAL;
|
||||
}
|
||||
attr |= PA_UNSET;
|
||||
|
||||
parameter_value param;
|
||||
param.value = 0.0;
|
||||
param.attr = attr;
|
||||
state.sub_context[level].named_params[strstore(nameBuf)] = param;
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int init_readonly_param(const char *nameBuf, double value, int attr) {
|
||||
if (add_named_param(nameBuf, PA_READONLY | attr) != INTERP_OK) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
if (store_named_param(nameBuf, value, true) != INTERP_OK) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
double inicheck() {
|
||||
const char *filename = getenv("INI_FILE_NAME");
|
||||
if (!filename) {
|
||||
return -1.0;
|
||||
}
|
||||
linuxcnc::IniFile inifile(filename);
|
||||
if (!inifile) {
|
||||
return -1.0;
|
||||
}
|
||||
if (auto inistring = inifile.findString("LINEAR_UNITS", "TRAJ")) {
|
||||
if ((strcasecmp("mm", inistring->c_str()) == 0) ||
|
||||
(strcasecmp("metric", inistring->c_str()) == 0)) {
|
||||
return 1.0;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
int init_named_parameters() {
|
||||
const char *pkgversion = PACKAGE_VERSION;
|
||||
const char *version_major = "_vmajor";
|
||||
const char *version_minor = "_vminor";
|
||||
const char *metric_machine = "_metric_machine";
|
||||
double vmajor = 0.0;
|
||||
double vminor = 0.0;
|
||||
double munits = 1.0;
|
||||
sscanf(pkgversion, "%lf%lf", &vmajor, &vminor);
|
||||
|
||||
if (init_readonly_param(version_major, vmajor, 0) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param(version_minor, vminor, 0) != INTERP_OK) return INTERP_ERROR;
|
||||
|
||||
munits = inicheck();
|
||||
if (init_readonly_param(metric_machine, munits, 0) != INTERP_OK) return INTERP_ERROR;
|
||||
|
||||
if (init_readonly_param("_line", NP_LINE, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_motion_mode", NP_MOTION_MODE, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_metric", NP_METRIC, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_imperial", NP_IMPERIAL, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_absolute", NP_ABSOLUTE, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_incremental", NP_INCREMENTAL, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_feed", NP_FEED, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_rpm", NP_RPM, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_x", NP_X, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_y", NP_Y, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_z", NP_Z, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_current_tool", NP_CURRENT_TOOL, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_call_level", NP_CALL_LEVEL, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
};
|
||||
|
||||
void print_named_value(NamedParamRuntime &runtime, const char *name) {
|
||||
int status = 0;
|
||||
double value = 0.0;
|
||||
const int rc = runtime.find_named_param(name, &status, &value);
|
||||
std::cout << name << ": rc=" << rc << " found=" << status << " value=" << value << "\n";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc == 2) {
|
||||
setenv("INI_FILE_NAME", argv[1], 1);
|
||||
}
|
||||
|
||||
NamedParamRuntime runtime;
|
||||
runtime.state.feature_set = FEATURE_INI_VARS;
|
||||
runtime.state.length_units = CANON_UNITS_MM;
|
||||
runtime.state.distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
runtime.state.motion_mode = G_1;
|
||||
runtime.state.feed_rate = 123.45;
|
||||
runtime.state.speed[0] = 678.9;
|
||||
runtime.state.current_x = 1.25;
|
||||
runtime.state.current_y = 2.5;
|
||||
runtime.state.current_z = 3.75;
|
||||
runtime.state.parameters[interp_param_global::TOOL_NUMBER] = 12.0;
|
||||
|
||||
const int rc = runtime.init_named_parameters();
|
||||
std::cout << "init_named_parameters=" << rc << "\n";
|
||||
std::cout << "global_named_count=" << runtime.state.sub_context[0].named_params.size() << "\n";
|
||||
std::cout << "required_parameter_first=" << interp_param_global::G28_X << "\n";
|
||||
std::cout << "readonly_tool_number_index=" << interp_param_global::TOOL_NUMBER << "\n";
|
||||
|
||||
print_named_value(runtime, "_vmajor");
|
||||
print_named_value(runtime, "_vminor");
|
||||
print_named_value(runtime, "_metric_machine");
|
||||
print_named_value(runtime, "_motion_mode");
|
||||
print_named_value(runtime, "_metric");
|
||||
print_named_value(runtime, "_feed");
|
||||
print_named_value(runtime, "_rpm");
|
||||
print_named_value(runtime, "_x");
|
||||
print_named_value(runtime, "_current_tool");
|
||||
print_named_value(runtime, "_ini[traj]max_linear_velocity");
|
||||
|
||||
return rc == INTERP_OK ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#include "emc/rs274ngc/rs274ngc_interp.hh"
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "emc/rs274ngc/interp_internal.hh"
|
||||
|
||||
struct pycontext_impl {};
|
||||
|
||||
pycontext::pycontext() : impl(new pycontext_impl) {}
|
||||
pycontext::~pycontext() { delete impl; }
|
||||
pycontext::pycontext(const pycontext &other) : impl(new pycontext_impl(*other.impl)) {}
|
||||
pycontext &pycontext::operator=(const pycontext &other) {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
delete impl;
|
||||
impl = new pycontext_impl(*other.impl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const char *strstore(const char *s)
|
||||
{
|
||||
static std::unordered_set<std::string> stringtable;
|
||||
|
||||
if (s == nullptr) {
|
||||
throw std::invalid_argument("strstore(): NULL argument");
|
||||
}
|
||||
auto pair = stringtable.insert(s);
|
||||
return pair.first->c_str();
|
||||
}
|
||||
|
||||
context_struct::context_struct()
|
||||
: position(0), sequence_number(0), filename(""), subName(""),
|
||||
m98_loop_counter(-1), context_status(0), call_type(0)
|
||||
{
|
||||
memset(saved_params, 0, sizeof(saved_params));
|
||||
memset(saved_g_codes, 0, sizeof(saved_g_codes));
|
||||
memset(saved_m_codes, 0, sizeof(saved_m_codes));
|
||||
memset(saved_settings, 0, sizeof(saved_settings));
|
||||
}
|
||||
|
||||
void context_struct::clear()
|
||||
{
|
||||
new (this) context_struct();
|
||||
}
|
||||
|
||||
setup::setup()
|
||||
: AA_axis_offset(0.0),
|
||||
AA_current(0.0),
|
||||
AA_origin_offset(0.0),
|
||||
BB_axis_offset(0.0),
|
||||
BB_current(0.0),
|
||||
BB_origin_offset(0.0),
|
||||
CC_axis_offset(0.0),
|
||||
CC_current(0.0),
|
||||
CC_origin_offset(0.0),
|
||||
u_axis_offset(0.0),
|
||||
u_current(0.0),
|
||||
u_origin_offset(0.0),
|
||||
v_axis_offset(0.0),
|
||||
v_current(0.0),
|
||||
v_origin_offset(0.0),
|
||||
w_axis_offset(0.0),
|
||||
w_current(0.0),
|
||||
w_origin_offset(0.0),
|
||||
active_g_codes{},
|
||||
active_m_codes{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
active_settings{},
|
||||
arc_not_allowed(0),
|
||||
axis_offset_x(0.0),
|
||||
axis_offset_y(0.0),
|
||||
axis_offset_z(0.0),
|
||||
blocks{},
|
||||
remap_level(0),
|
||||
blocktext{},
|
||||
control_mode(CANON_EXACT_STOP),
|
||||
tolerance(0.0),
|
||||
naivecam_tolerance(0.0),
|
||||
tolerance_default(0.0),
|
||||
naivecam_tolerance_default(0.0),
|
||||
current_pocket(0),
|
||||
current_x(0.0),
|
||||
current_y(0.0),
|
||||
current_z(0.0),
|
||||
cutter_comp_radius(0.0),
|
||||
cutter_comp_orientation(0),
|
||||
cutter_comp_side(CUTTER_COMP::OFF),
|
||||
cycle_cc(0.0),
|
||||
cycle_i(0.0),
|
||||
cycle_j(0.0),
|
||||
cycle_k(0.0),
|
||||
cycle_l(0),
|
||||
cycle_p(0.0),
|
||||
cycle_q(0.0),
|
||||
cycle_r(0.0),
|
||||
cycle_il(0.0),
|
||||
cycle_il_flag(0),
|
||||
distance_mode(DISTANCE_MODE::ABSOLUTE),
|
||||
ijk_distance_mode(DISTANCE_MODE::ABSOLUTE),
|
||||
feed_mode(FEED_MODE::UNITS_PER_MINUTE),
|
||||
feed_override(0),
|
||||
feed_rate(0.0),
|
||||
filename{},
|
||||
file_pointer(nullptr),
|
||||
flood(0),
|
||||
length_units(CANON_UNITS_INCHES),
|
||||
center_arc_radius_tolerance_inch(CENTER_ARC_RADIUS_TOLERANCE_INCH),
|
||||
center_arc_radius_tolerance_mm(CENTER_ARC_RADIUS_TOLERANCE_MM),
|
||||
line_length(0),
|
||||
linetext{},
|
||||
mist(0),
|
||||
motion_mode(0),
|
||||
origin_index(0),
|
||||
origin_offset_x(0.0),
|
||||
origin_offset_y(0.0),
|
||||
origin_offset_z(0.0),
|
||||
rotation_xy(0.0),
|
||||
parameters{0},
|
||||
parameter_occurrence(0),
|
||||
parameter_numbers{0},
|
||||
parameter_values{0},
|
||||
named_parameter_occurrence(0),
|
||||
named_parameters{nullptr},
|
||||
named_parameter_values{0},
|
||||
percent_flag(0),
|
||||
plane(CANON_PLANE::XY),
|
||||
probe_flag(0),
|
||||
input_flag(0),
|
||||
toolchange_flag(0),
|
||||
input_index(0),
|
||||
input_digital(0),
|
||||
cutter_comp_firstmove(0),
|
||||
program_x(0.0),
|
||||
program_y(0.0),
|
||||
program_z(0.0),
|
||||
retract_mode(RETRACT_MODE::R_PLANE),
|
||||
random_toolchanger(0),
|
||||
selected_pocket(0),
|
||||
selected_tool(0),
|
||||
sequence_number(0),
|
||||
num_spindles(0),
|
||||
active_spindle(0),
|
||||
speed{0.0},
|
||||
spindle_mode{SPINDLE_MODE::CONSTANT_RPM},
|
||||
speed_feed_mode{CANON_INDEPENDENT},
|
||||
speed_override{false},
|
||||
spindle_turning{CANON_STOPPED},
|
||||
stack{},
|
||||
stack_index(0),
|
||||
tool_offset{{0,0,0},0,0,0,0,0,0},
|
||||
tool_table{},
|
||||
traverse_rate(0.0),
|
||||
orient_offset(0.0),
|
||||
g43_with_zero_offset(false),
|
||||
defining_sub(0),
|
||||
sub_name(nullptr),
|
||||
doing_continue(0),
|
||||
doing_break(0),
|
||||
executed_if(0),
|
||||
skipping_o(nullptr),
|
||||
skipping_to_sub(nullptr),
|
||||
skipping_start(0),
|
||||
test_value(0.0),
|
||||
return_value(0.0),
|
||||
value_returned(0),
|
||||
call_level(0),
|
||||
sub_context{},
|
||||
call_state(0),
|
||||
adaptive_feed(0),
|
||||
feed_hold(0),
|
||||
loggingLevel(0),
|
||||
debugmask(0),
|
||||
log_file{},
|
||||
program_prefix{},
|
||||
subroutines{},
|
||||
use_lazy_close(0),
|
||||
lazy_closing(0),
|
||||
wizard_root{},
|
||||
tool_change_at_g30(0),
|
||||
tool_change_quill_up(0),
|
||||
tool_change_with_spindle_on(0),
|
||||
parameter_g73_peck_clearance(0.0),
|
||||
parameter_g83_peck_clearance(0.0),
|
||||
a_axis_wrapped(0),
|
||||
b_axis_wrapped(0),
|
||||
c_axis_wrapped(0),
|
||||
a_indexer_jnum(0),
|
||||
b_indexer_jnum(0),
|
||||
c_indexer_jnum(0),
|
||||
lathe_diameter_mode(0),
|
||||
mdi_interrupt(0),
|
||||
feature_set(0),
|
||||
disable_fanuc_style_sub(false),
|
||||
loop_on_main_m99(false),
|
||||
disable_g92_persistence(0),
|
||||
pythis(nullptr),
|
||||
on_abort_command(nullptr),
|
||||
init_once(CANON_STOPPED)
|
||||
{
|
||||
std::fill(parameters, parameters + interp_param_global::RS274NGC_MAX_PARAMETERS, 0);
|
||||
}
|
||||
|
||||
setup::~setup() {
|
||||
if (pythis) {
|
||||
delete pythis;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
struct _object;
|
||||
typedef _object PyObject;
|
||||
9
wasm-port/runtime/core/shims/boost/python/object_fwd.hpp
Normal file
9
wasm-port/runtime/core/shims/boost/python/object_fwd.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
class object {};
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
3
wasm-port/runtime/core/shims/config.h
Normal file
3
wasm-port/runtime/core/shims/config.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define PACKAGE_VERSION "2.10.0~pre1"
|
||||
7
wasm-port/runtime/core/shims/fmt/format.h
Normal file
7
wasm-port/runtime/core/shims/fmt/format.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <format>
|
||||
|
||||
namespace fmt {
|
||||
using std::format;
|
||||
}
|
||||
18
wasm-port/runtime/core/shims/nml_intf/emc.hh
Normal file
18
wasm-port/runtime/core/shims/nml_intf/emc.hh
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
// Minimal shim for standalone interpreter source probes.
|
||||
enum EmcJointType : int {
|
||||
EMC_LINEAR = 1,
|
||||
EMC_ANGULAR = 2,
|
||||
};
|
||||
|
||||
class EMC_STAT {
|
||||
public:
|
||||
struct Motion {
|
||||
struct Traj {
|
||||
double linearUnits = 1.0;
|
||||
} traj;
|
||||
} motion;
|
||||
};
|
||||
|
||||
extern EMC_STAT *emcStatus;
|
||||
13
wasm-port/runtime/core/shims/pythonplugin/python_plugin.hh
Normal file
13
wasm-port/runtime/core/shims/pythonplugin/python_plugin.hh
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class PythonPlugin {
|
||||
public:
|
||||
bool usable() const { return false; }
|
||||
int plugin_status() const { return 0; }
|
||||
const std::string &last_exception() const {
|
||||
static std::string empty;
|
||||
return empty;
|
||||
}
|
||||
};
|
||||
67
wasm-port/runtime/core/shims/rtapi.h
Normal file
67
wasm-port/runtime/core/shims/rtapi.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstddef>
|
||||
|
||||
#ifndef RTAPI_BEGIN_DECLS
|
||||
#ifdef __cplusplus
|
||||
#define RTAPI_BEGIN_DECLS extern "C" {
|
||||
#define RTAPI_END_DECLS }
|
||||
#else
|
||||
#define RTAPI_BEGIN_DECLS
|
||||
#define RTAPI_END_DECLS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef RTAPI_NAME_LEN
|
||||
#define RTAPI_NAME_LEN 31
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
RTAPI_MSG_NONE = 0,
|
||||
RTAPI_MSG_ERR,
|
||||
RTAPI_MSG_WARN,
|
||||
RTAPI_MSG_INFO,
|
||||
RTAPI_MSG_DBG,
|
||||
RTAPI_MSG_ALL
|
||||
} msg_level_t;
|
||||
|
||||
RTAPI_BEGIN_DECLS
|
||||
|
||||
static inline int rtapi_snprintf(char *buf, unsigned long size, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int rc = vsnprintf(buf, static_cast<size_t>(size), fmt, ap);
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int rtapi_vsnprintf(char *buf, unsigned long size, const char *fmt, va_list ap) {
|
||||
return vsnprintf(buf, static_cast<size_t>(size), fmt, ap);
|
||||
}
|
||||
|
||||
static inline void rtapi_print(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static inline void rtapi_print_msg(msg_level_t, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static inline int rtapi_set_msg_level(int) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int rtapi_get_msg_level(void) {
|
||||
return RTAPI_MSG_ALL;
|
||||
}
|
||||
|
||||
RTAPI_END_DECLS
|
||||
29
wasm-port/runtime/core/shims/tooldata/tooldata.hh
Normal file
29
wasm-port/runtime/core/shims/tooldata/tooldata.hh
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "emc/nml_intf/emctool.h"
|
||||
|
||||
enum {
|
||||
IDX_OK = 0,
|
||||
};
|
||||
|
||||
inline CANON_TOOL_TABLE tooldata_entry_init()
|
||||
{
|
||||
CANON_TOOL_TABLE tool{};
|
||||
tool.toolno = 0;
|
||||
tool.pocketno = 0;
|
||||
return tool;
|
||||
}
|
||||
|
||||
inline int tooldata_find_index_for_tool(int toolno)
|
||||
{
|
||||
return toolno == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
inline int tooldata_get(CANON_TOOL_TABLE *tool, int index)
|
||||
{
|
||||
if ((tool == nullptr) || (index != 0)) {
|
||||
return -1;
|
||||
}
|
||||
*tool = tooldata_entry_init();
|
||||
return IDX_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user