满庭芳·源流归一
结论:LinuxCNC rs274ngc 源码移植边界继续收拢。已将 rs274ngc 头文件纳入 manifest 跟踪,core 编译组仍只包含可编译源文件;启用 CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND 时 API 默认使用 LinuxCNC rs274 后端;M428/M429/M430 与 5axis/TRT/TDR/RTCP 相关路径继续保持来自 LinuxCNC 源码或 remap 配置的薄桥接。 验证:./test-linuxcnc-source-syntax.sh;./test-linuxcnc-api-native.sh;./test-native.sh;./test-linuxcnc-source-link.sh。
This commit is contained in:
@@ -143,11 +143,19 @@ RTCP 默认关闭。开启后,原有 `rapid`、`linear-feed`、`arc-feed` 事
|
||||
"toolLengths": {
|
||||
"7": 125
|
||||
}
|
||||
},
|
||||
"xyzbcTrt": {
|
||||
"xRotPoint": 0,
|
||||
"yRotPoint": 0,
|
||||
"zRotPoint": 0,
|
||||
"xOffset": -20,
|
||||
"zOffset": -15,
|
||||
"conventionalDirections": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
当前 RTCP 内核是第一版头头/摆头类几何模型:编程 XYZ 视为刀尖点,刀长沿本地 `-Z`,A/B/C 按 `Rz(C) * Ry(B) * Rx(A)` 旋转。后续会继续加入机型拓扑、旋转中心偏置、刀表刀长和不同五轴构型。
|
||||
RTCP pivot 事件只在已知 LinuxCNC switchkins 类型下输出。`M428` 切换到 `XYZBC_TRT` 后,`xyzbcTrt` 对应 LinuxCNC `xyzbc-trt-kins` 的 HAL pin:`x-rot-point`、`y-rot-point`、`z-rot-point`、`x-offset`、`z-offset`、`conventional-directions`;刀长仍来自 `toolLength` / `toolLengths`。`M430` 使用 LinuxCNC `userkfuncs.c` 经 `kins_util.c` identity 运动学路径。未支持或未知的 switchkins 类型不会回退到自研 RTCP 几何。
|
||||
|
||||
RTCP G 码控制已开始标准化:
|
||||
|
||||
@@ -161,11 +169,11 @@ RTCP G 码控制已开始标准化:
|
||||
|
||||
core 已对原型中的运动学切换 M 码做标准化解析:
|
||||
|
||||
- `M429`:切换到三轴恒等运动学 `IDENTITY`,关闭 RTCP。
|
||||
- `M428`:恢复到原始五轴运动学,开启 RTCP。
|
||||
- `M430`:切换到 `FIVEAXIS_BC`,开启 RTCP。
|
||||
- `M429`:切换到三轴恒等运动学 `IDENTITY`。
|
||||
- `M428`:切换到 LinuxCNC `xyzbc-trt-kins` 的 XYZBC TRT 运动学。
|
||||
- `M430`:切换到 LinuxCNC 默认 `userk` 运动学;当前对齐 `userkfuncs.c` 的 identity 正/逆解。
|
||||
|
||||
解析后会发出 `kinematics-switch` 事件。事件中的 `reserved` 字段表示运动学类型:`0=IDENTITY`、`1=ORIGINAL`、`2=FIVEAXIS_BC`;`feed` 字段临时表示 RTCP 状态:`0=关闭`、`1=开启`。同一行中的 `M428 M429 M430` 会按出现顺序产生三个切换事件。
|
||||
解析后会发出 `kinematics-switch` 事件。事件中的 `reserved` 字段表示运动学类型:`0=IDENTITY`、`1=XYZBC_TRT`、`2=USERK_IDENTITY`。这些 M 码对齐 LinuxCNC `remap_subs/428remap.ngc`、`429remap.ngc`、`430remap.ngc`,只设置 `motion.switchkins-type`,不隐式开启或关闭 RTCP;RTCP 状态仍由 `G43.4`、`G43.5`、`G49` 控制。同一行中的 `M428 M429 M430` 会按出现顺序产生三个切换事件。
|
||||
|
||||
`linuxcnc-rs274` native API backend 会在送入 LinuxCNC 解释器前拦截只包含这些切换 M 码的行,避免 LinuxCNC 去查找外部用户 M-code 文件。
|
||||
|
||||
|
||||
@@ -6,15 +6,7 @@ cd "$(dirname "$0")"
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "$manifest"
|
||||
|
||||
python_blockers=()
|
||||
core_python_sources=()
|
||||
@@ -30,9 +22,6 @@ core_native_fs_sources=()
|
||||
core_count=0
|
||||
blocked_count=0
|
||||
blocked_replacements=()
|
||||
core_source_list=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_wasm_blocker_core_sources.XXXXXX.txt")
|
||||
blocked_source_list=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_wasm_blocker_blocked_sources.XXXXXX.txt")
|
||||
trap 'rm -f "$core_source_list" "$blocked_source_list"' EXIT
|
||||
|
||||
blocked_replacement_for() {
|
||||
case "$1" in
|
||||
@@ -45,15 +34,19 @@ blocked_replacement_for() {
|
||||
esac
|
||||
}
|
||||
|
||||
./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core > "$core_source_list"
|
||||
./list-linuxcnc-wasm-manifest-sources.sh "$manifest" blocked > "$blocked_source_list"
|
||||
core_count=$(wc -l < "$core_source_list")
|
||||
blocked_count=$(wc -l < "$blocked_source_list")
|
||||
core_source_output=$(./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core)
|
||||
mapfile -t core_sources <<<"$core_source_output"
|
||||
blocked_source_output=$(./list-linuxcnc-wasm-manifest-sources.sh "$manifest" blocked)
|
||||
mapfile -t blocked_sources <<<"$blocked_source_output"
|
||||
core_count=${#core_sources[@]}
|
||||
blocked_count=${#blocked_sources[@]}
|
||||
|
||||
scan_source() {
|
||||
local group=$1
|
||||
local path=$2
|
||||
full_path="$linuxcnc_root/$path"
|
||||
full_path=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh \
|
||||
--missing-message "missing manifest source" \
|
||||
"$path")
|
||||
if [[ "$group" == "blocked" ]]; then
|
||||
if ! replacement=$(blocked_replacement_for "$path"); then
|
||||
echo "missing blocked replacement mapping: $path" >&2
|
||||
@@ -111,15 +104,15 @@ scan_source() {
|
||||
fi
|
||||
}
|
||||
|
||||
while IFS= read -r path; do
|
||||
for path in "${core_sources[@]}"; do
|
||||
[[ -z "$path" ]] && continue
|
||||
scan_source core "$path"
|
||||
done < "$core_source_list"
|
||||
done
|
||||
|
||||
while IFS= read -r path; do
|
||||
for path in "${blocked_sources[@]}"; do
|
||||
[[ -z "$path" ]] && continue
|
||||
scan_source blocked "$path"
|
||||
done < "$blocked_source_list"
|
||||
done
|
||||
|
||||
print_group() {
|
||||
local title=$1
|
||||
|
||||
@@ -6,32 +6,35 @@ cd "$(dirname "$0")"
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "$manifest"
|
||||
manifest=$(cd "$(dirname "$manifest")" && pwd)/$(basename "$manifest")
|
||||
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||
default_manifest="$PWD/linuxcnc-rs274-wasm-source-files.txt"
|
||||
|
||||
count_nonempty_lines() {
|
||||
local text=${1-}
|
||||
local count=0
|
||||
local line
|
||||
|
||||
while IFS= read -r line; do
|
||||
if [[ -n "$line" ]]; then
|
||||
count=$((count + 1))
|
||||
fi
|
||||
done <<<"$text"
|
||||
|
||||
printf '%s\n' "$count"
|
||||
}
|
||||
|
||||
# This script writes fixed build and public artifact paths, so serialize it.
|
||||
exec 9>"${TMPDIR:-/tmp}/cnc_sim_build_wasm.lock"
|
||||
flock 9
|
||||
|
||||
manifest_core_count=0
|
||||
manifest_blocked_count=0
|
||||
manifest_core_sources=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_wasm_manifest_core.XXXXXX.txt")
|
||||
manifest_blocked_sources=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_wasm_manifest_blocked.XXXXXX.txt")
|
||||
trap 'rm -f "$manifest_core_sources" "$manifest_blocked_sources"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core > "$manifest_core_sources"
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" blocked > "$manifest_blocked_sources"
|
||||
manifest_core_count=$(wc -l < "$manifest_core_sources")
|
||||
manifest_blocked_count=$(wc -l < "$manifest_blocked_sources")
|
||||
manifest_core_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core)
|
||||
manifest_blocked_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" blocked)
|
||||
manifest_core_count=$(count_nonempty_lines "$manifest_core_output")
|
||||
manifest_blocked_count=$(count_nonempty_lines "$manifest_blocked_output")
|
||||
|
||||
if [[ "$manifest_core_count" -eq 0 || "$manifest_blocked_count" -eq 0 ]]; then
|
||||
echo "unexpected wasm manifest partition: core=$manifest_core_count blocked=$manifest_blocked_count" >&2
|
||||
|
||||
21
check-linuxcnc-inputs.sh
Executable file
21
check-linuxcnc-inputs.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
manifest=${1:-}
|
||||
|
||||
if [[ "$manifest" == "--root-only" ]]; then
|
||||
manifest=
|
||||
fi
|
||||
|
||||
if [[ -n "$manifest" && ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -2,10 +2,11 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kCssSpindleModeEvent = 960;
|
||||
constexpr int kConstantRpmSpindleModeEvent = 970;
|
||||
|
||||
void rotate_xy(double *x, double *y, double degrees) {
|
||||
const double radians = degrees * std::acos(-1.0) / 180.0;
|
||||
const double c = std::cos(radians);
|
||||
@@ -32,7 +33,9 @@ void CanonEventSink::reset() {
|
||||
tool_length_offset_ = {};
|
||||
xy_rotation_degrees_ = 0.0;
|
||||
callback_status_ = 0;
|
||||
kinematics_type_ = 1;
|
||||
// LinuxCNC xyzbc-trt-kins with sparm=identityfirst starts at switchkins-type 0.
|
||||
// Source: linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini.
|
||||
kinematics_type_ = 0;
|
||||
feed_override_ = false;
|
||||
speed_override_ = false;
|
||||
adaptive_feed_ = false;
|
||||
@@ -67,6 +70,24 @@ void CanonEventSink::configure_rtcp(bool enabled, double tool_length) {
|
||||
rtcp_tool_length_ = tool_length;
|
||||
}
|
||||
|
||||
void CanonEventSink::configure_xyzbc_trt(const LinuxCncXyzbcTrtParameters ¶meters) {
|
||||
xyzbc_trt_parameters_ = parameters;
|
||||
xyzbc_trt_parameters_configured_ = true;
|
||||
use_xyzac_trt_ = false;
|
||||
}
|
||||
|
||||
void CanonEventSink::configure_xyzac_trt(const LinuxCncXyzbcTrtParameters ¶meters) {
|
||||
xyzbc_trt_parameters_ = parameters;
|
||||
xyzbc_trt_parameters_configured_ = true;
|
||||
use_xyzac_trt_ = true;
|
||||
}
|
||||
|
||||
void CanonEventSink::configure_fiveaxis(double pivot_length, int kinematics_type) {
|
||||
fiveaxis_configured_ = true;
|
||||
fiveaxis_pivot_length_ = pivot_length;
|
||||
fiveaxis_kinematics_type_ = kinematics_type;
|
||||
}
|
||||
|
||||
void CanonEventSink::set_tool_length(int h_code, double tool_length) {
|
||||
if (h_code <= 0) {
|
||||
default_rtcp_tool_length_ = tool_length;
|
||||
@@ -119,15 +140,37 @@ void CanonEventSink::set_rtcp_state(bool enabled, int h_code, int line) {
|
||||
emit(event);
|
||||
}
|
||||
|
||||
void CanonEventSink::switch_kinematics(int kinematics_type, bool rtcp_enabled, int line) {
|
||||
void CanonEventSink::switch_kinematics(int kinematics_type, int line) {
|
||||
kinematics_type_ = kinematics_type;
|
||||
rtcp_enabled_ = rtcp_enabled;
|
||||
// Source: linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/{428,429,430}remap.ngc.
|
||||
// M68 E3 Q#<kinstype>, then M66 E0 L0 to force synchronization.
|
||||
set_analog_output(3, static_cast<double>(kinematics_type_), false, line);
|
||||
wait_input(0, 0, 0, 0.0, line);
|
||||
CncSimEvent event = base_event(CNC_SIM_EVENT_KINEMATICS_SWITCH, line);
|
||||
event.reserved = kinematics_type_;
|
||||
event.feed = rtcp_enabled_ ? 1.0 : 0.0;
|
||||
emit(event);
|
||||
}
|
||||
|
||||
void CanonEventSink::switch_m_code_kinematics(int m_code, int default_kinematics_type, int line) {
|
||||
if (fiveaxis_configured_) {
|
||||
// Source: linuxcnc/configs/sim/axis/vismach/5axis/bridgemill/remap_subs/{428,429,430}remap.ngc
|
||||
// M428 selects 5axiskins type 0, M429 selects identity type 1, M430 selects userk type 2.
|
||||
if (m_code == 428) {
|
||||
switch_kinematics(0, line);
|
||||
return;
|
||||
}
|
||||
if (m_code == 429) {
|
||||
switch_kinematics(1, line);
|
||||
return;
|
||||
}
|
||||
if (m_code == 430) {
|
||||
switch_kinematics(2, line);
|
||||
return;
|
||||
}
|
||||
}
|
||||
switch_kinematics(default_kinematics_type, line);
|
||||
}
|
||||
|
||||
void CanonEventSink::set_g5x_offset(int index, const CncSimPose &offset, int line) {
|
||||
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_G5X_OFFSET, line);
|
||||
event.tool = index;
|
||||
@@ -198,7 +241,7 @@ void CanonEventSink::set_spindle_mode(int spindle, double mode, int line) {
|
||||
CncSimEvent event = base_event(CNC_SIM_EVENT_COMMENT, line);
|
||||
event.tool = spindle;
|
||||
event.feed = mode;
|
||||
event.reserved = mode == 0.0 ? 970 : 960;
|
||||
event.reserved = mode == 0.0 ? kConstantRpmSpindleModeEvent : kCssSpindleModeEvent;
|
||||
emit(event);
|
||||
}
|
||||
|
||||
@@ -479,16 +522,67 @@ void CanonEventSink::emit(CncSimEvent event) {
|
||||
}
|
||||
|
||||
void CanonEventSink::emit_rtcp_pivot(int line, const CncSimPose &start, const CncSimPose &end) {
|
||||
if (!rtcp_enabled_ || rtcp_tool_length_ == 0.0 || callback_status_ != 0) {
|
||||
if (!rtcp_enabled_ || callback_status_ != 0) {
|
||||
return;
|
||||
}
|
||||
CncSimEvent event = base_event(CNC_SIM_EVENT_RTCP_PIVOT, line);
|
||||
event.start = rtcp_pivot_from_tool_tip(start, rtcp_tool_length_);
|
||||
event.end = rtcp_pivot_from_tool_tip(end, rtcp_tool_length_);
|
||||
const RtcpVector tool = rtcp_tool_vector_from_pose(end, rtcp_tool_length_);
|
||||
event.center.x = tool.x;
|
||||
event.center.y = tool.y;
|
||||
event.center.z = tool.z;
|
||||
if (fiveaxis_configured_ && kinematics_type_ == fiveaxis_kinematics_type_) {
|
||||
const LinuxCncFiveAxisJoints start_joints =
|
||||
linuxcnc_5axis_inverse(start, fiveaxis_pivot_length_);
|
||||
const LinuxCncFiveAxisJoints end_joints =
|
||||
linuxcnc_5axis_inverse(end, fiveaxis_pivot_length_);
|
||||
event.start.x = start_joints.x;
|
||||
event.start.y = start_joints.y;
|
||||
event.start.z = start_joints.z;
|
||||
event.start.b = start_joints.b;
|
||||
event.start.c = start_joints.c;
|
||||
event.start.w = start_joints.w;
|
||||
event.end.x = end_joints.x;
|
||||
event.end.y = end_joints.y;
|
||||
event.end.z = end_joints.z;
|
||||
event.end.b = end_joints.b;
|
||||
event.end.c = end_joints.c;
|
||||
event.end.w = end_joints.w;
|
||||
event.reserved = kinematics_type_;
|
||||
event.dwell_seconds = fiveaxis_pivot_length_;
|
||||
} else if (kinematics_type_ == 1 || kinematics_type_ == 2) {
|
||||
LinuxCncFiveAxisJoints start_joints{};
|
||||
LinuxCncFiveAxisJoints end_joints{};
|
||||
if (kinematics_type_ == 1) {
|
||||
LinuxCncXyzbcTrtParameters parameters = xyzbc_trt_parameters_configured_
|
||||
? xyzbc_trt_parameters_
|
||||
: linuxcnc_xyzbc_trt_default_parameters(rtcp_tool_length_);
|
||||
parameters.tool_offset = rtcp_tool_length_;
|
||||
if (use_xyzac_trt_) {
|
||||
start_joints = linuxcnc_xyzac_trt_inverse(start, parameters);
|
||||
end_joints = linuxcnc_xyzac_trt_inverse(end, parameters);
|
||||
} else {
|
||||
start_joints = linuxcnc_xyzbc_trt_inverse(start, parameters);
|
||||
end_joints = linuxcnc_xyzbc_trt_inverse(end, parameters);
|
||||
}
|
||||
} else {
|
||||
start_joints = linuxcnc_xyzbc_userk_inverse(start);
|
||||
end_joints = linuxcnc_xyzbc_userk_inverse(end);
|
||||
}
|
||||
event.start.x = start_joints.x;
|
||||
event.start.y = start_joints.y;
|
||||
event.start.z = start_joints.z;
|
||||
event.start.a = start_joints.a;
|
||||
event.start.b = start_joints.b;
|
||||
event.start.c = start_joints.c;
|
||||
event.start.w = start_joints.w;
|
||||
event.end.x = end_joints.x;
|
||||
event.end.y = end_joints.y;
|
||||
event.end.z = end_joints.z;
|
||||
event.end.a = end_joints.a;
|
||||
event.end.b = end_joints.b;
|
||||
event.end.c = end_joints.c;
|
||||
event.end.w = end_joints.w;
|
||||
event.reserved = kinematics_type_;
|
||||
event.dwell_seconds = rtcp_tool_length_;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
emit(event);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "cnc_sim_api.h"
|
||||
#include "rtcp_kinematics.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -12,11 +13,15 @@ public:
|
||||
bool callback_aborted() const;
|
||||
void set_block_delete(bool enabled);
|
||||
void configure_rtcp(bool enabled, double tool_length);
|
||||
void configure_xyzbc_trt(const LinuxCncXyzbcTrtParameters ¶meters);
|
||||
void configure_xyzac_trt(const LinuxCncXyzbcTrtParameters ¶meters);
|
||||
void configure_fiveaxis(double pivot_length, int kinematics_type);
|
||||
void set_tool_length(int h_code, double tool_length);
|
||||
void set_tool_length_offset(const CncSimPose &offset);
|
||||
void apply_tool_length_offset(const CncSimPose &offset);
|
||||
void set_rtcp_state(bool enabled, int h_code, int line);
|
||||
void switch_kinematics(int kinematics_type, bool rtcp_enabled, int line);
|
||||
void switch_kinematics(int kinematics_type, int line);
|
||||
void switch_m_code_kinematics(int m_code, int default_kinematics_type, int line);
|
||||
void set_g5x_offset(int index, const CncSimPose &offset, int line);
|
||||
void set_g92_offset(const CncSimPose &offset, int line);
|
||||
void set_xy_rotation(double angle_degrees, int line);
|
||||
@@ -97,9 +102,15 @@ private:
|
||||
double default_rtcp_tool_length_ = 0.0;
|
||||
double rtcp_tool_length_ = 0.0;
|
||||
int rtcp_h_code_ = 0;
|
||||
LinuxCncXyzbcTrtParameters xyzbc_trt_parameters_{};
|
||||
bool xyzbc_trt_parameters_configured_ = false;
|
||||
bool use_xyzac_trt_ = false;
|
||||
bool fiveaxis_configured_ = false;
|
||||
double fiveaxis_pivot_length_ = 250.0;
|
||||
int fiveaxis_kinematics_type_ = 0;
|
||||
CncSimPose tool_length_offset_{};
|
||||
double xy_rotation_degrees_ = 0.0;
|
||||
int kinematics_type_ = 1;
|
||||
int kinematics_type_ = 0;
|
||||
bool feed_override_ = false;
|
||||
bool speed_override_ = false;
|
||||
bool adaptive_feed_ = false;
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
|
||||
struct CncSimHandle {
|
||||
CncSimDialect dialect = CNC_SIM_DIALECT_LINUXCNC;
|
||||
#ifdef CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND
|
||||
GcodeBackendKind backend = GcodeBackendKind::LinuxCncRs274;
|
||||
#else
|
||||
GcodeBackendKind backend = GcodeBackendKind::Smoke;
|
||||
#endif
|
||||
std::string last_error;
|
||||
CanonEventSink sink;
|
||||
};
|
||||
@@ -128,6 +132,86 @@ void apply_tool_length_table(CanonEventSink &sink, const std::string &compact) {
|
||||
}
|
||||
}
|
||||
|
||||
bool find_number_any(const std::string &compact, double *value, const char *first) {
|
||||
return find_number_value(compact, first, value);
|
||||
}
|
||||
|
||||
template <typename... Keys>
|
||||
bool find_number_any(const std::string &compact, double *value, const char *first, Keys... rest) {
|
||||
return find_number_value(compact, first, value) || find_number_any(compact, value, rest...);
|
||||
}
|
||||
|
||||
bool contains_bool_any(const std::string &compact, bool *value, const char *first) {
|
||||
return contains_bool_value(compact, first, value);
|
||||
}
|
||||
|
||||
template <typename... Keys>
|
||||
bool contains_bool_any(const std::string &compact, bool *value, const char *first, Keys... rest) {
|
||||
return contains_bool_value(compact, first, value) || contains_bool_any(compact, value, rest...);
|
||||
}
|
||||
|
||||
void apply_xyzbc_trt_config(CanonEventSink &sink, const std::string &compact) {
|
||||
LinuxCncXyzbcTrtParameters parameters = linuxcnc_xyzbc_trt_default_parameters(0.0);
|
||||
bool configured = false;
|
||||
const bool xyzac = compact.find("\"trt\":\"xyzac\"") != std::string::npos ||
|
||||
compact.find("\"kinematics\":\"xyzac-trt\"") != std::string::npos ||
|
||||
compact.find("\"switchkins\":\"xyzac-trt\"") != std::string::npos;
|
||||
const bool xyzbc = compact.find("\"trt\":\"xyzbc\"") != std::string::npos ||
|
||||
compact.find("\"kinematics\":\"xyzbc-trt\"") != std::string::npos ||
|
||||
compact.find("\"switchkins\":\"xyzbc-trt\"") != std::string::npos;
|
||||
|
||||
configured = find_number_any(compact, ¶meters.x_rot_point, "xrotpoint", "x_rot_point", "x-rot-point") ||
|
||||
configured;
|
||||
configured = find_number_any(compact, ¶meters.y_rot_point, "yrotpoint", "y_rot_point", "y-rot-point") ||
|
||||
configured;
|
||||
configured = find_number_any(compact, ¶meters.z_rot_point, "zrotpoint", "z_rot_point", "z-rot-point") ||
|
||||
configured;
|
||||
configured = find_number_any(compact, ¶meters.x_offset, "xoffset", "x_offset", "x-offset") ||
|
||||
configured;
|
||||
configured = find_number_any(compact, ¶meters.y_offset, "yoffset", "y_offset", "y-offset") ||
|
||||
configured;
|
||||
configured = find_number_any(compact, ¶meters.z_offset, "zoffset", "z_offset", "z-offset") ||
|
||||
configured;
|
||||
configured = contains_bool_any(compact,
|
||||
¶meters.conventional_directions,
|
||||
"conventionaldirections",
|
||||
"conventional_directions",
|
||||
"conventional-directions") ||
|
||||
configured;
|
||||
|
||||
if (configured || xyzac || xyzbc) {
|
||||
configured = true;
|
||||
}
|
||||
if (configured && xyzac) {
|
||||
sink.configure_xyzac_trt(parameters);
|
||||
} else if (configured) {
|
||||
sink.configure_xyzbc_trt(parameters);
|
||||
}
|
||||
}
|
||||
|
||||
void apply_fiveaxis_config(CanonEventSink &sink, const std::string &compact) {
|
||||
const bool fiveaxis = compact.find("\"kinematics\":\"5axiskins\"") != std::string::npos ||
|
||||
compact.find("\"switchkins\":\"5axiskins\"") != std::string::npos ||
|
||||
compact.find("\"kinematics\":\"5axis\"") != std::string::npos;
|
||||
double pivot_length = 250.0;
|
||||
const bool has_pivot_length = find_number_any(compact,
|
||||
&pivot_length,
|
||||
"pivotlength",
|
||||
"pivot_length",
|
||||
"pivot-length");
|
||||
double kinematics_type = 0.0;
|
||||
const bool has_kinematics_type = find_number_any(compact,
|
||||
&kinematics_type,
|
||||
"fiveaxiskinematicstype",
|
||||
"fiveaxis_kinematics_type",
|
||||
"fiveaxis-kinematics-type",
|
||||
"kinematicstype",
|
||||
"kinematics_type");
|
||||
if (fiveaxis || has_pivot_length || has_kinematics_type) {
|
||||
sink.configure_fiveaxis(pivot_length, static_cast<int>(kinematics_type));
|
||||
}
|
||||
}
|
||||
|
||||
int apply_config(CncSimHandle *handle, const std::string &json) {
|
||||
if (json.empty()) {
|
||||
return 0;
|
||||
@@ -158,6 +242,8 @@ int apply_config(CncSimHandle *handle, const std::string &json) {
|
||||
handle->sink.set_block_delete(block_delete);
|
||||
}
|
||||
apply_tool_length_table(handle->sink, compact);
|
||||
apply_xyzbc_trt_config(handle->sink, compact);
|
||||
apply_fiveaxis_config(handle->sink, compact);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kToolLengthOffsetEvent = 430;
|
||||
|
||||
CanonEventSink *active_sink = nullptr;
|
||||
int active_line = 0;
|
||||
bool flood_on = false;
|
||||
@@ -515,7 +517,7 @@ void USE_TOOL_LENGTH_OFFSET(const EmcPose &offset) {
|
||||
event.version = 1;
|
||||
event.type = CNC_SIM_EVENT_COMMENT;
|
||||
event.line = event_line();
|
||||
event.reserved = 430;
|
||||
event.reserved = kToolLengthOffsetEvent;
|
||||
event.start = tool_offset;
|
||||
active_sink->emit_raw(event);
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
||||
++line_number;
|
||||
cnc_sim_linuxcnc_set_current_line(line_number);
|
||||
std::vector<SimulatorGcodeControlAction> control_actions;
|
||||
if (parse_simulator_gcode_control_line(line, &control_actions)) {
|
||||
if (parse_simulator_gcode_control_line(line, sink.block_delete(), &control_actions)) {
|
||||
bool simulator_only_line = true;
|
||||
for (const auto &action : control_actions) {
|
||||
emit_simulator_gcode_control_action(sink, action, line_number);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,10 +8,134 @@ struct RtcpVector {
|
||||
double z;
|
||||
};
|
||||
|
||||
// Rotation order is intrinsic tool orientation A then B then C, represented as
|
||||
// Rz(C) * Ry(B) * Rx(A) applied to a local tool vector.
|
||||
RtcpVector rtcp_rotate_abc_degrees(RtcpVector vector, double a_deg, double b_deg, double c_deg);
|
||||
struct LinuxCncFiveAxisJoints {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double w;
|
||||
};
|
||||
|
||||
RtcpVector rtcp_tool_vector_from_pose(const CncSimPose &pose, double tool_length);
|
||||
CncSimPose rtcp_pivot_from_tool_tip(const CncSimPose &tool_tip, double tool_length);
|
||||
CncSimPose rtcp_tool_tip_from_pivot(const CncSimPose &pivot, double tool_length);
|
||||
struct LinuxCncAxisJoints {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double u;
|
||||
double v;
|
||||
double w;
|
||||
};
|
||||
|
||||
struct LinuxCncXyzbcTrtParameters {
|
||||
double x_rot_point;
|
||||
double y_rot_point;
|
||||
double z_rot_point;
|
||||
double x_offset;
|
||||
double y_offset;
|
||||
double z_offset;
|
||||
double tool_offset;
|
||||
bool conventional_directions;
|
||||
};
|
||||
|
||||
struct LinuxCncScaraParameters {
|
||||
double d1;
|
||||
double d2;
|
||||
double d3;
|
||||
double d4;
|
||||
double d5;
|
||||
double d6;
|
||||
};
|
||||
|
||||
struct LinuxCncXyzabTdrParameters {
|
||||
double tool_offset_z;
|
||||
double x_offset;
|
||||
double z_offset;
|
||||
double x_rot_point;
|
||||
double y_rot_point;
|
||||
double z_rot_point;
|
||||
};
|
||||
|
||||
struct LinuxCncPumaParameters {
|
||||
double a2;
|
||||
double a3;
|
||||
double d3;
|
||||
double d4;
|
||||
double d6;
|
||||
};
|
||||
|
||||
struct LinuxCncGenserParameters {
|
||||
double a[6];
|
||||
double alpha[6];
|
||||
double d[6];
|
||||
int unrotate[6];
|
||||
};
|
||||
|
||||
struct LinuxCncScaraJoints {
|
||||
double j0;
|
||||
double j1;
|
||||
double j2;
|
||||
double j3;
|
||||
double j4;
|
||||
double j5;
|
||||
};
|
||||
|
||||
LinuxCncAxisJoints linuxcnc_identity_default_joints();
|
||||
CncSimPose linuxcnc_identity_forward(const LinuxCncAxisJoints &joints);
|
||||
LinuxCncAxisJoints linuxcnc_identity_inverse(const CncSimPose &pose);
|
||||
|
||||
CncSimPose linuxcnc_rotatekins_forward(const LinuxCncAxisJoints &joints);
|
||||
LinuxCncAxisJoints linuxcnc_rotatekins_inverse(const CncSimPose &pose);
|
||||
|
||||
CncSimPose linuxcnc_5axis_forward(const LinuxCncFiveAxisJoints &joints, double pivot_length);
|
||||
LinuxCncFiveAxisJoints linuxcnc_5axis_inverse(const CncSimPose &pose, double pivot_length);
|
||||
|
||||
LinuxCncXyzbcTrtParameters linuxcnc_xyzbc_trt_default_parameters(double tool_offset);
|
||||
CncSimPose linuxcnc_xyzbc_trt_forward(const LinuxCncFiveAxisJoints &joints,
|
||||
const LinuxCncXyzbcTrtParameters ¶meters);
|
||||
LinuxCncFiveAxisJoints linuxcnc_xyzbc_trt_inverse(const CncSimPose &pose,
|
||||
const LinuxCncXyzbcTrtParameters ¶meters);
|
||||
CncSimPose linuxcnc_xyzac_trt_forward(const LinuxCncFiveAxisJoints &joints,
|
||||
const LinuxCncXyzbcTrtParameters ¶meters);
|
||||
LinuxCncFiveAxisJoints linuxcnc_xyzac_trt_inverse(const CncSimPose &pose,
|
||||
const LinuxCncXyzbcTrtParameters ¶meters);
|
||||
CncSimPose linuxcnc_xyzbc_userk_forward(const LinuxCncFiveAxisJoints &joints);
|
||||
LinuxCncFiveAxisJoints linuxcnc_xyzbc_userk_inverse(const CncSimPose &pose);
|
||||
|
||||
LinuxCncScaraParameters linuxcnc_scara_default_parameters();
|
||||
CncSimPose linuxcnc_scara_forward(const LinuxCncScaraJoints &joints,
|
||||
const LinuxCncScaraParameters ¶meters,
|
||||
int *iflags);
|
||||
LinuxCncScaraJoints linuxcnc_scara_inverse(const CncSimPose &pose,
|
||||
const LinuxCncScaraParameters ¶meters,
|
||||
int iflags);
|
||||
|
||||
LinuxCncXyzabTdrParameters linuxcnc_xyzab_tdr_default_parameters(double tool_offset_z);
|
||||
CncSimPose linuxcnc_xyzab_tdr_identity_forward(const LinuxCncAxisJoints &joints);
|
||||
LinuxCncAxisJoints linuxcnc_xyzab_tdr_identity_inverse(const CncSimPose &pose);
|
||||
CncSimPose linuxcnc_xyzab_tdr_tcp_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncXyzabTdrParameters ¶meters);
|
||||
LinuxCncAxisJoints linuxcnc_xyzab_tdr_tcp_inverse(const CncSimPose &pose,
|
||||
const LinuxCncXyzabTdrParameters ¶meters);
|
||||
|
||||
LinuxCncPumaParameters linuxcnc_puma_default_parameters();
|
||||
CncSimPose linuxcnc_puma_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncPumaParameters ¶meters,
|
||||
int *iflags);
|
||||
LinuxCncAxisJoints linuxcnc_puma_inverse(const CncSimPose &pose,
|
||||
const LinuxCncAxisJoints ¤t_joints,
|
||||
const LinuxCncPumaParameters ¶meters,
|
||||
int iflags,
|
||||
int *fflags);
|
||||
|
||||
LinuxCncGenserParameters linuxcnc_genser_puma560_parameters();
|
||||
CncSimPose linuxcnc_genser_forward(const LinuxCncAxisJoints &joints,
|
||||
const LinuxCncGenserParameters ¶meters);
|
||||
LinuxCncAxisJoints linuxcnc_genser_inverse(const CncSimPose &pose,
|
||||
const LinuxCncAxisJoints &joint_estimate,
|
||||
const LinuxCncGenserParameters ¶meters,
|
||||
int *iterations,
|
||||
int max_iterations = 100);
|
||||
|
||||
@@ -6,31 +6,155 @@
|
||||
|
||||
namespace {
|
||||
|
||||
std::string strip_line_comment(const std::string &line) {
|
||||
bool strip_line_comment(const std::string &line, bool block_delete, std::string *stripped) {
|
||||
std::string out;
|
||||
bool in_paren = false;
|
||||
bool saw_code = false;
|
||||
for (char raw : line) {
|
||||
const char ch = static_cast<char>(std::toupper(static_cast<unsigned char>(raw)));
|
||||
if (in_paren) {
|
||||
if (ch == '(') {
|
||||
return false;
|
||||
}
|
||||
if (ch == ')') {
|
||||
in_paren = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (ch == '(') {
|
||||
saw_code = true;
|
||||
in_paren = true;
|
||||
continue;
|
||||
}
|
||||
if (ch == ';') {
|
||||
break;
|
||||
}
|
||||
if (!saw_code && std::isspace(static_cast<unsigned char>(ch))) {
|
||||
out.push_back(ch);
|
||||
continue;
|
||||
}
|
||||
if (!saw_code && ch == '/') {
|
||||
if (block_delete) {
|
||||
return false;
|
||||
}
|
||||
saw_code = true;
|
||||
continue;
|
||||
}
|
||||
saw_code = true;
|
||||
out.push_back(ch);
|
||||
}
|
||||
return out;
|
||||
if (in_paren) {
|
||||
return false;
|
||||
}
|
||||
*stripped = out;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool g_code_is(double actual, double expected) {
|
||||
return std::fabs(actual - expected) < 0.0001;
|
||||
bool linuxcnc_integer_word_value(double value, int *integer) {
|
||||
*integer = static_cast<int>(std::floor(value));
|
||||
const double fraction = value - *integer;
|
||||
if (fraction > 0.9999) {
|
||||
*integer = static_cast<int>(std::ceil(value));
|
||||
return true;
|
||||
}
|
||||
return fraction <= 0.0001;
|
||||
}
|
||||
|
||||
bool linuxcnc_g_word_value(double value, int *g_code) {
|
||||
const double scaled = value * 10.0;
|
||||
int parsed = static_cast<int>(std::floor(scaled));
|
||||
const double fraction = scaled - parsed;
|
||||
if (fraction > 0.999) {
|
||||
parsed = static_cast<int>(std::ceil(scaled));
|
||||
} else if (fraction > 0.001) {
|
||||
return false;
|
||||
}
|
||||
if (parsed < 0 || parsed > 999) {
|
||||
return false;
|
||||
}
|
||||
*g_code = parsed;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_linuxcnc_real_number(const char *text, size_t start, double *value, size_t *end_index) {
|
||||
const char first = text[start];
|
||||
const char next = text[start + 1];
|
||||
if (first == '[') {
|
||||
double nested = 0.0;
|
||||
size_t nested_end = start + 1;
|
||||
if (!read_linuxcnc_real_number(text, start + 1, &nested, &nested_end) ||
|
||||
text[nested_end] != ']') {
|
||||
return false;
|
||||
}
|
||||
*value = nested;
|
||||
*end_index = nested_end + 1;
|
||||
return true;
|
||||
}
|
||||
if ((first == '+' || first == '-') &&
|
||||
next != '\0' &&
|
||||
!std::isdigit(static_cast<unsigned char>(next)) &&
|
||||
next != '.') {
|
||||
double nested = 0.0;
|
||||
size_t nested_end = start + 1;
|
||||
if (!read_linuxcnc_real_number(text, start + 1, &nested, &nested_end)) {
|
||||
return false;
|
||||
}
|
||||
*value = first == '-' ? -nested : nested;
|
||||
*end_index = nested_end;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t i = start;
|
||||
while (text[i] == '+' || text[i] == '-') {
|
||||
++i;
|
||||
}
|
||||
const size_t number_start = i;
|
||||
while (std::isdigit(static_cast<unsigned char>(text[i])) || text[i] == '.') {
|
||||
++i;
|
||||
}
|
||||
if (i == start || i == number_start) {
|
||||
return false;
|
||||
}
|
||||
std::string token(text + start, i - start);
|
||||
char *end = nullptr;
|
||||
const double parsed = std::strtod(token.c_str(), &end);
|
||||
if (end != token.c_str() + token.size()) {
|
||||
return false;
|
||||
}
|
||||
*value = parsed;
|
||||
*end_index = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool skip_linuxcnc_leading_n_number(const std::string &stripped, std::string *without_n) {
|
||||
size_t i = 0;
|
||||
while (std::isspace(static_cast<unsigned char>(stripped[i]))) {
|
||||
++i;
|
||||
}
|
||||
if (stripped[i] != 'N') {
|
||||
*without_n = stripped;
|
||||
return true;
|
||||
}
|
||||
++i;
|
||||
const size_t integer_start = i;
|
||||
while (std::isdigit(static_cast<unsigned char>(stripped[i]))) {
|
||||
++i;
|
||||
}
|
||||
if (i == integer_start) {
|
||||
return false;
|
||||
}
|
||||
if (stripped[i] == '.') {
|
||||
++i;
|
||||
const size_t fraction_start = i;
|
||||
while (std::isdigit(static_cast<unsigned char>(stripped[i]))) {
|
||||
++i;
|
||||
}
|
||||
if (i == fraction_start) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*without_n = stripped.substr(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_m_control_line(const std::string &stripped,
|
||||
@@ -46,9 +170,13 @@ bool parse_m_control_line(const std::string &stripped,
|
||||
return false;
|
||||
}
|
||||
++i;
|
||||
char *end = nullptr;
|
||||
const long value = std::strtol(text + i, &end, 10);
|
||||
if (end == text + i) {
|
||||
double raw_value = 0.0;
|
||||
size_t end = i;
|
||||
if (!read_linuxcnc_real_number(text, i, &raw_value, &end)) {
|
||||
return false;
|
||||
}
|
||||
int value = 0;
|
||||
if (!linuxcnc_integer_word_value(raw_value, &value) || value < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -56,19 +184,19 @@ bool parse_m_control_line(const std::string &stripped,
|
||||
action.kind = SimulatorGcodeControlKind::KinematicsSwitch;
|
||||
if (value == 428) {
|
||||
action.value = 1;
|
||||
action.rtcp_enabled = true;
|
||||
action.m_code = 428;
|
||||
} else if (value == 429) {
|
||||
action.value = 0;
|
||||
action.rtcp_enabled = false;
|
||||
action.m_code = 429;
|
||||
} else if (value == 430) {
|
||||
action.value = 2;
|
||||
action.rtcp_enabled = true;
|
||||
action.m_code = 430;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
actions->push_back(action);
|
||||
saw_code = true;
|
||||
i = static_cast<size_t>(end - text);
|
||||
i = end;
|
||||
}
|
||||
return saw_code;
|
||||
}
|
||||
@@ -78,7 +206,9 @@ bool parse_rtcp_control_line(const std::string &stripped,
|
||||
const char *text = stripped.c_str();
|
||||
std::vector<SimulatorGcodeControlAction> parsed;
|
||||
int h_code = 0;
|
||||
bool saw_h_word = false;
|
||||
bool saw_rtcp_code = false;
|
||||
bool saw_rtcp_g_word = false;
|
||||
|
||||
for (size_t i = 0; text[i] != '\0';) {
|
||||
if (std::isspace(static_cast<unsigned char>(text[i]))) {
|
||||
@@ -90,26 +220,44 @@ bool parse_rtcp_control_line(const std::string &stripped,
|
||||
return false;
|
||||
}
|
||||
++i;
|
||||
char *end = nullptr;
|
||||
const double value = std::strtod(text + i, &end);
|
||||
if (end == text + i) {
|
||||
double value = 0.0;
|
||||
size_t end = i;
|
||||
if (!read_linuxcnc_real_number(text, i, &value, &end)) {
|
||||
return false;
|
||||
}
|
||||
if (letter == 'H') {
|
||||
h_code = static_cast<int>(std::lround(value));
|
||||
} else if (g_code_is(value, 43.4) || g_code_is(value, 43.5) || g_code_is(value, 49.0)) {
|
||||
if (saw_h_word) {
|
||||
return false;
|
||||
}
|
||||
if (!linuxcnc_integer_word_value(value, &h_code) || h_code < -1) {
|
||||
return false;
|
||||
}
|
||||
saw_h_word = true;
|
||||
} else {
|
||||
int g_code = 0;
|
||||
if (!linuxcnc_g_word_value(value, &g_code) ||
|
||||
(g_code != 434 && g_code != 435 && g_code != 490)) {
|
||||
return false;
|
||||
}
|
||||
if (saw_rtcp_g_word) {
|
||||
return false;
|
||||
}
|
||||
SimulatorGcodeControlAction action{};
|
||||
action.kind = SimulatorGcodeControlKind::RtcpState;
|
||||
action.value = static_cast<int>(std::lround(value * 10.0));
|
||||
action.rtcp_enabled = g_code_is(value, 43.4) || g_code_is(value, 43.5);
|
||||
action.value = g_code;
|
||||
action.rtcp_enabled = g_code == 434 || g_code == 435;
|
||||
parsed.push_back(action);
|
||||
saw_rtcp_code = true;
|
||||
} else {
|
||||
return false;
|
||||
saw_rtcp_g_word = true;
|
||||
}
|
||||
i = static_cast<size_t>(end - text);
|
||||
i = end;
|
||||
}
|
||||
|
||||
for (const auto &action : parsed) {
|
||||
if (!action.rtcp_enabled && saw_h_word) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (auto &action : parsed) {
|
||||
action.h_code = action.rtcp_enabled ? h_code : 0;
|
||||
actions->push_back(action);
|
||||
@@ -121,13 +269,26 @@ bool parse_rtcp_control_line(const std::string &stripped,
|
||||
|
||||
bool parse_simulator_gcode_control_line(const std::string &line,
|
||||
std::vector<SimulatorGcodeControlAction> *actions) {
|
||||
return parse_simulator_gcode_control_line(line, false, actions);
|
||||
}
|
||||
|
||||
bool parse_simulator_gcode_control_line(const std::string &line,
|
||||
bool block_delete,
|
||||
std::vector<SimulatorGcodeControlAction> *actions) {
|
||||
actions->clear();
|
||||
const std::string stripped = strip_line_comment(line);
|
||||
if (parse_m_control_line(stripped, actions)) {
|
||||
std::string stripped;
|
||||
if (!strip_line_comment(line, block_delete, &stripped)) {
|
||||
return false;
|
||||
}
|
||||
std::string control_line;
|
||||
if (!skip_linuxcnc_leading_n_number(stripped, &control_line)) {
|
||||
return false;
|
||||
}
|
||||
if (parse_m_control_line(control_line, actions)) {
|
||||
return true;
|
||||
}
|
||||
actions->clear();
|
||||
if (parse_rtcp_control_line(stripped, actions)) {
|
||||
if (parse_rtcp_control_line(control_line, actions)) {
|
||||
return true;
|
||||
}
|
||||
actions->clear();
|
||||
@@ -138,7 +299,7 @@ void emit_simulator_gcode_control_action(CanonEventSink &sink,
|
||||
const SimulatorGcodeControlAction &action,
|
||||
int line) {
|
||||
if (action.kind == SimulatorGcodeControlKind::KinematicsSwitch) {
|
||||
sink.switch_kinematics(action.value, action.rtcp_enabled, line);
|
||||
sink.switch_m_code_kinematics(action.m_code, action.value, line);
|
||||
} else if (action.kind == SimulatorGcodeControlKind::RtcpState) {
|
||||
sink.set_rtcp_state(action.rtcp_enabled, action.h_code, line);
|
||||
}
|
||||
|
||||
@@ -13,12 +13,16 @@ enum class SimulatorGcodeControlKind {
|
||||
struct SimulatorGcodeControlAction {
|
||||
SimulatorGcodeControlKind kind;
|
||||
int value;
|
||||
int m_code;
|
||||
bool rtcp_enabled;
|
||||
int h_code;
|
||||
};
|
||||
|
||||
bool parse_simulator_gcode_control_line(const std::string &line,
|
||||
std::vector<SimulatorGcodeControlAction> *actions);
|
||||
bool parse_simulator_gcode_control_line(const std::string &line,
|
||||
bool block_delete,
|
||||
std::vector<SimulatorGcodeControlAction> *actions);
|
||||
void emit_simulator_gcode_control_action(CanonEventSink &sink,
|
||||
const SimulatorGcodeControlAction &action,
|
||||
int line);
|
||||
|
||||
@@ -149,11 +149,13 @@ constexpr double kRadiusToleranceMm = kRadiusToleranceInch * kMmPerInch;
|
||||
constexpr double kCenterArcRadiusToleranceInch = 2.0 * 0.001 * M_SQRT2;
|
||||
constexpr double kCenterArcRadiusToleranceMm = 2.0 * 0.01 * M_SQRT2;
|
||||
constexpr double kSpiralRelativeTolerance = 0.001;
|
||||
constexpr int kConstantRpmSpindleModeEvent = 970;
|
||||
constexpr int kCutterCompOffEvent = 400;
|
||||
constexpr int kCutterCompLeftEvent = 410;
|
||||
constexpr int kCutterCompRightEvent = 420;
|
||||
constexpr int kCutterCompLeftExplicitEvent = 411;
|
||||
constexpr int kCutterCompRightExplicitEvent = 421;
|
||||
constexpr int kToolLengthOffsetEvent = 430;
|
||||
|
||||
enum class LinuxCncReaderSymbol {
|
||||
None,
|
||||
@@ -178,6 +180,12 @@ size_t leading_special_word_start(const std::string &line);
|
||||
bool is_numeric_m98_subprogram_header(const std::string &line);
|
||||
OwordKind oword_kind(const std::string &line);
|
||||
bool integer_word_value(const std::unordered_map<char, double> &words, char letter, int *value);
|
||||
bool evaluate_expression(const std::string &text,
|
||||
const std::vector<CallFrame> &call_stack,
|
||||
const std::unordered_map<int, double> ¶meters,
|
||||
const std::unordered_map<std::string, double> &named_parameters,
|
||||
double *value,
|
||||
std::string *error);
|
||||
|
||||
template <size_t Size>
|
||||
bool contains_int(const std::array<int, Size> &values, int value) {
|
||||
@@ -685,6 +693,91 @@ LinuxCncIntegerReadResult read_linuxcnc_integer_value(const std::string &text,
|
||||
return LinuxCncIntegerReadResult::Ok;
|
||||
}
|
||||
|
||||
bool is_current_position_parameter_index(int index) {
|
||||
return index >= 5420 && index <= 5428;
|
||||
}
|
||||
|
||||
bool line_reads_current_position_parameter(const std::string &line,
|
||||
const std::vector<CallFrame> &call_stack,
|
||||
const std::unordered_map<int, double> ¶meters,
|
||||
const std::unordered_map<std::string, double> &named_parameters) {
|
||||
for (size_t i = 0; i < line.size(); ++i) {
|
||||
if (line[i] != '#') {
|
||||
continue;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
size_t index_end = i + 1;
|
||||
size_t parameter_start = i + 1;
|
||||
while (parameter_start < line.size() &&
|
||||
std::isspace(static_cast<unsigned char>(line[parameter_start]))) {
|
||||
++parameter_start;
|
||||
}
|
||||
if (parameter_start < line.size() && line[parameter_start] == '[') {
|
||||
const size_t close = find_matching_square_bracket(line, parameter_start);
|
||||
if (close != std::string::npos) {
|
||||
size_t bracket_index_end = parameter_start + 1;
|
||||
const LinuxCncIntegerReadResult bracket_result =
|
||||
read_linuxcnc_integer_value(line, parameter_start + 1, &index, &bracket_index_end);
|
||||
size_t after_bracket_index = bracket_index_end;
|
||||
while (after_bracket_index < close &&
|
||||
std::isspace(static_cast<unsigned char>(line[after_bracket_index]))) {
|
||||
++after_bracket_index;
|
||||
}
|
||||
bool has_current_position_index =
|
||||
bracket_result == LinuxCncIntegerReadResult::Ok &&
|
||||
after_bracket_index == close &&
|
||||
is_current_position_parameter_index(index);
|
||||
if (!has_current_position_index) {
|
||||
double index_value = 0.0;
|
||||
if (evaluate_expression(line.substr(parameter_start + 1,
|
||||
close - parameter_start - 1),
|
||||
call_stack,
|
||||
parameters,
|
||||
named_parameters,
|
||||
&index_value,
|
||||
nullptr)) {
|
||||
int expression_index = 0;
|
||||
has_current_position_index =
|
||||
linuxcnc_integer_from_real(index_value, &expression_index) ==
|
||||
LinuxCncIntegerReadResult::Ok &&
|
||||
is_current_position_parameter_index(expression_index);
|
||||
}
|
||||
}
|
||||
if (has_current_position_index) {
|
||||
size_t after_close = close + 1;
|
||||
while (after_close < line.size() &&
|
||||
std::isspace(static_cast<unsigned char>(line[after_close]))) {
|
||||
++after_close;
|
||||
}
|
||||
if (after_close < line.size() && line[after_close] == '=') {
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const LinuxCncIntegerReadResult result =
|
||||
read_linuxcnc_integer_value(line, i + 1, &index, &index_end);
|
||||
if (result != LinuxCncIntegerReadResult::Ok ||
|
||||
!is_current_position_parameter_index(index)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t after_index = index_end;
|
||||
while (after_index < line.size() &&
|
||||
std::isspace(static_cast<unsigned char>(line[after_index]))) {
|
||||
++after_index;
|
||||
}
|
||||
if (after_index < line.size() && line[after_index] == '=') {
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool parse_linuxcnc_real_number(const char *text, double *value, size_t *consumed) {
|
||||
size_t end = 0;
|
||||
while (text[end] == '+' || text[end] == '-') {
|
||||
@@ -1190,6 +1283,7 @@ bool parse_word_list_impl(const std::string &line, ParsedWordList *parsed, std::
|
||||
parsed->theta_flag = false;
|
||||
parsed->theta_value = 0.0;
|
||||
std::array<bool, 26> seen_letters{};
|
||||
std::array<double, 26> seen_letter_values{};
|
||||
const char *text = line.c_str();
|
||||
for (size_t i = 0; text[i] != '\0';) {
|
||||
if (std::isspace(static_cast<unsigned char>(text[i]))) {
|
||||
@@ -1338,13 +1432,27 @@ bool parse_word_list_impl(const std::string &line, ParsedWordList *parsed, std::
|
||||
if (letter != 'G' && letter != 'M') {
|
||||
const size_t letter_index = static_cast<size_t>(letter - 'A');
|
||||
if (strict && seen_letters[letter_index]) {
|
||||
if (error) {
|
||||
*error = "Multiple " + std::string(1, static_cast<char>(std::tolower(static_cast<unsigned char>(letter)))) +
|
||||
" words on one line";
|
||||
if ((letter == 'P' || letter == 'Q') && seen_letter_values[letter_index] <= -1.0) {
|
||||
parsed->words.erase(std::remove_if(parsed->words.begin(),
|
||||
parsed->words.end(),
|
||||
[letter](const Word &word) {
|
||||
return word.letter == letter;
|
||||
}),
|
||||
parsed->words.end());
|
||||
} else {
|
||||
if (error) {
|
||||
const char duplicate_letter =
|
||||
(letter == 'U' || letter == 'V' || letter == 'W')
|
||||
? letter
|
||||
: static_cast<char>(std::tolower(static_cast<unsigned char>(letter)));
|
||||
*error = "Multiple " + std::string(1, duplicate_letter) +
|
||||
" words on one line";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
seen_letters[letter_index] = true;
|
||||
seen_letter_values[letter_index] = value;
|
||||
}
|
||||
parsed->words.push_back({letter, value});
|
||||
i = next;
|
||||
@@ -3309,7 +3417,7 @@ std::string expand_expressions_and_parameters(const std::string &line,
|
||||
const size_t close = find_matching_square_bracket(line, function_start);
|
||||
if (close == std::string::npos) {
|
||||
if (error) {
|
||||
*error = "unterminated bracket expression";
|
||||
*error = "Unclosed expression";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -3356,7 +3464,7 @@ std::string expand_expressions_and_parameters(const std::string &line,
|
||||
const size_t close = find_matching_square_bracket(line, i);
|
||||
if (close == std::string::npos) {
|
||||
if (error) {
|
||||
*error = "unterminated bracket expression";
|
||||
*error = "Unclosed expression";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -3391,7 +3499,7 @@ std::string expand_expressions_and_parameters(const std::string &line,
|
||||
const size_t close = find_matching_square_bracket(line, end);
|
||||
if (close == std::string::npos) {
|
||||
if (error) {
|
||||
*error = "unterminated indirect parameter expression";
|
||||
*error = "Unclosed expression";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -3400,7 +3508,7 @@ std::string expand_expressions_and_parameters(const std::string &line,
|
||||
const size_t close = line.find('>', end + 1);
|
||||
if (close == std::string::npos) {
|
||||
if (error) {
|
||||
*error = "unterminated indirect named parameter expression";
|
||||
*error = "Named parameter not terminated";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -3445,7 +3553,7 @@ std::string expand_expressions_and_parameters(const std::string &line,
|
||||
const size_t close = find_matching_square_bracket(line, j);
|
||||
if (close == std::string::npos) {
|
||||
if (error) {
|
||||
*error = "unterminated indexed parameter expression";
|
||||
*error = "Unclosed expression";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -3491,7 +3599,7 @@ std::string expand_expressions_and_parameters(const std::string &line,
|
||||
const size_t close = line.find('>', j + 1);
|
||||
if (close == std::string::npos) {
|
||||
if (error) {
|
||||
*error = "unterminated named parameter expression";
|
||||
*error = "Named parameter not terminated";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -3653,7 +3761,7 @@ bool parse_parameter_assignment(const std::string &line,
|
||||
const size_t close = text.find('>', pos + 1);
|
||||
if (close == std::string::npos) {
|
||||
if (error) {
|
||||
*error = "unterminated named parameter assignment";
|
||||
*error = "Named parameter not terminated";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -3669,7 +3777,7 @@ bool parse_parameter_assignment(const std::string &line,
|
||||
const size_t close = find_matching_square_bracket(text, pos);
|
||||
if (close == std::string::npos) {
|
||||
if (error) {
|
||||
*error = "unterminated indexed parameter assignment";
|
||||
*error = "Unclosed expression";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -3793,7 +3901,7 @@ bool parse_parameter_assignment(const std::string &line,
|
||||
const size_t close = find_matching_square_bracket(text, pos);
|
||||
if (close == std::string::npos) {
|
||||
if (error) {
|
||||
*error = "unterminated parameter assignment expression";
|
||||
*error = "Unclosed expression";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -4994,6 +5102,119 @@ bool validate_r_arc_reaches_end_point(const CncSimEvent &event, int plane, doubl
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validate_absolute_center_arc_axis_words(const std::unordered_map<char, double> &words,
|
||||
int plane,
|
||||
bool absolute,
|
||||
std::string *error) {
|
||||
if (!absolute || words.count('R')) {
|
||||
return true;
|
||||
}
|
||||
auto missing = [error](char axis) {
|
||||
if (error) {
|
||||
*error = std::string(1, axis) + " word missing in absolute center arc";
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (plane == 17 && (words.count('I') || words.count('J'))) {
|
||||
if (!words.count('I')) {
|
||||
return missing('I');
|
||||
}
|
||||
if (!words.count('J')) {
|
||||
return missing('J');
|
||||
}
|
||||
} else if (plane == 18 && (words.count('I') || words.count('K'))) {
|
||||
if (!words.count('I')) {
|
||||
return missing('I');
|
||||
}
|
||||
if (!words.count('K')) {
|
||||
return missing('K');
|
||||
}
|
||||
} else if (plane == 19 && (words.count('J') || words.count('K'))) {
|
||||
if (!words.count('J')) {
|
||||
return missing('J');
|
||||
}
|
||||
if (!words.count('K')) {
|
||||
return missing('K');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validate_arc_format_words(const std::unordered_map<char, double> &words, std::string *error) {
|
||||
const bool has_r = words.count('R') != 0;
|
||||
const bool has_ijk = words.count('I') || words.count('J') || words.count('K');
|
||||
if (has_r && has_ijk) {
|
||||
if (error) {
|
||||
*error = "Mixed radius ijk format for arc";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!has_r && !has_ijk) {
|
||||
if (error) {
|
||||
*error = "R i j k words all missing for arc";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validate_arc_plane_center_words(const std::unordered_map<char, double> &words,
|
||||
int plane,
|
||||
std::string *error) {
|
||||
if (plane == 17 && words.count('K')) {
|
||||
if (error) {
|
||||
*error = "K word given for arc in xy plane";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (plane == 18 && words.count('J')) {
|
||||
if (error) {
|
||||
*error = "J word given for arc in xz plane";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (plane == 19 && words.count('I')) {
|
||||
if (error) {
|
||||
*error = "I word given for arc in yz plane";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validate_r_arc_endpoint_words(const std::unordered_map<char, double> &words,
|
||||
const ParsedWordList &parsed,
|
||||
int plane,
|
||||
std::string *error) {
|
||||
if (!words.count('R')) {
|
||||
return true;
|
||||
}
|
||||
if (plane == 17) {
|
||||
if (!words.count('X') && !words.count('Y') &&
|
||||
!parsed.radius_flag && !parsed.theta_flag) {
|
||||
if (error) {
|
||||
*error = "X and y words missing for arc in xy plane";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else if (plane == 18) {
|
||||
if (!words.count('X') && !words.count('Z')) {
|
||||
if (error) {
|
||||
*error = "X and z words missing for arc in xz plane";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else if (plane == 19) {
|
||||
if (!words.count('Y') && !words.count('Z')) {
|
||||
if (error) {
|
||||
*error = "Y and z words missing for arc in yz plane";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool modal_motion_is_threading(int modal_motion) {
|
||||
return modal_motion == kModalMotionG33 ||
|
||||
modal_motion == kModalMotionG331;
|
||||
@@ -5101,7 +5322,7 @@ void emit_tool_length_offset(CanonEventSink &sink, const CncSimPose &offset, int
|
||||
event.version = 1;
|
||||
event.type = CNC_SIM_EVENT_COMMENT;
|
||||
event.line = line;
|
||||
event.reserved = 430;
|
||||
event.reserved = kToolLengthOffsetEvent;
|
||||
event.start = offset;
|
||||
sink.emit_raw(event);
|
||||
}
|
||||
@@ -5645,6 +5866,13 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
}
|
||||
|
||||
refresh_readonly_named_parameters(line_number);
|
||||
if (cutter_comp_on_ &&
|
||||
line_reads_current_position_parameter(line, call_stack, parameters, named_parameters)) {
|
||||
if (error) {
|
||||
*error = "Cannot read current position with cutter radius compensation on";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
std::string parameter_error;
|
||||
std::vector<PendingParameterAssignment> pending_assignments;
|
||||
if (!extract_parameter_assignments(line,
|
||||
@@ -5726,7 +5954,7 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
}
|
||||
std::vector<SimulatorGcodeControlAction> simulator_control_actions;
|
||||
if (!has_keyword_oword &&
|
||||
parse_simulator_gcode_control_line(line, &simulator_control_actions)) {
|
||||
parse_simulator_gcode_control_line(line, sink_.block_delete(), &simulator_control_actions)) {
|
||||
bool simulator_only_line = true;
|
||||
for (const auto &action : simulator_control_actions) {
|
||||
emit_simulator_gcode_control_action(sink_, action, line_number);
|
||||
@@ -6578,7 +6806,8 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
if (l == 0) {
|
||||
if (spindle_tool_id_ > 0) {
|
||||
if (error) {
|
||||
*error = "G10 L0 not allowed with loaded tool";
|
||||
*error = "G10 L0 not allowed with loaded tool <" +
|
||||
std::to_string(spindle_tool_id_) + ">";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -6761,21 +6990,30 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
if (explicit_comp) {
|
||||
if (!words.count('D')) {
|
||||
if (error) {
|
||||
*error = "G41.1/G42.1 requires a D word";
|
||||
*error = std::string(cutter_comp_left ? "G41.1" : "G42.1") +
|
||||
" with no D word";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (words.count('L') && sink_.plane() != 18) {
|
||||
if (error) {
|
||||
*error = "G41.1/G42.1 with L word requires G18";
|
||||
*error = std::string(cutter_comp_left ? "G41.1" : "G42.1") +
|
||||
" with L word, but plane is not G18";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
} else if (words.count('D')) {
|
||||
const double d_value = words.at('D');
|
||||
if (std::fabs(d_value - std::round(d_value)) > 0.0001 || d_value < 0.0) {
|
||||
if (std::fabs(d_value - std::round(d_value)) > 0.0001) {
|
||||
if (error) {
|
||||
*error = "G41/G42 requires a non-negative whole-number D word";
|
||||
*error = std::string(cutter_comp_left ? "G41" : "G42") +
|
||||
" requires D word to be a whole number";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (d_value < 0.0) {
|
||||
if (error) {
|
||||
*error = "Negative d word tool radius index used";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -7626,6 +7864,16 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
break;
|
||||
}
|
||||
const int spindle = selected_spindle;
|
||||
if ((m == 3 || m == 4 || m == 5) &&
|
||||
parsed_word_list.dollar_flag &&
|
||||
!smoke_spindle_selector_valid_for_speed(parsed_word_list.dollar_value)) {
|
||||
if (error) {
|
||||
*error = "Spindle ($) number out of range in M" + std::to_string(m) +
|
||||
" Command\nnum_spindles =" + std::to_string(kSmokeNumSpindles) +
|
||||
". $=" + std::to_string(rounded_value(parsed_word_list.dollar_value)) + "\n";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (m == 3) {
|
||||
sink_.start_spindle(spindle, 1, line_number);
|
||||
if (stop_if_callback_aborted(sink_, error)) {
|
||||
@@ -7944,17 +8192,17 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
return -1;
|
||||
}
|
||||
} else if (m == 428) {
|
||||
sink_.switch_kinematics(1, true, line_number);
|
||||
sink_.switch_kinematics(1, line_number);
|
||||
if (stop_if_callback_aborted(sink_, error)) {
|
||||
return -1;
|
||||
}
|
||||
} else if (m == 429) {
|
||||
sink_.switch_kinematics(0, false, line_number);
|
||||
sink_.switch_kinematics(0, line_number);
|
||||
if (stop_if_callback_aborted(sink_, error)) {
|
||||
return -1;
|
||||
}
|
||||
} else if (m == 430) {
|
||||
sink_.switch_kinematics(2, true, line_number);
|
||||
sink_.switch_kinematics(2, line_number);
|
||||
if (stop_if_callback_aborted(sink_, error)) {
|
||||
return -1;
|
||||
}
|
||||
@@ -8077,8 +8325,15 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
const bool arc_center_or_radius_words =
|
||||
(modal_motion == 2 || modal_motion == 3) &&
|
||||
(words.count('I') || words.count('J') || words.count('K') ||
|
||||
(words.count('R') && !has_m_code(word_list, 19)));
|
||||
const bool current_line_requests_motion =
|
||||
has_axis_words || parsed_word_list.radius_flag || parsed_word_list.theta_flag;
|
||||
has_axis_words ||
|
||||
parsed_word_list.radius_flag ||
|
||||
parsed_word_list.theta_flag ||
|
||||
arc_center_or_radius_words;
|
||||
const bool explicit_threading_motion =
|
||||
has_g_code(word_list, 33.0) || has_g_code(word_list, 33.1) || has_g_code(word_list, 76.0);
|
||||
if ((current_line_requests_motion || explicit_threading_motion) && !has_axis_words &&
|
||||
@@ -8723,11 +8978,23 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (!validate_arc_format_words(words, error)) {
|
||||
return -1;
|
||||
}
|
||||
if (!validate_arc_plane_center_words(words, sink_.plane(), error)) {
|
||||
return -1;
|
||||
}
|
||||
if (!validate_r_arc_endpoint_words(words, parsed_word_list, sink_.plane(), error)) {
|
||||
return -1;
|
||||
}
|
||||
event.arc_turns = modal_motion == 2 ? -1 : 1;
|
||||
if (words.count('R') &&
|
||||
!validate_r_arc_reaches_end_point(event, sink_.plane(), words.at('R') * sink_.unit_scale(), error)) {
|
||||
return -1;
|
||||
}
|
||||
if (!validate_absolute_center_arc_axis_words(words, sink_.plane(), arc_absolute_, error)) {
|
||||
return -1;
|
||||
}
|
||||
set_arc_center(&event, words, sink_.plane(), sink_.unit_scale(), arc_absolute_);
|
||||
if (!words.count('R') &&
|
||||
!validate_arc_center_radius_consistency(event, sink_.plane(), sink_.unit_scale(), error)) {
|
||||
@@ -8964,7 +9231,7 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
||||
if (stop_if_callback_aborted(sink_, error)) {
|
||||
return -1;
|
||||
}
|
||||
emit_comment_state(sink_, line_number, 970);
|
||||
emit_comment_state(sink_, line_number, kConstantRpmSpindleModeEvent);
|
||||
if (stop_if_callback_aborted(sink_, error)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "canon_event_sink.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
@@ -25,6 +26,18 @@ bool expect(bool value, const char *message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool near(double actual, double expected) {
|
||||
return std::fabs(actual - expected) < 1e-9;
|
||||
}
|
||||
|
||||
bool expect_near(double actual, double expected, const char *message) {
|
||||
if (!near(actual, expected)) {
|
||||
std::cerr << "FAIL: " << message << " actual=" << actual << " expected=" << expected << '\n';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
@@ -32,6 +45,8 @@ int main() {
|
||||
std::vector<CncSimEvent> events;
|
||||
CanonEventSink sink;
|
||||
sink.set_callback(collect_event, &events);
|
||||
ok &= expect(sink.kinematics_type() == 0,
|
||||
"expected LinuxCNC xyzbc-trt identityfirst startup kinematics type 0");
|
||||
|
||||
CncSimPose end{};
|
||||
end.x = 10.0;
|
||||
@@ -49,6 +64,8 @@ int main() {
|
||||
|
||||
int abort_count = 0;
|
||||
sink.reset();
|
||||
ok &= expect(sink.kinematics_type() == 0,
|
||||
"expected LinuxCNC xyzbc-trt identityfirst reset kinematics type 0");
|
||||
sink.set_callback(abort_on_second_event, &abort_count);
|
||||
sink.select_plane(17, 1);
|
||||
sink.set_feed_rate(100.0, 2);
|
||||
@@ -56,6 +73,251 @@ int main() {
|
||||
ok &= expect(sink.callback_aborted(), "expected callback abort state");
|
||||
ok &= expect(abort_count == 2, "expected no further callbacks after abort");
|
||||
|
||||
events.clear();
|
||||
sink.reset();
|
||||
sink.set_callback(collect_event, &events);
|
||||
sink.configure_rtcp(false, 250.0);
|
||||
sink.switch_kinematics(2, 1);
|
||||
CncSimPose five_axis_end{};
|
||||
five_axis_end.x = 260.0;
|
||||
five_axis_end.y = 20.0;
|
||||
five_axis_end.z = 280.0;
|
||||
five_axis_end.b = 90.0;
|
||||
five_axis_end.c = 45.0;
|
||||
five_axis_end.w = 12.0;
|
||||
sink.straight_feed(2, five_axis_end);
|
||||
bool saw_userk_before_g434 = false;
|
||||
for (const auto &event : events) {
|
||||
saw_userk_before_g434 = saw_userk_before_g434 || event.type == CNC_SIM_EVENT_RTCP_PIVOT;
|
||||
}
|
||||
ok &= expect(!saw_userk_before_g434, "expected M430 not to enable RTCP without G43.4/G43.5");
|
||||
|
||||
events.clear();
|
||||
sink.set_rtcp_state(true, 0, 2);
|
||||
sink.straight_feed(3, five_axis_end);
|
||||
bool saw_userk_pivot = false;
|
||||
for (const auto &event : events) {
|
||||
saw_userk_pivot = saw_userk_pivot ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 2 &&
|
||||
near(event.dwell_seconds, 250.0) &&
|
||||
near(event.end.x, 260.0) &&
|
||||
near(event.end.y, 20.0) &&
|
||||
near(event.end.z, 280.0) &&
|
||||
near(event.end.b, 90.0) &&
|
||||
near(event.end.c, 45.0) &&
|
||||
near(event.end.w, 0.0));
|
||||
}
|
||||
ok &= expect(saw_userk_pivot, "expected M430-style RTCP pivot to use LinuxCNC userk identity inverse");
|
||||
|
||||
events.clear();
|
||||
sink.configure_rtcp(true, 0.0);
|
||||
sink.switch_kinematics(2, 3);
|
||||
bool saw_userk_remap_m68 = false;
|
||||
bool saw_userk_remap_m66 = false;
|
||||
bool saw_userk_switch_rtcp_feed = false;
|
||||
for (const auto &event : events) {
|
||||
saw_userk_remap_m68 = saw_userk_remap_m68 ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 68 &&
|
||||
event.tool == 3 &&
|
||||
near(event.feed, 2.0));
|
||||
saw_userk_remap_m66 = saw_userk_remap_m66 ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 66 &&
|
||||
event.tool == 0 &&
|
||||
near(event.feed, 0.0) &&
|
||||
near(event.dwell_seconds, 0.0));
|
||||
saw_userk_switch_rtcp_feed = saw_userk_switch_rtcp_feed ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 2 &&
|
||||
near(event.feed, 1.0));
|
||||
}
|
||||
ok &= expect(saw_userk_remap_m68, "expected M430 remap to emit LinuxCNC M68 E3 Q2 side effect");
|
||||
ok &= expect(saw_userk_remap_m66, "expected M430 remap to emit LinuxCNC M66 E0 L0 side effect");
|
||||
ok &= expect(!saw_userk_switch_rtcp_feed,
|
||||
"expected kinematics switch event not to carry RTCP state");
|
||||
|
||||
events.clear();
|
||||
CncSimPose zero_tool_end{};
|
||||
zero_tool_end.x = 7.0;
|
||||
zero_tool_end.y = 8.0;
|
||||
zero_tool_end.z = 9.0;
|
||||
zero_tool_end.b = 10.0;
|
||||
zero_tool_end.c = 11.0;
|
||||
sink.straight_feed(4, zero_tool_end);
|
||||
bool saw_zero_tool_userk_pivot = false;
|
||||
for (const auto &event : events) {
|
||||
saw_zero_tool_userk_pivot = saw_zero_tool_userk_pivot ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||
event.line == 4 &&
|
||||
event.reserved == 2 &&
|
||||
near(event.dwell_seconds, 0.0) &&
|
||||
near(event.end.x, 7.0) &&
|
||||
near(event.end.y, 8.0) &&
|
||||
near(event.end.z, 9.0) &&
|
||||
near(event.end.b, 10.0) &&
|
||||
near(event.end.c, 11.0));
|
||||
}
|
||||
ok &= expect(saw_zero_tool_userk_pivot, "expected M430 userk inverse to run with zero tool offset");
|
||||
|
||||
events.clear();
|
||||
sink.configure_rtcp(false, 250.0);
|
||||
sink.switch_kinematics(1, 3);
|
||||
CncSimPose trt_end{};
|
||||
trt_end.x = 225.0;
|
||||
trt_end.y = 20.0;
|
||||
trt_end.z = -205.0;
|
||||
trt_end.b = 90.0;
|
||||
sink.straight_feed(4, trt_end);
|
||||
bool saw_trt_before_g434 = false;
|
||||
for (const auto &event : events) {
|
||||
saw_trt_before_g434 = saw_trt_before_g434 || event.type == CNC_SIM_EVENT_RTCP_PIVOT;
|
||||
}
|
||||
ok &= expect(!saw_trt_before_g434, "expected M428 not to enable RTCP without G43.4/G43.5");
|
||||
|
||||
events.clear();
|
||||
sink.set_rtcp_state(true, 0, 4);
|
||||
sink.straight_feed(5, trt_end);
|
||||
bool saw_xyzbc_trt_pivot = false;
|
||||
for (const auto &event : events) {
|
||||
saw_xyzbc_trt_pivot = saw_xyzbc_trt_pivot ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||
event.line == 5 &&
|
||||
event.reserved == 1 &&
|
||||
near(event.dwell_seconds, 250.0) &&
|
||||
near(event.end.x, 10.0) &&
|
||||
near(event.end.y, 20.0) &&
|
||||
near(event.end.z, 30.0) &&
|
||||
near(event.end.b, 90.0));
|
||||
}
|
||||
ok &= expect(saw_xyzbc_trt_pivot, "expected M428-style RTCP pivot to use LinuxCNC xyzbc-trt inverse");
|
||||
|
||||
events.clear();
|
||||
LinuxCncXyzbcTrtParameters trt_parameters = linuxcnc_xyzbc_trt_default_parameters(0.0);
|
||||
trt_parameters.x_rot_point = 3.0;
|
||||
trt_parameters.y_rot_point = -4.0;
|
||||
trt_parameters.z_rot_point = 5.0;
|
||||
trt_parameters.x_offset = 2.0;
|
||||
trt_parameters.z_offset = 7.0;
|
||||
trt_parameters.conventional_directions = true;
|
||||
sink.configure_rtcp(false, 11.0);
|
||||
sink.configure_xyzbc_trt(trt_parameters);
|
||||
sink.switch_kinematics(1, 5);
|
||||
sink.set_rtcp_state(true, 0, 5);
|
||||
CncSimPose configured_trt_end{};
|
||||
configured_trt_end.x = 30.0;
|
||||
configured_trt_end.y = 40.0;
|
||||
configured_trt_end.z = 50.0;
|
||||
configured_trt_end.b = 20.0;
|
||||
configured_trt_end.c = -30.0;
|
||||
sink.straight_feed(6, configured_trt_end);
|
||||
LinuxCncXyzbcTrtParameters expected_trt_parameters = trt_parameters;
|
||||
expected_trt_parameters.tool_offset = 11.0;
|
||||
const LinuxCncFiveAxisJoints expected_configured_trt =
|
||||
linuxcnc_xyzbc_trt_inverse(configured_trt_end, expected_trt_parameters);
|
||||
bool saw_configured_trt_pivot = false;
|
||||
for (const auto &event : events) {
|
||||
saw_configured_trt_pivot = saw_configured_trt_pivot ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||
event.line == 6 &&
|
||||
event.reserved == 1 &&
|
||||
near(event.dwell_seconds, 11.0) &&
|
||||
near(event.end.x, expected_configured_trt.x) &&
|
||||
near(event.end.y, expected_configured_trt.y) &&
|
||||
near(event.end.z, expected_configured_trt.z) &&
|
||||
near(event.end.b, expected_configured_trt.b) &&
|
||||
near(event.end.c, expected_configured_trt.c));
|
||||
}
|
||||
ok &= expect(saw_configured_trt_pivot, "expected M428 xyzbc-trt inverse to use configured HAL-style pins");
|
||||
|
||||
events.clear();
|
||||
LinuxCncXyzbcTrtParameters xyzac_parameters = linuxcnc_xyzbc_trt_default_parameters(0.0);
|
||||
xyzac_parameters.y_offset = 20.0;
|
||||
xyzac_parameters.z_offset = 10.0;
|
||||
sink.configure_rtcp(false, 7.0);
|
||||
sink.configure_xyzac_trt(xyzac_parameters);
|
||||
sink.switch_kinematics(1, 6);
|
||||
sink.set_rtcp_state(true, 0, 6);
|
||||
CncSimPose xyzac_end{};
|
||||
xyzac_end.x = 12.0;
|
||||
xyzac_end.y = -8.0;
|
||||
xyzac_end.z = 42.0;
|
||||
xyzac_end.a = 35.0;
|
||||
xyzac_end.c = -25.0;
|
||||
sink.straight_feed(7, xyzac_end);
|
||||
LinuxCncXyzbcTrtParameters expected_xyzac_parameters = xyzac_parameters;
|
||||
expected_xyzac_parameters.tool_offset = 7.0;
|
||||
const LinuxCncFiveAxisJoints expected_xyzac =
|
||||
linuxcnc_xyzac_trt_inverse(xyzac_end, expected_xyzac_parameters);
|
||||
bool saw_xyzac_trt_pivot = false;
|
||||
for (const auto &event : events) {
|
||||
saw_xyzac_trt_pivot = saw_xyzac_trt_pivot ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||
event.line == 7 &&
|
||||
event.reserved == 1 &&
|
||||
near(event.dwell_seconds, 7.0) &&
|
||||
near(event.end.x, expected_xyzac.x) &&
|
||||
near(event.end.y, expected_xyzac.y) &&
|
||||
near(event.end.z, expected_xyzac.z) &&
|
||||
near(event.end.a, expected_xyzac.a) &&
|
||||
near(event.end.c, expected_xyzac.c));
|
||||
}
|
||||
ok &= expect(saw_xyzac_trt_pivot, "expected M428 xyzac-trt inverse to use LinuxCNC xyzacKinematicsInverse");
|
||||
|
||||
std::vector<CncSimEvent> fiveaxis_events;
|
||||
CanonEventSink fiveaxis_sink;
|
||||
fiveaxis_sink.set_callback(collect_event, &fiveaxis_events);
|
||||
fiveaxis_sink.configure_rtcp(true, 250.0);
|
||||
fiveaxis_sink.configure_fiveaxis(250.0, 0);
|
||||
fiveaxis_sink.switch_m_code_kinematics(428, 1, 8);
|
||||
CncSimPose bridgemill_end{};
|
||||
bridgemill_end.x = 260.0;
|
||||
bridgemill_end.y = 20.0;
|
||||
bridgemill_end.z = 280.0;
|
||||
bridgemill_end.b = 90.0;
|
||||
bridgemill_end.c = 0.0;
|
||||
fiveaxis_sink.straight_feed(9, bridgemill_end);
|
||||
bool saw_fiveaxis_pivot = false;
|
||||
for (const auto &event : fiveaxis_events) {
|
||||
saw_fiveaxis_pivot = saw_fiveaxis_pivot ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||
event.line == 9 &&
|
||||
event.reserved == 0 &&
|
||||
near(event.dwell_seconds, 250.0) &&
|
||||
near(event.end.x, 10.0) &&
|
||||
near(event.end.y, 20.0) &&
|
||||
near(event.end.z, 30.0) &&
|
||||
near(event.end.b, 90.0) &&
|
||||
near(event.end.c, 0.0));
|
||||
}
|
||||
ok &= expect(saw_fiveaxis_pivot, "expected M428 bridgemill RTCP pivot to use LinuxCNC 5axiskins inverse");
|
||||
|
||||
events.clear();
|
||||
sink.configure_rtcp(true, 250.0);
|
||||
sink.switch_kinematics(0, 3);
|
||||
five_axis_end.x = 300.0;
|
||||
sink.straight_feed(4, five_axis_end);
|
||||
bool saw_disabled_pivot = false;
|
||||
for (const auto &event : events) {
|
||||
saw_disabled_pivot = saw_disabled_pivot || event.type == CNC_SIM_EVENT_RTCP_PIVOT;
|
||||
}
|
||||
ok &= expect(!saw_disabled_pivot, "expected M429-style kinematics switch to disable RTCP pivot events");
|
||||
|
||||
events.clear();
|
||||
sink.configure_rtcp(true, 250.0);
|
||||
sink.switch_kinematics(3, 5);
|
||||
sink.straight_feed(6, five_axis_end);
|
||||
bool saw_unknown_switchkins_pivot = false;
|
||||
for (const auto &event : events) {
|
||||
saw_unknown_switchkins_pivot = saw_unknown_switchkins_pivot || event.type == CNC_SIM_EVENT_RTCP_PIVOT;
|
||||
}
|
||||
ok &= expect(!saw_unknown_switchkins_pivot,
|
||||
"expected unsupported switchkins type to avoid generic RTCP fallback");
|
||||
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kToolLengthOffsetEvent = 430;
|
||||
constexpr int kCssSpindleModeEvent = 960;
|
||||
constexpr int kConstantRpmSpindleModeEvent = 970;
|
||||
|
||||
int collect_event(const CncSimEvent *event, void *user_data) {
|
||||
auto *events = static_cast<std::vector<CncSimEvent> *>(user_data);
|
||||
events->push_back(*event);
|
||||
@@ -54,6 +58,34 @@ bool saw_comment_state(const std::vector<CncSimEvent> &events,
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
{
|
||||
std::vector<CncSimEvent> default_events;
|
||||
CncSimHandle *default_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(default_sim, collect_event, &default_events);
|
||||
const char default_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G0 X1\n"
|
||||
"M30\n";
|
||||
bool default_ok = true;
|
||||
default_ok &= expect(cnc_sim_parse_program(default_sim,
|
||||
default_program,
|
||||
sizeof(default_program) - 1) == 0,
|
||||
cnc_sim_last_error(default_sim));
|
||||
bool saw_default_linuxcnc_rapid = false;
|
||||
for (const auto &event : default_events) {
|
||||
saw_default_linuxcnc_rapid = saw_default_linuxcnc_rapid ||
|
||||
(event.type == CNC_SIM_EVENT_RAPID &&
|
||||
event.line == 2 &&
|
||||
near(event.end.x, 1.0));
|
||||
}
|
||||
default_ok &= expect(saw_default_linuxcnc_rapid,
|
||||
"expected compiled API default backend to use LinuxCNC rs274");
|
||||
cnc_sim_destroy(default_sim);
|
||||
if (!default_ok) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
const char config[] =
|
||||
"{\"backend\":\"linuxcnc-rs274\",\"rtcp\":{\"enabled\":true,\"toolLength\":100,\"toolLengths\":{\"7\":125}}}";
|
||||
const char program[] =
|
||||
@@ -62,6 +94,7 @@ int main() {
|
||||
"M428 M429 M430\n"
|
||||
"G49\n"
|
||||
"G43.4 H7\n"
|
||||
"G43.5 H7\n"
|
||||
"S8000 M3\n"
|
||||
"G0 X0 Y0 Z5\n"
|
||||
"F600\n"
|
||||
@@ -91,6 +124,7 @@ int main() {
|
||||
bool saw_m430 = false;
|
||||
bool saw_g49 = false;
|
||||
bool saw_g434 = false;
|
||||
bool saw_g435 = false;
|
||||
bool saw_g5x_offset = false;
|
||||
bool saw_xy_rotation = false;
|
||||
bool saw_g92_clear = false;
|
||||
@@ -180,22 +214,20 @@ int main() {
|
||||
saw_end = saw_end || event.type == CNC_SIM_EVENT_PROGRAM_END;
|
||||
saw_rtcp = saw_rtcp ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||
event.end.z == 130.0);
|
||||
event.reserved == 2 &&
|
||||
event.end.z == 5.0);
|
||||
saw_m428 = saw_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 1 &&
|
||||
event.feed == 1.0);
|
||||
event.reserved == 1);
|
||||
saw_m429 = saw_m429 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 0 &&
|
||||
event.feed == 0.0);
|
||||
event.reserved == 0);
|
||||
saw_m430 = saw_m430 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 2 &&
|
||||
event.feed == 1.0);
|
||||
event.reserved == 2);
|
||||
saw_g49 = saw_g49 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 4 &&
|
||||
@@ -206,6 +238,12 @@ int main() {
|
||||
event.feed == 1.0 &&
|
||||
event.tool == 7 &&
|
||||
event.dwell_seconds == 125.0);
|
||||
saw_g435 = saw_g435 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 6 &&
|
||||
event.feed == 1.0 &&
|
||||
event.tool == 7 &&
|
||||
event.dwell_seconds == 125.0);
|
||||
}
|
||||
|
||||
ok &= expect(saw_tool, "expected LinuxCNC tool-change event");
|
||||
@@ -217,8 +255,17 @@ int main() {
|
||||
ok &= expect(saw_m428, "expected LinuxCNC M428 kinematics switch");
|
||||
ok &= expect(saw_m429, "expected LinuxCNC M429 kinematics switch");
|
||||
ok &= expect(saw_m430, "expected LinuxCNC M430 kinematics switch");
|
||||
ok &= expect(saw_comment_state(events, 3, 68, 3, 1.0),
|
||||
"expected LinuxCNC M428 remap M68 E3 Q1 side effect");
|
||||
ok &= expect(saw_comment_state(events, 3, 68, 3, 0.0),
|
||||
"expected LinuxCNC M429 remap M68 E3 Q0 side effect");
|
||||
ok &= expect(saw_comment_state(events, 3, 68, 3, 2.0),
|
||||
"expected LinuxCNC M430 remap M68 E3 Q2 side effect");
|
||||
ok &= expect(saw_comment_state(events, 3, 66, 0, 0.0),
|
||||
"expected LinuxCNC M428/M429/M430 remap M66 E0 L0 side effect");
|
||||
ok &= expect(saw_g49, "expected LinuxCNC G49 RTCP off state");
|
||||
ok &= expect(saw_g434, "expected LinuxCNC G43.4 RTCP on state with H code");
|
||||
ok &= expect(saw_g435, "expected LinuxCNC G43.5 RTCP on state with H code");
|
||||
|
||||
const char arc_planes_program[] =
|
||||
"G21 G90 G17\n"
|
||||
@@ -416,25 +463,25 @@ int main() {
|
||||
saw_g431_tool_length = saw_g431_tool_length ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 430 &&
|
||||
event.reserved == kToolLengthOffsetEvent &&
|
||||
event.start.x == 1.0 &&
|
||||
event.start.z == 2.0);
|
||||
saw_g432_tool_length = saw_g432_tool_length ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 430 &&
|
||||
event.reserved == kToolLengthOffsetEvent &&
|
||||
event.start.x == 1.25 &&
|
||||
event.start.z == 2.5);
|
||||
saw_g49_dynamic_tool_length_clear = saw_g49_dynamic_tool_length_clear ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 5 &&
|
||||
event.reserved == 430 &&
|
||||
event.reserved == kToolLengthOffsetEvent &&
|
||||
event.start.x == 0.0 &&
|
||||
event.start.z == 0.0);
|
||||
saw_g432_h_tool_length = saw_g432_h_tool_length ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 4 &&
|
||||
event.reserved == 430 &&
|
||||
event.reserved == kToolLengthOffsetEvent &&
|
||||
event.start.x == 1.25 &&
|
||||
event.start.z == 15.0);
|
||||
}
|
||||
@@ -517,12 +564,12 @@ int main() {
|
||||
saw_g97_mode = saw_g97_mode ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 970 &&
|
||||
event.reserved == kConstantRpmSpindleModeEvent &&
|
||||
event.feed == 0.0);
|
||||
saw_g96_mode = saw_g96_mode ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 960 &&
|
||||
event.reserved == kCssSpindleModeEvent &&
|
||||
event.feed == 2500.0);
|
||||
}
|
||||
ok &= expect(saw_g97_mode, "expected LinuxCNC G97 constant-RPM spindle mode state");
|
||||
@@ -903,12 +950,12 @@ int main() {
|
||||
saw_tool_length = saw_tool_length ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 430 &&
|
||||
event.reserved == kToolLengthOffsetEvent &&
|
||||
near(event.start.z, 12.5));
|
||||
saw_tool_length_clear = saw_tool_length_clear ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 430 &&
|
||||
event.reserved == kToolLengthOffsetEvent &&
|
||||
event.start.z == 0.0);
|
||||
}
|
||||
ok &= expect(saw_tool_length, "expected LinuxCNC G43 H1 tool length event");
|
||||
@@ -1272,6 +1319,157 @@ int main() {
|
||||
}
|
||||
ok &= expect(saw_block_delete_disabled_line, "expected LinuxCNC disabled block-delete line to execute");
|
||||
|
||||
const char block_delete_rtcp_controls_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"/N10 M428\n"
|
||||
"/N20 G43.4 H7\n"
|
||||
"M30\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_load_config_json(sim, block_delete_on_config, sizeof(block_delete_on_config) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
block_delete_rtcp_controls_program,
|
||||
sizeof(block_delete_rtcp_controls_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_block_delete_skipped_m428 = false;
|
||||
bool saw_block_delete_skipped_g434 = false;
|
||||
for (const auto &event : events) {
|
||||
saw_block_delete_skipped_m428 = saw_block_delete_skipped_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2);
|
||||
saw_block_delete_skipped_g434 = saw_block_delete_skipped_g434 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 3);
|
||||
}
|
||||
ok &= expect(!saw_block_delete_skipped_m428, "expected LinuxCNC block-delete M428 line to be skipped");
|
||||
ok &= expect(!saw_block_delete_skipped_g434, "expected LinuxCNC block-delete G43.4 line to be skipped");
|
||||
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_load_config_json(sim, block_delete_off_config, sizeof(block_delete_off_config) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
block_delete_rtcp_controls_program,
|
||||
sizeof(block_delete_rtcp_controls_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_block_delete_disabled_m428 = false;
|
||||
bool saw_block_delete_disabled_g434 = false;
|
||||
for (const auto &event : events) {
|
||||
saw_block_delete_disabled_m428 = saw_block_delete_disabled_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 1);
|
||||
saw_block_delete_disabled_g434 = saw_block_delete_disabled_g434 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 3 &&
|
||||
event.tool == 7);
|
||||
}
|
||||
ok &= expect(saw_block_delete_disabled_m428, "expected LinuxCNC disabled block-delete M428 to execute");
|
||||
ok &= expect(saw_block_delete_disabled_g434, "expected LinuxCNC disabled block-delete G43.4 to execute");
|
||||
|
||||
const char unary_sign_rtcp_controls_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"M++428\n"
|
||||
"G+43.4 H++7\n"
|
||||
"M30\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_load_config_json(sim, config, sizeof(config) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
unary_sign_rtcp_controls_program,
|
||||
sizeof(unary_sign_rtcp_controls_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_unary_sign_m428 = false;
|
||||
bool saw_unary_sign_g434 = false;
|
||||
for (const auto &event : events) {
|
||||
saw_unary_sign_m428 = saw_unary_sign_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 1);
|
||||
saw_unary_sign_g434 = saw_unary_sign_g434 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 3 &&
|
||||
event.tool == 7);
|
||||
}
|
||||
ok &= expect(saw_unary_sign_m428, "expected LinuxCNC source M++428 to execute as M428");
|
||||
ok &= expect(saw_unary_sign_g434, "expected LinuxCNC source G+43.4 H++7 to execute as G43.4 H7");
|
||||
|
||||
const char numbered_rtcp_controls_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"N10 M428\n"
|
||||
"N20 G43.4 H7\n"
|
||||
"M30\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
numbered_rtcp_controls_program,
|
||||
sizeof(numbered_rtcp_controls_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_numbered_m428 = false;
|
||||
bool saw_numbered_g434 = false;
|
||||
for (const auto &event : events) {
|
||||
saw_numbered_m428 = saw_numbered_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 1);
|
||||
saw_numbered_g434 = saw_numbered_g434 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 3 &&
|
||||
event.tool == 7);
|
||||
}
|
||||
ok &= expect(saw_numbered_m428, "expected LinuxCNC source N10 M428 to execute as M428");
|
||||
ok &= expect(saw_numbered_g434, "expected LinuxCNC source N20 G43.4 H7 to execute as G43.4 H7");
|
||||
|
||||
const char bracket_rtcp_controls_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"M[428]\n"
|
||||
"G[43.4] H[7]\n"
|
||||
"M30\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
bracket_rtcp_controls_program,
|
||||
sizeof(bracket_rtcp_controls_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_bracket_m428 = false;
|
||||
bool saw_bracket_g434 = false;
|
||||
for (const auto &event : events) {
|
||||
saw_bracket_m428 = saw_bracket_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 1);
|
||||
saw_bracket_g434 = saw_bracket_g434 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 3 &&
|
||||
event.tool == 7);
|
||||
}
|
||||
ok &= expect(saw_bracket_m428, "expected LinuxCNC source M[428] to execute as M428");
|
||||
ok &= expect(saw_bracket_g434, "expected LinuxCNC source G[43.4] H[7] to execute as G43.4 H7");
|
||||
|
||||
const char exponent_m428_control_program[] =
|
||||
"G21 G90\n"
|
||||
"M4.28e2\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
exponent_m428_control_program,
|
||||
sizeof(exponent_m428_control_program) - 1) != 0,
|
||||
"expected LinuxCNC source backend to reject exponent M428 control syntax");
|
||||
|
||||
const char exponent_g434_control_program[] =
|
||||
"G21 G90\n"
|
||||
"G4.34e1 H7\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
exponent_g434_control_program,
|
||||
sizeof(exponent_g434_control_program) - 1) != 0,
|
||||
"expected LinuxCNC source backend to reject exponent G43.4 control syntax");
|
||||
|
||||
const char exponent_h_control_program[] =
|
||||
"G21 G90\n"
|
||||
"G43.4 H7e0\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
exponent_h_control_program,
|
||||
sizeof(exponent_h_control_program) - 1) != 0,
|
||||
"expected LinuxCNC source backend to reject exponent H control syntax");
|
||||
|
||||
cnc_sim_destroy(sim);
|
||||
|
||||
int abort_count = 0;
|
||||
|
||||
@@ -11,6 +11,12 @@
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kToolLengthOffsetEvent = 430;
|
||||
constexpr int kCssSpindleModeEvent = 960;
|
||||
constexpr int kConstantRpmSpindleModeEvent = 970;
|
||||
constexpr int kCutterCompOffEvent = 400;
|
||||
constexpr int kCutterCompLeftExplicitEvent = 411;
|
||||
|
||||
int collect_event(const CncSimEvent *event, void *user_data) {
|
||||
auto *events = static_cast<std::vector<CncSimEvent> *>(user_data);
|
||||
events->push_back(*event);
|
||||
@@ -114,6 +120,7 @@ int main() {
|
||||
"M428 M429 M430\n"
|
||||
"G49\n"
|
||||
"G43.4 H7\n"
|
||||
"G43.5 H7\n"
|
||||
"S8000 M3\n"
|
||||
"G0 X0 Y0 Z5\n"
|
||||
"F600\n"
|
||||
@@ -154,6 +161,7 @@ int main() {
|
||||
bool saw_m430 = false;
|
||||
bool saw_g49 = false;
|
||||
bool saw_g434 = false;
|
||||
bool saw_g435 = false;
|
||||
bool saw_spindle_cw = false;
|
||||
bool saw_spindle_orient = false;
|
||||
bool saw_spindle_orient_wait = false;
|
||||
@@ -379,23 +387,21 @@ int main() {
|
||||
saw_plane = saw_plane || event.type == CNC_SIM_EVENT_SET_PLANE;
|
||||
saw_rtcp = saw_rtcp ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||
event.line == 7 &&
|
||||
event.end.z == 130.0);
|
||||
event.line == 8 &&
|
||||
event.reserved == 2 &&
|
||||
event.end.z == 5.0);
|
||||
saw_m428 = saw_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 1 &&
|
||||
event.feed == 1.0);
|
||||
event.reserved == 1);
|
||||
saw_m429 = saw_m429 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 0 &&
|
||||
event.feed == 0.0);
|
||||
event.reserved == 0);
|
||||
saw_m430 = saw_m430 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 2 &&
|
||||
event.feed == 1.0);
|
||||
event.reserved == 2);
|
||||
saw_g49 = saw_g49 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 4 &&
|
||||
@@ -406,21 +412,27 @@ int main() {
|
||||
event.feed == 1.0 &&
|
||||
event.tool == 7 &&
|
||||
event.dwell_seconds == 125.0);
|
||||
saw_g435 = saw_g435 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 6 &&
|
||||
event.feed == 1.0 &&
|
||||
event.tool == 7 &&
|
||||
event.dwell_seconds == 125.0);
|
||||
saw_spindle_cw = saw_spindle_cw ||
|
||||
(event.type == CNC_SIM_EVENT_SET_SPINDLE &&
|
||||
event.line == 6 &&
|
||||
event.line == 7 &&
|
||||
event.spindle == 8000.0 &&
|
||||
event.reserved == 1);
|
||||
saw_spindle_orient = saw_spindle_orient ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 15 &&
|
||||
event.line == 16 &&
|
||||
event.reserved == 1901 &&
|
||||
event.tool == 0 &&
|
||||
event.feed == 45.0 &&
|
||||
event.arc_turns == 1);
|
||||
saw_spindle_orient_wait = saw_spindle_orient_wait ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 15 &&
|
||||
event.line == 16 &&
|
||||
event.reserved == 1902 &&
|
||||
event.tool == 0 &&
|
||||
event.dwell_seconds == 2.0);
|
||||
@@ -429,7 +441,7 @@ int main() {
|
||||
event.start.x == 20.0 && event.end.x == 25.0);
|
||||
saw_r_arc_center = saw_r_arc_center ||
|
||||
(event.type == CNC_SIM_EVENT_ARC_FEED &&
|
||||
event.line == 14 &&
|
||||
event.line == 15 &&
|
||||
(event.center.x != event.start.x || event.center.y != event.start.y));
|
||||
}
|
||||
ok &= expect(saw_rapid, "expected rapid event");
|
||||
@@ -442,15 +454,97 @@ int main() {
|
||||
ok &= expect(saw_rtcp, "expected RTCP pivot event from config");
|
||||
ok &= expect(saw_m428, "expected M428 original kinematics switch");
|
||||
ok &= expect(saw_m429, "expected M429 identity kinematics switch");
|
||||
ok &= expect(saw_m430, "expected M430 five-axis BC kinematics switch");
|
||||
ok &= expect(saw_m430, "expected M430 userk kinematics switch");
|
||||
ok &= expect(saw_comment_state(events, 3, 68, 3, 1.0),
|
||||
"expected M428 remap M68 E3 Q1 side effect");
|
||||
ok &= expect(saw_comment_state(events, 3, 68, 3, 0.0),
|
||||
"expected M429 remap M68 E3 Q0 side effect");
|
||||
ok &= expect(saw_comment_state(events, 3, 68, 3, 2.0),
|
||||
"expected M430 remap M68 E3 Q2 side effect");
|
||||
ok &= expect(saw_comment_state(events, 3, 66, 0, 0.0),
|
||||
"expected M428/M429/M430 remap M66 E0 L0 side effect");
|
||||
ok &= expect(saw_g49, "expected G49 RTCP off state");
|
||||
ok &= expect(saw_g434, "expected G43.4 RTCP on state with H code");
|
||||
ok &= expect(saw_g435, "expected G43.5 RTCP on state with H code");
|
||||
ok &= expect(saw_spindle_cw, "expected M3 clockwise spindle state");
|
||||
ok &= expect(saw_spindle_orient, "expected M19 spindle orient state");
|
||||
ok &= expect(saw_spindle_orient_wait, "expected M19 spindle orient wait state");
|
||||
ok &= expect(saw_incremental_move, "expected G91 incremental move");
|
||||
ok &= expect(saw_r_arc_center, "expected R arc center calculation");
|
||||
|
||||
{
|
||||
std::vector<CncSimEvent> configured_events;
|
||||
CncSimHandle *configured_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(configured_sim, collect_event, &configured_events);
|
||||
const char configured_rtcp[] =
|
||||
"{\"backend\":\"smoke\",\"rtcp\":{\"enabled\":false,\"toolLength\":11},"
|
||||
"\"xyzbcTrt\":{\"xRotPoint\":3,\"yRotPoint\":-4,\"zRotPoint\":5,"
|
||||
"\"xOffset\":2,\"zOffset\":7,\"conventionalDirections\":true}}";
|
||||
const char configured_program[] =
|
||||
"M428\n"
|
||||
"G43.4\n"
|
||||
"G0 X30 Y40 Z50 B20 C-30\n";
|
||||
ok &= expect(cnc_sim_load_config_json(configured_sim,
|
||||
configured_rtcp,
|
||||
sizeof(configured_rtcp) - 1) == 0,
|
||||
cnc_sim_last_error(configured_sim));
|
||||
ok &= expect(cnc_sim_parse_program(configured_sim,
|
||||
configured_program,
|
||||
sizeof(configured_program) - 1) == 0,
|
||||
cnc_sim_last_error(configured_sim));
|
||||
bool saw_configured_rtcp = false;
|
||||
for (const auto &event : configured_events) {
|
||||
saw_configured_rtcp = saw_configured_rtcp ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||
event.reserved == 1 &&
|
||||
near(event.dwell_seconds, 11.0) &&
|
||||
near(event.end.x, -4.814629) &&
|
||||
near(event.end.y, 47.605118) &&
|
||||
near(event.end.z, 48.160567) &&
|
||||
near(event.end.b, 20.0) &&
|
||||
near(event.end.c, -30.0));
|
||||
}
|
||||
ok &= expect(saw_configured_rtcp, "expected JSON-configured xyzbc-trt pins to affect M428 inverse");
|
||||
cnc_sim_destroy(configured_sim);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<CncSimEvent> fiveaxis_events;
|
||||
CncSimHandle *fiveaxis_sim = cnc_sim_create();
|
||||
cnc_sim_set_event_callback(fiveaxis_sim, collect_event, &fiveaxis_events);
|
||||
const char fiveaxis_config[] =
|
||||
"{\"backend\":\"smoke\",\"rtcp\":{\"enabled\":true,\"toolLength\":250},"
|
||||
"\"kinematics\":\"5axiskins\",\"pivotLength\":250}";
|
||||
const char fiveaxis_program[] =
|
||||
"M428\n"
|
||||
"G0 X260 Y20 Z280 B90 C0\n";
|
||||
ok &= expect(cnc_sim_load_config_json(fiveaxis_sim,
|
||||
fiveaxis_config,
|
||||
sizeof(fiveaxis_config) - 1) == 0,
|
||||
cnc_sim_last_error(fiveaxis_sim));
|
||||
ok &= expect(cnc_sim_parse_program(fiveaxis_sim,
|
||||
fiveaxis_program,
|
||||
sizeof(fiveaxis_program) - 1) == 0,
|
||||
cnc_sim_last_error(fiveaxis_sim));
|
||||
bool saw_fiveaxis_rtcp = false;
|
||||
bool saw_fiveaxis_m428 = false;
|
||||
for (const auto &event : fiveaxis_events) {
|
||||
saw_fiveaxis_m428 = saw_fiveaxis_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.reserved == 0);
|
||||
saw_fiveaxis_rtcp = saw_fiveaxis_rtcp ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_PIVOT &&
|
||||
event.reserved == 0 &&
|
||||
near(event.end.x, 10.0) &&
|
||||
near(event.end.y, 20.0) &&
|
||||
near(event.end.z, 30.0) &&
|
||||
near(event.end.b, 90.0));
|
||||
}
|
||||
ok &= expect(saw_fiveaxis_m428, "expected LinuxCNC bridgemill M428 to select 5axiskins type 0");
|
||||
ok &= expect(saw_fiveaxis_rtcp, "expected 5axiskins inverse from LinuxCNC 5axiskins.c for M428");
|
||||
cnc_sim_destroy(fiveaxis_sim);
|
||||
}
|
||||
|
||||
const char io_controls_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"M62 P1\n"
|
||||
@@ -1282,19 +1376,19 @@ int main() {
|
||||
saw_g431_tool_length = saw_g431_tool_length ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 430 &&
|
||||
event.reserved == kToolLengthOffsetEvent &&
|
||||
event.start.x == 1.0 &&
|
||||
event.start.z == 2.0);
|
||||
saw_g432_tool_length = saw_g432_tool_length ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 430 &&
|
||||
event.reserved == kToolLengthOffsetEvent &&
|
||||
event.start.x == 1.25 &&
|
||||
event.start.z == 2.5);
|
||||
saw_g49_tool_length_clear = saw_g49_tool_length_clear ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 5 &&
|
||||
event.reserved == 430 &&
|
||||
event.reserved == kToolLengthOffsetEvent &&
|
||||
event.start.x == 0.0 &&
|
||||
event.start.z == 0.0);
|
||||
saw_g432_followup_comment = saw_g432_followup_comment ||
|
||||
@@ -1304,7 +1398,7 @@ int main() {
|
||||
saw_g432_h_tool_length = saw_g432_h_tool_length ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 4 &&
|
||||
event.reserved == 430 &&
|
||||
event.reserved == kToolLengthOffsetEvent &&
|
||||
event.start.x == 1.25 &&
|
||||
event.start.z == 15.0);
|
||||
}
|
||||
@@ -1428,12 +1522,12 @@ int main() {
|
||||
saw_g43_h_tool_length = saw_g43_h_tool_length ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 430 &&
|
||||
event.reserved == kToolLengthOffsetEvent &&
|
||||
event.start.z == 12.5);
|
||||
saw_g43_current_tool_length = saw_g43_current_tool_length ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 5 &&
|
||||
event.reserved == 430 &&
|
||||
event.reserved == kToolLengthOffsetEvent &&
|
||||
event.start.z == 0.0);
|
||||
}
|
||||
ok &= expect(saw_g43_h_tool_length, "expected smoke G43 H1 tool-table offset");
|
||||
@@ -1814,6 +1908,50 @@ int main() {
|
||||
"D word with no G41, G41.1, G42, G42.1, G71, G71.1, G71.2 G73, G83 or G96 to use it",
|
||||
"expected LinuxCNC modal-motion-D error text");
|
||||
|
||||
const char negative_cutter_comp_d_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G41 D-1\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
negative_cutter_comp_d_program,
|
||||
sizeof(negative_cutter_comp_d_program) - 1) != 0,
|
||||
"expected LinuxCNC G41 to reject a negative D tool index");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Negative d word tool radius index used",
|
||||
"expected LinuxCNC negative cutter-comp D error text");
|
||||
|
||||
const char noninteger_cutter_comp_d_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G41 D1.5\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
noninteger_cutter_comp_d_program,
|
||||
sizeof(noninteger_cutter_comp_d_program) - 1) != 0,
|
||||
"expected LinuxCNC G41 to reject a non-integer D tool index");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "G41 requires D word to be a whole number",
|
||||
"expected LinuxCNC non-integer cutter-comp D error text");
|
||||
|
||||
const char missing_explicit_cutter_comp_d_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G42.1\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
missing_explicit_cutter_comp_d_program,
|
||||
sizeof(missing_explicit_cutter_comp_d_program) - 1) != 0,
|
||||
"expected LinuxCNC G42.1 to require a D word");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "G42.1 with no D word",
|
||||
"expected LinuxCNC missing explicit cutter-comp D error text");
|
||||
|
||||
const char explicit_cutter_comp_l_wrong_plane_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G41.1 D0.25 L1\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
explicit_cutter_comp_l_wrong_plane_program,
|
||||
sizeof(explicit_cutter_comp_l_wrong_plane_program) - 1) != 0,
|
||||
"expected LinuxCNC G41.1 L word to require G18");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "G41.1 with L word, but plane is not G18",
|
||||
"expected LinuxCNC explicit cutter-comp L-plane error text");
|
||||
|
||||
const char cutter_comp_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G0 X0 Y0 Z0\n"
|
||||
@@ -1828,8 +1966,12 @@ int main() {
|
||||
bool saw_g41 = false;
|
||||
bool saw_g40 = false;
|
||||
for (const auto &event : events) {
|
||||
saw_g41 = saw_g41 || (event.type == CNC_SIM_EVENT_COMMENT && event.reserved == 411);
|
||||
saw_g40 = saw_g40 || (event.type == CNC_SIM_EVENT_COMMENT && event.reserved == 400);
|
||||
saw_g41 = saw_g41 ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.reserved == kCutterCompLeftExplicitEvent);
|
||||
saw_g40 = saw_g40 ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.reserved == kCutterCompOffEvent);
|
||||
}
|
||||
ok &= expect(saw_g41, "expected G41.1 cutter compensation state event");
|
||||
ok &= expect(saw_g40, "expected G40 cutter compensation clear event");
|
||||
@@ -2095,12 +2237,12 @@ int main() {
|
||||
saw_g97_mode = saw_g97_mode ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 970 &&
|
||||
event.reserved == kConstantRpmSpindleModeEvent &&
|
||||
event.feed == 0.0);
|
||||
saw_g96_mode = saw_g96_mode ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 960 &&
|
||||
event.reserved == kCssSpindleModeEvent &&
|
||||
event.feed == 2500.0);
|
||||
}
|
||||
ok &= expect(saw_g97_mode, "expected G97 constant-RPM spindle mode state");
|
||||
@@ -3787,6 +3929,18 @@ int main() {
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Cannot do zero repeats of cycle",
|
||||
cnc_sim_last_error(sim));
|
||||
|
||||
const char noninteger_cycle_l_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"F100\n"
|
||||
"G81 X1 Z-1 R1 L1.5\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
noninteger_cycle_l_program,
|
||||
sizeof(noninteger_cycle_l_program) - 1) != 0,
|
||||
"expected noninteger canned cycle L word to fail");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Non integer value for integer",
|
||||
cnc_sim_last_error(sim));
|
||||
|
||||
const char missing_cycle_feed_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G81 X1 Z-1 R1\n";
|
||||
@@ -3875,6 +4029,16 @@ int main() {
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Negative or zero q value used",
|
||||
cnc_sim_last_error(sim));
|
||||
|
||||
const char negative_then_positive_g83_q_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"F100\n"
|
||||
"G83 X1 Z-1 R1 Q-2 Q0.5\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
negative_then_positive_g83_q_program,
|
||||
sizeof(negative_then_positive_g83_q_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
|
||||
const char cross_cycle_q_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G73 X1 Z-1 R1 Q0.5\n"
|
||||
@@ -5904,6 +6068,86 @@ int main() {
|
||||
sizeof(readonly_numbered_parameter_assignment_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject assignment to read-only numbered parameter");
|
||||
|
||||
const char cutter_comp_read_current_position_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G41.1 D1\n"
|
||||
"#1 = #5420\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
cutter_comp_read_current_position_program,
|
||||
sizeof(cutter_comp_read_current_position_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject reading #5420 with cutter compensation on");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) ==
|
||||
"Cannot read current position with cutter radius compensation on",
|
||||
"expected LinuxCNC cutter-comp current-position read error text");
|
||||
|
||||
const char cutter_comp_read_indexed_current_position_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G41.1 D1\n"
|
||||
"#1 = #[5420]\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
cutter_comp_read_indexed_current_position_program,
|
||||
sizeof(cutter_comp_read_indexed_current_position_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject reading #[5420] with cutter compensation on");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) ==
|
||||
"Cannot read current position with cutter radius compensation on",
|
||||
"expected LinuxCNC cutter-comp indexed current-position read error text");
|
||||
|
||||
const char cutter_comp_read_spaced_indexed_current_position_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G41.1 D1\n"
|
||||
"G1 X# [5420]\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
cutter_comp_read_spaced_indexed_current_position_program,
|
||||
sizeof(cutter_comp_read_spaced_indexed_current_position_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject reading # [5420] with cutter compensation on");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) ==
|
||||
"Cannot read current position with cutter radius compensation on",
|
||||
"expected LinuxCNC cutter-comp spaced indexed current-position read error text");
|
||||
|
||||
const char cutter_comp_read_expression_indexed_current_position_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G41.1 D1\n"
|
||||
"#1 = #[5400 + 20]\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
cutter_comp_read_expression_indexed_current_position_program,
|
||||
sizeof(cutter_comp_read_expression_indexed_current_position_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject reading #[5400 + 20] with cutter compensation on");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) ==
|
||||
"Cannot read current position with cutter radius compensation on",
|
||||
"expected LinuxCNC cutter-comp expression-indexed current-position read error text");
|
||||
|
||||
const char cutter_comp_read_parameter_indexed_current_position_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"#1 = 5420\n"
|
||||
"G41.1 D1\n"
|
||||
"#2 = #[#1]\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
cutter_comp_read_parameter_indexed_current_position_program,
|
||||
sizeof(cutter_comp_read_parameter_indexed_current_position_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject reading #[#1] with cutter compensation on");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) ==
|
||||
"Cannot read current position with cutter radius compensation on",
|
||||
"expected LinuxCNC cutter-comp parameter-indexed current-position read error text");
|
||||
|
||||
const char cutter_comp_read_named_indexed_current_position_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"#<idx> = 5420\n"
|
||||
"G41.1 D1\n"
|
||||
"#2 = #[#<idx>]\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
cutter_comp_read_named_indexed_current_position_program,
|
||||
sizeof(cutter_comp_read_named_indexed_current_position_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject reading #[#<idx>] with cutter compensation on");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) ==
|
||||
"Cannot read current position with cutter radius compensation on",
|
||||
"expected LinuxCNC cutter-comp named-indexed current-position read error text");
|
||||
|
||||
const char arc_center_tolerance_good_imperial_program[] =
|
||||
"G20\n"
|
||||
"F1\n"
|
||||
@@ -6378,6 +6622,98 @@ int main() {
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "bad number format (conversion failed) parsing '1.2.3'",
|
||||
"expected LinuxCNC malformed-real-value error text");
|
||||
|
||||
const char unclosed_word_expression_program[] =
|
||||
"G21 G90\n"
|
||||
"F100\n"
|
||||
"G1 X[1 + 2\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
unclosed_word_expression_program,
|
||||
sizeof(unclosed_word_expression_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject an unclosed word expression");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Unclosed expression",
|
||||
"expected LinuxCNC unclosed-word-expression error text");
|
||||
|
||||
const char unclosed_parameter_assignment_expression_program[] =
|
||||
"#1 = [1 + 2\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
unclosed_parameter_assignment_expression_program,
|
||||
sizeof(unclosed_parameter_assignment_expression_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject an unclosed parameter assignment expression");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Unclosed expression",
|
||||
"expected LinuxCNC unclosed-parameter-assignment-expression error text");
|
||||
|
||||
const char unclosed_indexed_parameter_reference_program[] =
|
||||
"G21 G90\n"
|
||||
"F100\n"
|
||||
"G1 X#[1 + 2\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
unclosed_indexed_parameter_reference_program,
|
||||
sizeof(unclosed_indexed_parameter_reference_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject an unclosed indexed parameter reference");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Unclosed expression",
|
||||
"expected LinuxCNC unclosed-indexed-parameter-reference error text");
|
||||
|
||||
const char unclosed_indexed_parameter_assignment_program[] =
|
||||
"#[1 + 2 = 3\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
unclosed_indexed_parameter_assignment_program,
|
||||
sizeof(unclosed_indexed_parameter_assignment_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject an unclosed indexed parameter assignment");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Unclosed expression",
|
||||
"expected LinuxCNC unclosed-indexed-parameter-assignment error text");
|
||||
|
||||
const char unclosed_indirect_parameter_reference_program[] =
|
||||
"#1 = 3\n"
|
||||
"G21 G90\n"
|
||||
"F100\n"
|
||||
"G1 X##[1 + 2\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
unclosed_indirect_parameter_reference_program,
|
||||
sizeof(unclosed_indirect_parameter_reference_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject an unclosed indirect parameter reference");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Unclosed expression",
|
||||
"expected LinuxCNC unclosed-indirect-parameter-reference error text");
|
||||
|
||||
const char unterminated_named_parameter_reference_program[] =
|
||||
"G21 G90\n"
|
||||
"F100\n"
|
||||
"G1 X#<missing\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
unterminated_named_parameter_reference_program,
|
||||
sizeof(unterminated_named_parameter_reference_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject an unterminated named parameter reference");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Named parameter not terminated",
|
||||
"expected LinuxCNC unterminated-named-parameter-reference error text");
|
||||
|
||||
const char unterminated_indirect_named_parameter_reference_program[] =
|
||||
"#1 = 3\n"
|
||||
"G21 G90\n"
|
||||
"F100\n"
|
||||
"G1 X##<missing\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
unterminated_indirect_named_parameter_reference_program,
|
||||
sizeof(unterminated_indirect_named_parameter_reference_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject an unterminated indirect named parameter reference");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Named parameter not terminated",
|
||||
"expected LinuxCNC unterminated-indirect-named-parameter-reference error text");
|
||||
|
||||
const char unterminated_named_parameter_assignment_program[] =
|
||||
"#<missing = 3\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
unterminated_named_parameter_assignment_program,
|
||||
sizeof(unterminated_named_parameter_assignment_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject an unterminated named parameter assignment");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Named parameter not terminated",
|
||||
"expected LinuxCNC unterminated-named-parameter-assignment error text");
|
||||
|
||||
const char unused_p_word_program[] =
|
||||
"G21 G90\n"
|
||||
"F100\n"
|
||||
@@ -6398,6 +6734,115 @@ int main() {
|
||||
sizeof(invalid_arc_p_word_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject P value less than 1 with G2/G3");
|
||||
|
||||
const char absolute_center_arc_missing_axis_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"F100\n"
|
||||
"G90.1\n"
|
||||
"G2 X1 Y0 I0.5\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
absolute_center_arc_missing_axis_program,
|
||||
sizeof(absolute_center_arc_missing_axis_program) - 1) != 0,
|
||||
"expected LinuxCNC absolute-center arc to reject a missing center axis");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "J word missing in absolute center arc",
|
||||
"expected LinuxCNC missing absolute-center arc axis error text");
|
||||
|
||||
const char mixed_radius_ijk_arc_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"F100\n"
|
||||
"G2 X1 Y0 R1 I0.5 J0\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
mixed_radius_ijk_arc_program,
|
||||
sizeof(mixed_radius_ijk_arc_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject mixed R and IJK arc format");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Mixed radius ijk format for arc",
|
||||
"expected LinuxCNC mixed R/IJK arc error text");
|
||||
|
||||
const char missing_arc_format_words_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"F100\n"
|
||||
"G2 X1 Y0\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
missing_arc_format_words_program,
|
||||
sizeof(missing_arc_format_words_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject arc with no R/I/J/K words");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "R i j k words all missing for arc",
|
||||
"expected LinuxCNC missing R/I/J/K arc error text");
|
||||
|
||||
const char xy_arc_with_k_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"F100\n"
|
||||
"G2 X1 Y0 I0.5 J0 K0\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
xy_arc_with_k_program,
|
||||
sizeof(xy_arc_with_k_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject K word in XY-plane arc");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "K word given for arc in xy plane",
|
||||
"expected LinuxCNC XY-plane arc K-word error text");
|
||||
|
||||
const char xz_arc_with_j_program[] =
|
||||
"G21 G90 G18\n"
|
||||
"F100\n"
|
||||
"G2 X1 Z0 I0.5 K0 J0\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
xz_arc_with_j_program,
|
||||
sizeof(xz_arc_with_j_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject J word in XZ-plane arc");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "J word given for arc in xz plane",
|
||||
"expected LinuxCNC XZ-plane arc J-word error text");
|
||||
|
||||
const char yz_arc_with_i_program[] =
|
||||
"G21 G90 G19\n"
|
||||
"F100\n"
|
||||
"G2 Y1 Z0 J0.5 K0 I0\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
yz_arc_with_i_program,
|
||||
sizeof(yz_arc_with_i_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject I word in YZ-plane arc");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "I word given for arc in yz plane",
|
||||
"expected LinuxCNC YZ-plane arc I-word error text");
|
||||
|
||||
const char xy_r_arc_missing_endpoint_words_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"F100\n"
|
||||
"G2 R1\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
xy_r_arc_missing_endpoint_words_program,
|
||||
sizeof(xy_r_arc_missing_endpoint_words_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject XY R-format arc with no endpoint words");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "X and y words missing for arc in xy plane",
|
||||
"expected LinuxCNC XY R-format missing endpoint error text");
|
||||
|
||||
const char xz_r_arc_missing_endpoint_words_program[] =
|
||||
"G21 G90 G18\n"
|
||||
"F100\n"
|
||||
"G2 R1\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
xz_r_arc_missing_endpoint_words_program,
|
||||
sizeof(xz_r_arc_missing_endpoint_words_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject XZ R-format arc with no endpoint words");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "X and z words missing for arc in xz plane",
|
||||
"expected LinuxCNC XZ R-format missing endpoint error text");
|
||||
|
||||
const char yz_r_arc_missing_endpoint_words_program[] =
|
||||
"G21 G90 G19\n"
|
||||
"F100\n"
|
||||
"G2 R1\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
yz_r_arc_missing_endpoint_words_program,
|
||||
sizeof(yz_r_arc_missing_endpoint_words_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject YZ R-format arc with no endpoint words");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Y and z words missing for arc in yz plane",
|
||||
"expected LinuxCNC YZ R-format missing endpoint error text");
|
||||
|
||||
const char r_arc_too_small_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"F100\n"
|
||||
@@ -6628,6 +7073,8 @@ int main() {
|
||||
g10_l0_loaded_tool_program,
|
||||
sizeof(g10_l0_loaded_tool_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject G10 L0 with a loaded tool");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "G10 L0 not allowed with loaded tool <1>",
|
||||
"expected LinuxCNC G10 L0 loaded-tool error text");
|
||||
}
|
||||
|
||||
const char out_of_range_g10_l1_p_word_program[] =
|
||||
@@ -7104,6 +7551,24 @@ int main() {
|
||||
ok &= expect(saw_near_negative_one_g4_dwell,
|
||||
"expected LinuxCNC to execute G4 with P just above -1");
|
||||
|
||||
const char negative_then_positive_g4_p_word_program[] =
|
||||
"G21 G90\n"
|
||||
"G4 P-2 P3\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
negative_then_positive_g4_p_word_program,
|
||||
sizeof(negative_then_positive_g4_p_word_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_overridden_g4_dwell = false;
|
||||
for (const auto &event : events) {
|
||||
saw_overridden_g4_dwell = saw_overridden_g4_dwell ||
|
||||
(event.type == CNC_SIM_EVENT_DWELL &&
|
||||
event.line == 2 &&
|
||||
near(event.dwell_seconds, 3.0));
|
||||
}
|
||||
ok &= expect(saw_overridden_g4_dwell,
|
||||
"expected LinuxCNC P sentinel duplicate rule to keep the later G4 P value");
|
||||
|
||||
const char g4_with_arc_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"F100\n"
|
||||
@@ -7513,6 +7978,18 @@ int main() {
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Multiple x words on one line",
|
||||
"expected LinuxCNC duplicate-X error text");
|
||||
|
||||
const char duplicate_u_word_program[] =
|
||||
"G21 G90\n"
|
||||
"F100\n"
|
||||
"G1 U1 U2\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
duplicate_u_word_program,
|
||||
sizeof(duplicate_u_word_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject multiple U words on one line");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Multiple U words on one line",
|
||||
"expected LinuxCNC duplicate-U error text");
|
||||
|
||||
const char duplicate_spindle_selector_program[] =
|
||||
"G21 G90\n"
|
||||
"M3 $0 $1\n";
|
||||
@@ -7767,6 +8244,33 @@ int main() {
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Unknown g code used",
|
||||
"expected mixed G43.4 motion to use LinuxCNC unknown-G error text");
|
||||
|
||||
const char exponent_m428_control_program[] =
|
||||
"G21 G90\n"
|
||||
"M4.28e2\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
exponent_m428_control_program,
|
||||
sizeof(exponent_m428_control_program) - 1) != 0,
|
||||
"expected LinuxCNC-style M parsing to reject exponent M428 control syntax");
|
||||
|
||||
const char exponent_g434_control_program[] =
|
||||
"G21 G90\n"
|
||||
"G4.34e1 H7\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
exponent_g434_control_program,
|
||||
sizeof(exponent_g434_control_program) - 1) != 0,
|
||||
"expected LinuxCNC-style G parsing to reject exponent G43.4 control syntax");
|
||||
|
||||
const char exponent_h_control_program[] =
|
||||
"G21 G90\n"
|
||||
"G43.4 H7e0\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
exponent_h_control_program,
|
||||
sizeof(exponent_h_control_program) - 1) != 0,
|
||||
"expected LinuxCNC-style H parsing to reject exponent H control syntax");
|
||||
|
||||
const char invalid_character_program[] =
|
||||
"G21 G90\n"
|
||||
"?\n";
|
||||
@@ -7902,6 +8406,42 @@ int main() {
|
||||
ok &= expect(saw_spindle_all_cw, "expected LinuxCNC M3 $-1 spindle state");
|
||||
ok &= expect(saw_spindle_all_stop, "expected LinuxCNC M5 $-1 spindle state");
|
||||
|
||||
const char m3_dollar_word_out_of_range_program[] =
|
||||
"G21\n"
|
||||
"M3 $1\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
m3_dollar_word_out_of_range_program,
|
||||
sizeof(m3_dollar_word_out_of_range_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject out-of-range M3 $ spindle selector");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) ==
|
||||
"Spindle ($) number out of range in M3 Command\nnum_spindles =1. $=1\n",
|
||||
"expected LinuxCNC out-of-range M3 $ spindle error text");
|
||||
|
||||
const char m4_dollar_word_out_of_range_program[] =
|
||||
"G21\n"
|
||||
"M4 $1\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
m4_dollar_word_out_of_range_program,
|
||||
sizeof(m4_dollar_word_out_of_range_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject out-of-range M4 $ spindle selector");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) ==
|
||||
"Spindle ($) number out of range in M4 Command\nnum_spindles =1. $=1\n",
|
||||
"expected LinuxCNC out-of-range M4 $ spindle error text");
|
||||
|
||||
const char m5_dollar_word_out_of_range_program[] =
|
||||
"G21\n"
|
||||
"M5 $1\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
m5_dollar_word_out_of_range_program,
|
||||
sizeof(m5_dollar_word_out_of_range_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject out-of-range M5 $ spindle selector");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) ==
|
||||
"Spindle ($) number out of range in M5 Command\nnum_spindles =1. $=1\n",
|
||||
"expected LinuxCNC out-of-range M5 $ spindle error text");
|
||||
|
||||
const char spindle_mode_dollar_program[] =
|
||||
"G21\n"
|
||||
"G97 S1000 $0\n"
|
||||
@@ -7919,12 +8459,12 @@ int main() {
|
||||
saw_g97_dollar_mode = saw_g97_dollar_mode ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 970 &&
|
||||
event.reserved == kConstantRpmSpindleModeEvent &&
|
||||
event.tool == 0);
|
||||
saw_g96_dollar_mode = saw_g96_dollar_mode ||
|
||||
(event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 3 &&
|
||||
event.reserved == 960 &&
|
||||
event.reserved == kCssSpindleModeEvent &&
|
||||
event.tool == 0 &&
|
||||
near(event.feed, 2500.0));
|
||||
saw_g95_dollar_feed_mode = saw_g95_dollar_feed_mode ||
|
||||
@@ -8487,6 +9027,28 @@ int main() {
|
||||
sizeof(polar_g92_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject polar coordinates with G92");
|
||||
|
||||
const char polar_g52_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G52 @1 ^90\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
polar_g52_program,
|
||||
sizeof(polar_g52_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject polar coordinates with G52");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "All axes missing with g52 or g92",
|
||||
"expected LinuxCNC G52 polar missing-axis error text");
|
||||
|
||||
const char polar_g52_with_x_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G52 X1 @1 ^90\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
polar_g52_with_x_program,
|
||||
sizeof(polar_g52_with_x_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject X word mixed with polar coordinate in G52");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "Cannot specify both polar coordinate and X word",
|
||||
"expected LinuxCNC G52 polar/X conflict error text");
|
||||
|
||||
const char polar_g10_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G10 L2 P1 @1 ^90\n";
|
||||
@@ -8667,6 +9229,18 @@ int main() {
|
||||
sizeof(bad_precision_g_code_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject G code not on a tenth boundary");
|
||||
|
||||
const char boundary_noninteger_g_code_program[] =
|
||||
"G21 G90\n"
|
||||
"F100\n"
|
||||
"G1.9999 X1\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
boundary_noninteger_g_code_program,
|
||||
sizeof(boundary_noninteger_g_code_program) - 1) != 0,
|
||||
"expected LinuxCNC to reject G code exactly at the read_g upper tolerance boundary");
|
||||
ok &= expect(std::string(cnc_sim_last_error(sim)) == "G-code out of range",
|
||||
"expected LinuxCNC boundary-G error text");
|
||||
|
||||
const char scientific_notation_word_program[] =
|
||||
"G21 G90\n"
|
||||
"F100\n"
|
||||
@@ -9819,6 +10393,130 @@ int main() {
|
||||
}
|
||||
ok &= expect(saw_block_delete_disabled_line, "expected smoke disabled block-delete line to execute");
|
||||
|
||||
const char block_delete_rtcp_controls_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"/N10 M428\n"
|
||||
"/N20 G43.4 H7\n"
|
||||
"M30\n";
|
||||
config_rc = cnc_sim_load_config_json(sim, block_delete_on_config, sizeof(block_delete_on_config) - 1);
|
||||
events.clear();
|
||||
ok &= expect(config_rc == 0, cnc_sim_last_error(sim));
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
block_delete_rtcp_controls_program,
|
||||
sizeof(block_delete_rtcp_controls_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_smoke_block_delete_skipped_m428 = false;
|
||||
bool saw_smoke_block_delete_skipped_g434 = false;
|
||||
for (const auto &event : events) {
|
||||
saw_smoke_block_delete_skipped_m428 = saw_smoke_block_delete_skipped_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2);
|
||||
saw_smoke_block_delete_skipped_g434 = saw_smoke_block_delete_skipped_g434 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 3);
|
||||
}
|
||||
ok &= expect(!saw_smoke_block_delete_skipped_m428, "expected smoke block-delete M428 line to be skipped");
|
||||
ok &= expect(!saw_smoke_block_delete_skipped_g434, "expected smoke block-delete G43.4 line to be skipped");
|
||||
|
||||
config_rc = cnc_sim_load_config_json(sim, block_delete_off_config, sizeof(block_delete_off_config) - 1);
|
||||
events.clear();
|
||||
ok &= expect(config_rc == 0, cnc_sim_last_error(sim));
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
block_delete_rtcp_controls_program,
|
||||
sizeof(block_delete_rtcp_controls_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_smoke_block_delete_disabled_m428 = false;
|
||||
bool saw_smoke_block_delete_disabled_g434 = false;
|
||||
for (const auto &event : events) {
|
||||
saw_smoke_block_delete_disabled_m428 = saw_smoke_block_delete_disabled_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 1);
|
||||
saw_smoke_block_delete_disabled_g434 = saw_smoke_block_delete_disabled_g434 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 3 &&
|
||||
event.tool == 7);
|
||||
}
|
||||
ok &= expect(saw_smoke_block_delete_disabled_m428, "expected smoke disabled block-delete M428 to execute");
|
||||
ok &= expect(saw_smoke_block_delete_disabled_g434, "expected smoke disabled block-delete G43.4 to execute");
|
||||
|
||||
const char unary_sign_rtcp_controls_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"M++428\n"
|
||||
"G+43.4 H++7\n"
|
||||
"M30\n";
|
||||
config_rc = cnc_sim_load_config_json(sim, smoke_config, sizeof(smoke_config) - 1);
|
||||
events.clear();
|
||||
ok &= expect(config_rc == 0, cnc_sim_last_error(sim));
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
unary_sign_rtcp_controls_program,
|
||||
sizeof(unary_sign_rtcp_controls_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_smoke_unary_sign_m428 = false;
|
||||
bool saw_smoke_unary_sign_g434 = false;
|
||||
for (const auto &event : events) {
|
||||
saw_smoke_unary_sign_m428 = saw_smoke_unary_sign_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 1);
|
||||
saw_smoke_unary_sign_g434 = saw_smoke_unary_sign_g434 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 3 &&
|
||||
event.tool == 7);
|
||||
}
|
||||
ok &= expect(saw_smoke_unary_sign_m428, "expected smoke M++428 to execute as M428");
|
||||
ok &= expect(saw_smoke_unary_sign_g434, "expected smoke G+43.4 H++7 to execute as G43.4 H7");
|
||||
|
||||
const char numbered_rtcp_controls_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"N10 M428\n"
|
||||
"N20 G43.4 H7\n"
|
||||
"M30\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
numbered_rtcp_controls_program,
|
||||
sizeof(numbered_rtcp_controls_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_smoke_numbered_m428 = false;
|
||||
bool saw_smoke_numbered_g434 = false;
|
||||
for (const auto &event : events) {
|
||||
saw_smoke_numbered_m428 = saw_smoke_numbered_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 1);
|
||||
saw_smoke_numbered_g434 = saw_smoke_numbered_g434 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 3 &&
|
||||
event.tool == 7);
|
||||
}
|
||||
ok &= expect(saw_smoke_numbered_m428, "expected smoke N10 M428 to execute as M428");
|
||||
ok &= expect(saw_smoke_numbered_g434, "expected smoke N20 G43.4 H7 to execute as G43.4 H7");
|
||||
|
||||
const char bracket_rtcp_controls_program[] =
|
||||
"G21 G90 G17\n"
|
||||
"M[428]\n"
|
||||
"G[43.4] H[7]\n"
|
||||
"M30\n";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_parse_program(sim,
|
||||
bracket_rtcp_controls_program,
|
||||
sizeof(bracket_rtcp_controls_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_smoke_bracket_m428 = false;
|
||||
bool saw_smoke_bracket_g434 = false;
|
||||
for (const auto &event : events) {
|
||||
saw_smoke_bracket_m428 = saw_smoke_bracket_m428 ||
|
||||
(event.type == CNC_SIM_EVENT_KINEMATICS_SWITCH &&
|
||||
event.line == 2 &&
|
||||
event.reserved == 1);
|
||||
saw_smoke_bracket_g434 = saw_smoke_bracket_g434 ||
|
||||
(event.type == CNC_SIM_EVENT_RTCP_STATE &&
|
||||
event.line == 3 &&
|
||||
event.tool == 7);
|
||||
}
|
||||
ok &= expect(saw_smoke_bracket_m428, "expected smoke M[428] to execute as M428");
|
||||
ok &= expect(saw_smoke_bracket_g434, "expected smoke G[43.4] H[7] to execute as G43.4 H7");
|
||||
|
||||
const char comment_then_slash_program[] =
|
||||
"G21 G90 F100\n"
|
||||
"(comment) /G1 X5\n"
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kToolLengthOffsetEvent = 430;
|
||||
constexpr int kCssSpindleModeEvent = 960;
|
||||
|
||||
int collect_event(const CncSimEvent *event, void *user_data) {
|
||||
auto *events = static_cast<std::vector<CncSimEvent> *>(user_data);
|
||||
events->push_back(*event);
|
||||
@@ -189,7 +192,7 @@ int main() {
|
||||
event.spindle == 0.0 &&
|
||||
event.reserved == 0);
|
||||
saw_spindle_mode = saw_spindle_mode || (event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.reserved == 960 &&
|
||||
event.reserved == kCssSpindleModeEvent &&
|
||||
event.feed == 2500.0 &&
|
||||
event.tool == 0);
|
||||
saw_feed_mode = saw_feed_mode || (event.type == CNC_SIM_EVENT_SET_FEED &&
|
||||
@@ -320,7 +323,7 @@ int main() {
|
||||
event.feed == 15.0);
|
||||
saw_tool_length = saw_tool_length || (event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 19 &&
|
||||
event.reserved == 430 &&
|
||||
event.reserved == kToolLengthOffsetEvent &&
|
||||
event.start.z == 12.5);
|
||||
saw_comment = saw_comment || (event.type == CNC_SIM_EVENT_COMMENT &&
|
||||
event.line == 20);
|
||||
|
||||
@@ -105,6 +105,15 @@ int parse_named_integer_constant(const std::string &source, const std::string &n
|
||||
return std::stoi(match[1].str());
|
||||
}
|
||||
|
||||
int parse_named_enum_value(const std::string &source, const std::string &name) {
|
||||
const std::regex pattern(R"(\b)" + name + R"(\s*=\s*(-?\d+))");
|
||||
std::smatch match;
|
||||
if (!std::regex_search(source, match, pattern)) {
|
||||
return -1;
|
||||
}
|
||||
return std::stoi(match[1].str());
|
||||
}
|
||||
|
||||
int parse_constexpr_integer(const std::string &source, const std::string &name) {
|
||||
const std::regex pattern(R"(constexpr\s+int\s+)" + name + R"(\s*=\s*(\d+))");
|
||||
std::smatch match;
|
||||
@@ -822,6 +831,8 @@ int main() {
|
||||
const std::string interp_internal_source = read_file(interp_internal_path);
|
||||
const std::string parameter_def_source = read_file(parameter_def_path);
|
||||
const std::string linuxcnc_h_source = read_file(linuxcnc_h_path);
|
||||
const std::string canon_event_sink_source = read_file("core/src/canon_event_sink.cpp");
|
||||
const std::string linuxcnc_canon_bridge_source = read_file("core/src/linuxcnc_canon_bridge.cpp");
|
||||
const std::string smoke_source = read_file("core/src/smoke_gcode_parser.cpp");
|
||||
|
||||
bool ok = true;
|
||||
@@ -832,6 +843,8 @@ int main() {
|
||||
ok &= expect(!interp_internal_source.empty(), "expected to read LinuxCNC interp_internal.hh");
|
||||
ok &= expect(!parameter_def_source.empty(), "expected to read LinuxCNC interp_parameter_def.hh");
|
||||
ok &= expect(!linuxcnc_h_source.empty(), "expected to read LinuxCNC linuxcnc.h");
|
||||
ok &= expect(!canon_event_sink_source.empty(), "expected to read canon_event_sink.cpp");
|
||||
ok &= expect(!linuxcnc_canon_bridge_source.empty(), "expected to read linuxcnc_canon_bridge.cpp");
|
||||
ok &= expect(!smoke_source.empty(), "expected to read smoke_gcode_parser.cpp");
|
||||
|
||||
const int linuxcnc_max_parameters =
|
||||
@@ -1034,6 +1047,56 @@ int main() {
|
||||
ok &= expect(smoke_min_analog_output_index == linuxcnc_min_analog_output_index,
|
||||
"expected smoke M67/M68 minimum analog output index to match LinuxCNC");
|
||||
|
||||
const int linuxcnc_cutter_comp_off = parse_named_enum_value(interp_internal_source, "G_40");
|
||||
const int linuxcnc_cutter_comp_left = parse_named_enum_value(interp_internal_source, "G_41");
|
||||
const int linuxcnc_cutter_comp_left_explicit = parse_named_enum_value(interp_internal_source, "G_41_1");
|
||||
const int linuxcnc_cutter_comp_right = parse_named_enum_value(interp_internal_source, "G_42");
|
||||
const int linuxcnc_cutter_comp_right_explicit = parse_named_enum_value(interp_internal_source, "G_42_1");
|
||||
ok &= expect(parse_constexpr_integer(smoke_source, "kCutterCompOffEvent") == linuxcnc_cutter_comp_off,
|
||||
"expected smoke cutter-comp off event to match LinuxCNC G40 enum");
|
||||
ok &= expect(parse_constexpr_integer(smoke_source, "kCutterCompLeftEvent") == linuxcnc_cutter_comp_left,
|
||||
"expected smoke cutter-comp left event to match LinuxCNC G41 enum");
|
||||
ok &= expect(parse_constexpr_integer(smoke_source, "kCutterCompLeftExplicitEvent") ==
|
||||
linuxcnc_cutter_comp_left_explicit,
|
||||
"expected smoke explicit cutter-comp left event to match LinuxCNC G41.1 enum");
|
||||
ok &= expect(parse_constexpr_integer(smoke_source, "kCutterCompRightEvent") == linuxcnc_cutter_comp_right,
|
||||
"expected smoke cutter-comp right event to match LinuxCNC G42 enum");
|
||||
ok &= expect(parse_constexpr_integer(smoke_source, "kCutterCompRightExplicitEvent") ==
|
||||
linuxcnc_cutter_comp_right_explicit,
|
||||
"expected smoke explicit cutter-comp right event to match LinuxCNC G42.1 enum");
|
||||
|
||||
const int linuxcnc_tool_length_offset = parse_named_enum_value(interp_internal_source, "G_43");
|
||||
const int linuxcnc_dynamic_tool_length_offset =
|
||||
parse_named_enum_value(interp_internal_source, "G_43_1");
|
||||
const int linuxcnc_additive_tool_length_offset =
|
||||
parse_named_enum_value(interp_internal_source, "G_43_2");
|
||||
const int linuxcnc_cancel_tool_length_offset =
|
||||
parse_named_enum_value(interp_internal_source, "G_49");
|
||||
ok &= expect(parse_constexpr_integer(smoke_source, "kToolLengthOffsetEvent") ==
|
||||
linuxcnc_tool_length_offset,
|
||||
"expected smoke tool-length offset event to match LinuxCNC G43 enum");
|
||||
ok &= expect(parse_constexpr_integer(linuxcnc_canon_bridge_source, "kToolLengthOffsetEvent") ==
|
||||
linuxcnc_tool_length_offset,
|
||||
"expected LinuxCNC bridge tool-length offset event to match LinuxCNC G43 enum");
|
||||
ok &= expect(linuxcnc_dynamic_tool_length_offset == 431,
|
||||
"expected LinuxCNC G43.1 enum to remain dynamic tool-length offset");
|
||||
ok &= expect(linuxcnc_additive_tool_length_offset == 432,
|
||||
"expected LinuxCNC G43.2 enum to remain additive tool-length offset");
|
||||
ok &= expect(linuxcnc_cancel_tool_length_offset == 490,
|
||||
"expected LinuxCNC G49 enum to remain cancel tool-length offset");
|
||||
|
||||
const int linuxcnc_css_spindle_mode = parse_named_enum_value(interp_internal_source, "G_96");
|
||||
const int linuxcnc_constant_rpm_spindle_mode = parse_named_enum_value(interp_internal_source, "G_97");
|
||||
ok &= expect(parse_constexpr_integer(canon_event_sink_source, "kCssSpindleModeEvent") ==
|
||||
linuxcnc_css_spindle_mode,
|
||||
"expected canon sink CSS spindle mode event to match LinuxCNC G96 enum");
|
||||
ok &= expect(parse_constexpr_integer(canon_event_sink_source, "kConstantRpmSpindleModeEvent") ==
|
||||
linuxcnc_constant_rpm_spindle_mode,
|
||||
"expected canon sink constant-RPM spindle mode event to match LinuxCNC G97 enum");
|
||||
ok &= expect(parse_constexpr_integer(smoke_source, "kConstantRpmSpindleModeEvent") ==
|
||||
linuxcnc_constant_rpm_spindle_mode,
|
||||
"expected smoke constant-RPM spindle mode event to match LinuxCNC G97 enum");
|
||||
|
||||
const std::vector<double> linuxcnc_g_code_read_real_constants =
|
||||
parse_g_code_read_real_constants(interp_read_source);
|
||||
const double smoke_g_code_scale = parse_constexpr_double(smoke_source, "kLinuxCncGCodeScale");
|
||||
@@ -1184,11 +1247,21 @@ int main() {
|
||||
"expected complete smoke G modal table");
|
||||
ok &= expect(smoke_max_g_code == static_cast<int>(gees.size()) - 1,
|
||||
"expected smoke max G code to match LinuxCNC gees[] table");
|
||||
if (gees.size() > 490) {
|
||||
ok &= expect(gees[430] == 8, "expected LinuxCNC G43 to remain tool-length modal group 8");
|
||||
if (gees.size() > static_cast<std::size_t>(linuxcnc_cancel_tool_length_offset) &&
|
||||
linuxcnc_tool_length_offset >= 0 &&
|
||||
linuxcnc_dynamic_tool_length_offset >= 0 &&
|
||||
linuxcnc_additive_tool_length_offset >= 0 &&
|
||||
linuxcnc_cancel_tool_length_offset >= 0) {
|
||||
ok &= expect(gees[linuxcnc_tool_length_offset] == 8,
|
||||
"expected LinuxCNC G43 to remain tool-length modal group 8");
|
||||
ok &= expect(gees[linuxcnc_dynamic_tool_length_offset] == 8,
|
||||
"expected LinuxCNC G43.1 to remain tool-length modal group 8");
|
||||
ok &= expect(gees[linuxcnc_additive_tool_length_offset] == 8,
|
||||
"expected LinuxCNC G43.2 to remain tool-length modal group 8");
|
||||
ok &= expect(gees[434] == -1, "expected LinuxCNC G43.4 to stay out of gees[]");
|
||||
ok &= expect(gees[435] == -1, "expected LinuxCNC G43.5 to stay out of gees[]");
|
||||
ok &= expect(gees[490] == 8, "expected LinuxCNC G49 to remain tool-length modal group 8");
|
||||
ok &= expect(gees[linuxcnc_cancel_tool_length_offset] == 8,
|
||||
"expected LinuxCNC G49 to remain tool-length modal group 8");
|
||||
}
|
||||
if (gees.size() == smoke_g.size()) {
|
||||
ok &= expect_tables_equal(smoke_g, gees, "G modal group");
|
||||
|
||||
@@ -17,7 +17,39 @@ bool expect_near(double actual, double expected, const char *message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool expect_pose_near(const CncSimPose &actual, const CncSimPose &expected, const char *message) {
|
||||
bool expect(bool condition, const char *message) {
|
||||
if (!condition) {
|
||||
std::cerr << "FAIL: " << message << '\n';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool expect_near_eps(double actual, double expected, double epsilon, const char *message) {
|
||||
if (std::fabs(actual - expected) >= epsilon) {
|
||||
std::cerr << "FAIL: " << message << " actual=" << actual << " expected=" << expected
|
||||
<< " epsilon=" << epsilon << '\n';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool expect_joints_near(const LinuxCncFiveAxisJoints &actual,
|
||||
const LinuxCncFiveAxisJoints &expected,
|
||||
const char *message) {
|
||||
bool ok = true;
|
||||
ok &= expect_near(actual.x, expected.x, message);
|
||||
ok &= expect_near(actual.y, expected.y, message);
|
||||
ok &= expect_near(actual.z, expected.z, message);
|
||||
ok &= expect_near(actual.b, expected.b, message);
|
||||
ok &= expect_near(actual.c, expected.c, message);
|
||||
ok &= expect_near(actual.w, expected.w, message);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool expect_axis_joints_near(const LinuxCncAxisJoints &actual,
|
||||
const LinuxCncAxisJoints &expected,
|
||||
const char *message) {
|
||||
bool ok = true;
|
||||
ok &= expect_near(actual.x, expected.x, message);
|
||||
ok &= expect_near(actual.y, expected.y, message);
|
||||
@@ -25,6 +57,9 @@ bool expect_pose_near(const CncSimPose &actual, const CncSimPose &expected, cons
|
||||
ok &= expect_near(actual.a, expected.a, message);
|
||||
ok &= expect_near(actual.b, expected.b, message);
|
||||
ok &= expect_near(actual.c, expected.c, message);
|
||||
ok &= expect_near(actual.u, expected.u, message);
|
||||
ok &= expect_near(actual.v, expected.v, message);
|
||||
ok &= expect_near(actual.w, expected.w, message);
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -33,43 +68,378 @@ bool expect_pose_near(const CncSimPose &actual, const CncSimPose &expected, cons
|
||||
int main() {
|
||||
bool ok = true;
|
||||
|
||||
CncSimPose tip{};
|
||||
tip.x = 10.0;
|
||||
tip.y = 20.0;
|
||||
tip.z = 30.0;
|
||||
LinuxCncAxisJoints axis_joints{};
|
||||
axis_joints.x = 1.0;
|
||||
axis_joints.y = 2.0;
|
||||
axis_joints.z = 3.0;
|
||||
axis_joints.a = 4.0;
|
||||
axis_joints.b = 5.0;
|
||||
axis_joints.c = 6.0;
|
||||
axis_joints.u = 7.0;
|
||||
axis_joints.v = 8.0;
|
||||
axis_joints.w = 9.0;
|
||||
CncSimPose identity_pose = linuxcnc_identity_forward(axis_joints);
|
||||
ok &= expect_near(identity_pose.x, 1.0, "identity/trivkins forward x");
|
||||
ok &= expect_near(identity_pose.c, 6.0, "identity/trivkins forward c");
|
||||
ok &= expect_near(identity_pose.w, 9.0, "identity/trivkins forward w");
|
||||
ok &= expect_axis_joints_near(linuxcnc_identity_inverse(identity_pose),
|
||||
axis_joints,
|
||||
"identity/trivkins forward/inverse roundtrip");
|
||||
|
||||
CncSimPose pivot = rtcp_pivot_from_tool_tip(tip, 100.0);
|
||||
ok &= expect_near(pivot.x, 10.0, "zero-angle pivot x");
|
||||
ok &= expect_near(pivot.y, 20.0, "zero-angle pivot y");
|
||||
ok &= expect_near(pivot.z, 130.0, "zero-angle pivot z");
|
||||
axis_joints = {};
|
||||
axis_joints.x = 10.0;
|
||||
axis_joints.y = 0.0;
|
||||
axis_joints.z = 3.0;
|
||||
axis_joints.a = 4.0;
|
||||
axis_joints.b = 5.0;
|
||||
axis_joints.c = 90.0;
|
||||
axis_joints.u = 7.0;
|
||||
axis_joints.v = 8.0;
|
||||
axis_joints.w = 9.0;
|
||||
CncSimPose rotate_pose = linuxcnc_rotatekins_forward(axis_joints);
|
||||
ok &= expect_near(rotate_pose.x, 0.0, "rotatekins C90 forward x");
|
||||
ok &= expect_near(rotate_pose.y, -10.0, "rotatekins C90 forward y");
|
||||
ok &= expect_near(rotate_pose.z, 3.0, "rotatekins C90 forward z");
|
||||
ok &= expect_axis_joints_near(linuxcnc_rotatekins_inverse(rotate_pose),
|
||||
axis_joints,
|
||||
"rotatekins forward/inverse roundtrip");
|
||||
|
||||
tip.a = 90.0;
|
||||
pivot = rtcp_pivot_from_tool_tip(tip, 100.0);
|
||||
ok &= expect_near(pivot.x, 10.0, "A90 pivot x");
|
||||
ok &= expect_near(pivot.y, -80.0, "A90 pivot y");
|
||||
ok &= expect_near(pivot.z, 30.0, "A90 pivot z");
|
||||
LinuxCncFiveAxisJoints joints{};
|
||||
joints.x = 10.0;
|
||||
joints.y = 20.0;
|
||||
joints.z = 30.0;
|
||||
CncSimPose pose = linuxcnc_5axis_forward(joints, 250.0);
|
||||
ok &= expect_near(pose.x, 10.0, "5axiskins B0 C0 forward x");
|
||||
ok &= expect_near(pose.y, 20.0, "5axiskins B0 C0 forward y");
|
||||
ok &= expect_near(pose.z, 30.0, "5axiskins B0 C0 forward z");
|
||||
|
||||
tip.a = 0.0;
|
||||
tip.b = 90.0;
|
||||
pivot = rtcp_pivot_from_tool_tip(tip, 100.0);
|
||||
ok &= expect_near(pivot.x, 110.0, "B90 pivot x");
|
||||
ok &= expect_near(pivot.y, 20.0, "B90 pivot y");
|
||||
ok &= expect_near(pivot.z, 30.0, "B90 pivot z");
|
||||
joints.b = 90.0;
|
||||
joints.c = 0.0;
|
||||
pose = linuxcnc_5axis_forward(joints, 250.0);
|
||||
ok &= expect_near(pose.x, 260.0, "5axiskins B90 C0 forward x");
|
||||
ok &= expect_near(pose.y, 20.0, "5axiskins B90 C0 forward y");
|
||||
ok &= expect_near(pose.z, 280.0, "5axiskins B90 C0 forward z");
|
||||
|
||||
tip.a = 35.0;
|
||||
tip.b = -20.0;
|
||||
tip.c = 15.0;
|
||||
pivot = rtcp_pivot_from_tool_tip(tip, 123.4);
|
||||
const CncSimPose roundtrip = rtcp_tool_tip_from_pivot(pivot, 123.4);
|
||||
ok &= expect_pose_near(roundtrip, tip, "RTCP pivot/tool-tip roundtrip");
|
||||
joints.c = 90.0;
|
||||
pose = linuxcnc_5axis_forward(joints, 250.0);
|
||||
ok &= expect_near(pose.x, 10.0, "5axiskins B90 C90 forward x");
|
||||
ok &= expect_near(pose.y, 270.0, "5axiskins B90 C90 forward y");
|
||||
ok &= expect_near(pose.z, 280.0, "5axiskins B90 C90 forward z");
|
||||
|
||||
tip = {};
|
||||
tip.a = 90.0;
|
||||
tip.b = 90.0;
|
||||
const RtcpVector vector = rtcp_tool_vector_from_pose(tip, 10.0);
|
||||
ok &= expect_near(vector.x, 0.0, "A90 B90 tool vector x");
|
||||
ok &= expect_near(vector.y, 10.0, "A90 B90 tool vector y");
|
||||
ok &= expect_near(vector.z, 0.0, "A90 B90 tool vector z");
|
||||
joints.x = -12.5;
|
||||
joints.y = 4.0;
|
||||
joints.z = 81.25;
|
||||
joints.b = 37.0;
|
||||
joints.c = -23.0;
|
||||
joints.w = -15.0;
|
||||
pose = linuxcnc_5axis_forward(joints, 250.0);
|
||||
const LinuxCncFiveAxisJoints roundtrip_joints = linuxcnc_5axis_inverse(pose, 250.0);
|
||||
ok &= expect_joints_near(roundtrip_joints, joints, "5axiskins forward/inverse roundtrip");
|
||||
|
||||
LinuxCncXyzbcTrtParameters trt_parameters = linuxcnc_xyzbc_trt_default_parameters(250.0);
|
||||
joints = {};
|
||||
joints.x = 10.0;
|
||||
joints.y = 20.0;
|
||||
joints.z = 30.0;
|
||||
pose = linuxcnc_xyzbc_trt_forward(joints, trt_parameters);
|
||||
ok &= expect_near(pose.x, 10.0, "xyzbc-trt B0 C0 forward x");
|
||||
ok &= expect_near(pose.y, 20.0, "xyzbc-trt B0 C0 forward y");
|
||||
ok &= expect_near(pose.z, 30.0, "xyzbc-trt B0 C0 forward z");
|
||||
ok &= expect_near(pose.w, 0.0, "xyzbc-trt XYZBC forward drops unconfigured W");
|
||||
|
||||
joints.b = 90.0;
|
||||
joints.c = 0.0;
|
||||
pose = linuxcnc_xyzbc_trt_forward(joints, trt_parameters);
|
||||
ok &= expect_near(pose.x, 185.0, "xyzbc-trt B90 C0 forward x");
|
||||
ok &= expect_near(pose.y, 20.0, "xyzbc-trt B90 C0 forward y");
|
||||
ok &= expect_near(pose.z, 265.0, "xyzbc-trt B90 C0 forward z");
|
||||
|
||||
joints.c = 90.0;
|
||||
pose = linuxcnc_xyzbc_trt_forward(joints, trt_parameters);
|
||||
ok &= expect_near(pose.x, 20.0, "xyzbc-trt B90 C90 forward x");
|
||||
ok &= expect_near(pose.y, -185.0, "xyzbc-trt B90 C90 forward y");
|
||||
ok &= expect_near(pose.z, 265.0, "xyzbc-trt B90 C90 forward z");
|
||||
|
||||
pose = {};
|
||||
pose.x = 225.0;
|
||||
pose.y = 20.0;
|
||||
pose.z = -205.0;
|
||||
pose.b = 90.0;
|
||||
LinuxCncFiveAxisJoints trt_inverse_joints = linuxcnc_xyzbc_trt_inverse(pose, trt_parameters);
|
||||
ok &= expect_near(trt_inverse_joints.x, 10.0, "xyzbc-trt B90 C0 inverse x");
|
||||
ok &= expect_near(trt_inverse_joints.y, 20.0, "xyzbc-trt B90 C0 inverse y");
|
||||
ok &= expect_near(trt_inverse_joints.z, 30.0, "xyzbc-trt B90 C0 inverse z");
|
||||
ok &= expect_near(trt_inverse_joints.b, 90.0, "xyzbc-trt B90 C0 inverse b");
|
||||
ok &= expect_near(trt_inverse_joints.w, 0.0, "xyzbc-trt XYZBC inverse drops unconfigured W");
|
||||
|
||||
trt_parameters.conventional_directions = true;
|
||||
joints.x = -12.5;
|
||||
joints.y = 4.0;
|
||||
joints.z = 81.25;
|
||||
joints.b = 37.0;
|
||||
joints.c = -23.0;
|
||||
joints.w = 0.0;
|
||||
pose = linuxcnc_xyzbc_trt_forward(joints, trt_parameters);
|
||||
const LinuxCncFiveAxisJoints trt_roundtrip_joints = linuxcnc_xyzbc_trt_inverse(pose, trt_parameters);
|
||||
ok &= expect_joints_near(trt_roundtrip_joints, joints, "xyzbc-trt conventional forward/inverse roundtrip");
|
||||
|
||||
pose = {};
|
||||
pose.x = 1.0;
|
||||
pose.y = 2.0;
|
||||
pose.z = 3.0;
|
||||
pose.b = 4.0;
|
||||
pose.c = 5.0;
|
||||
pose.w = 6.0;
|
||||
const LinuxCncFiveAxisJoints userk_joints = linuxcnc_xyzbc_userk_inverse(pose);
|
||||
ok &= expect_near(userk_joints.x, 1.0, "xyzbc userk identity inverse x");
|
||||
ok &= expect_near(userk_joints.y, 2.0, "xyzbc userk identity inverse y");
|
||||
ok &= expect_near(userk_joints.z, 3.0, "xyzbc userk identity inverse z");
|
||||
ok &= expect_near(userk_joints.b, 4.0, "xyzbc userk identity inverse b");
|
||||
ok &= expect_near(userk_joints.c, 5.0, "xyzbc userk identity inverse c");
|
||||
ok &= expect_near(userk_joints.w, 0.0, "xyzbc userk identity inverse drops unconfigured W");
|
||||
|
||||
joints = {};
|
||||
joints.x = 6.0;
|
||||
joints.y = 5.0;
|
||||
joints.z = 4.0;
|
||||
joints.a = 12.0;
|
||||
joints.b = 3.0;
|
||||
joints.c = 2.0;
|
||||
joints.w = 1.0;
|
||||
const CncSimPose userk_pose = linuxcnc_xyzbc_userk_forward(joints);
|
||||
ok &= expect_near(userk_pose.x, 6.0, "xyzbc userk identity forward x");
|
||||
ok &= expect_near(userk_pose.y, 5.0, "xyzbc userk identity forward y");
|
||||
ok &= expect_near(userk_pose.z, 4.0, "xyzbc userk identity forward z");
|
||||
ok &= expect_near(userk_pose.a, 0.0, "xyzbc userk identity forward drops unconfigured A");
|
||||
ok &= expect_near(userk_pose.b, 3.0, "xyzbc userk identity forward b");
|
||||
ok &= expect_near(userk_pose.c, 2.0, "xyzbc userk identity forward c");
|
||||
ok &= expect_near(userk_pose.w, 0.0, "xyzbc userk identity forward drops unconfigured W");
|
||||
|
||||
trt_parameters = linuxcnc_xyzbc_trt_default_parameters(250.0);
|
||||
joints = {};
|
||||
joints.x = 10.0;
|
||||
joints.y = 20.0;
|
||||
joints.z = 30.0;
|
||||
CncSimPose xyzac_pose = linuxcnc_xyzac_trt_forward(joints, trt_parameters);
|
||||
ok &= expect_near(xyzac_pose.x, 10.0, "xyzac-trt A0 C0 forward x");
|
||||
ok &= expect_near(xyzac_pose.y, 20.0, "xyzac-trt A0 C0 forward y");
|
||||
ok &= expect_near(xyzac_pose.z, 30.0, "xyzac-trt A0 C0 forward z");
|
||||
|
||||
joints.a = 90.0;
|
||||
joints.c = 0.0;
|
||||
xyzac_pose = linuxcnc_xyzac_trt_forward(joints, trt_parameters);
|
||||
ok &= expect_near(xyzac_pose.x, 10.0, "xyzac-trt A90 C0 forward x");
|
||||
ok &= expect_near(xyzac_pose.y, -205.0, "xyzac-trt A90 C0 forward y");
|
||||
ok &= expect_near(xyzac_pose.z, 215.0, "xyzac-trt A90 C0 forward z");
|
||||
|
||||
joints.c = 90.0;
|
||||
xyzac_pose = linuxcnc_xyzac_trt_forward(joints, trt_parameters);
|
||||
ok &= expect_near(xyzac_pose.x, -205.0, "xyzac-trt A90 C90 forward x");
|
||||
ok &= expect_near(xyzac_pose.y, -10.0, "xyzac-trt A90 C90 forward y");
|
||||
ok &= expect_near(xyzac_pose.z, 215.0, "xyzac-trt A90 C90 forward z");
|
||||
|
||||
trt_parameters.conventional_directions = true;
|
||||
joints.x = -12.5;
|
||||
joints.y = 4.0;
|
||||
joints.z = 81.25;
|
||||
joints.a = 37.0;
|
||||
joints.c = -23.0;
|
||||
joints.b = 0.0;
|
||||
joints.w = 0.0;
|
||||
xyzac_pose = linuxcnc_xyzac_trt_forward(joints, trt_parameters);
|
||||
const LinuxCncFiveAxisJoints xyzac_roundtrip_joints =
|
||||
linuxcnc_xyzac_trt_inverse(xyzac_pose, trt_parameters);
|
||||
ok &= expect_near(xyzac_roundtrip_joints.x, joints.x, "xyzac-trt conventional roundtrip x");
|
||||
ok &= expect_near(xyzac_roundtrip_joints.y, joints.y, "xyzac-trt conventional roundtrip y");
|
||||
ok &= expect_near(xyzac_roundtrip_joints.z, joints.z, "xyzac-trt conventional roundtrip z");
|
||||
ok &= expect_near(xyzac_roundtrip_joints.a, joints.a, "xyzac-trt conventional roundtrip a");
|
||||
ok &= expect_near(xyzac_roundtrip_joints.c, joints.c, "xyzac-trt conventional roundtrip c");
|
||||
ok &= expect_near(xyzac_roundtrip_joints.b, 0.0, "xyzac-trt inverse drops unconfigured B");
|
||||
ok &= expect_near(xyzac_roundtrip_joints.w, 0.0, "xyzac-trt inverse drops unconfigured W");
|
||||
|
||||
LinuxCncScaraParameters scara_parameters = linuxcnc_scara_default_parameters();
|
||||
LinuxCncScaraJoints scara_joints{};
|
||||
scara_joints.j0 = 0.0;
|
||||
scara_joints.j1 = 0.0;
|
||||
scara_joints.j2 = 10.0;
|
||||
scara_joints.j3 = 0.0;
|
||||
scara_joints.j4 = 11.0;
|
||||
scara_joints.j5 = 12.0;
|
||||
int scara_iflags = 0;
|
||||
CncSimPose scara_pose = linuxcnc_scara_forward(scara_joints, scara_parameters, &scara_iflags);
|
||||
ok &= expect_near(scara_pose.x, 640.0, "scarakins default forward x");
|
||||
ok &= expect_near(scara_pose.y, 0.0, "scarakins default forward y");
|
||||
ok &= expect_near(scara_pose.z, 480.0, "scarakins default forward z");
|
||||
ok &= expect_near(scara_pose.c, 0.0, "scarakins default forward c");
|
||||
ok &= expect_near(scara_pose.a, 11.0, "scarakins default forward a");
|
||||
ok &= expect_near(scara_pose.b, 12.0, "scarakins default forward b");
|
||||
ok &= expect_near(scara_iflags, 1, "scarakins forward sets iflags for joint1 below 90");
|
||||
LinuxCncScaraJoints scara_inverse_joints =
|
||||
linuxcnc_scara_inverse(scara_pose, scara_parameters, scara_iflags);
|
||||
ok &= expect_near(scara_inverse_joints.j0, scara_joints.j0, "scarakins roundtrip j0");
|
||||
ok &= expect_near(scara_inverse_joints.j1, scara_joints.j1, "scarakins roundtrip j1");
|
||||
ok &= expect_near(scara_inverse_joints.j2, scara_joints.j2, "scarakins roundtrip j2");
|
||||
ok &= expect_near(scara_inverse_joints.j3, scara_joints.j3, "scarakins roundtrip j3");
|
||||
ok &= expect_near(scara_inverse_joints.j4, scara_joints.j4, "scarakins roundtrip j4");
|
||||
ok &= expect_near(scara_inverse_joints.j5, scara_joints.j5, "scarakins roundtrip j5");
|
||||
|
||||
scara_joints.j0 = 15.0;
|
||||
scara_joints.j1 = 120.0;
|
||||
scara_joints.j2 = -5.0;
|
||||
scara_joints.j3 = 20.0;
|
||||
scara_pose = linuxcnc_scara_forward(scara_joints, scara_parameters, &scara_iflags);
|
||||
ok &= expect_near(scara_iflags, 0, "scarakins forward clears iflags for joint1 at or above 90");
|
||||
scara_inverse_joints = linuxcnc_scara_inverse(scara_pose, scara_parameters, scara_iflags);
|
||||
ok &= expect_near(scara_inverse_joints.j0, scara_joints.j0, "scarakins iflags0 roundtrip j0");
|
||||
ok &= expect_near(scara_inverse_joints.j1, scara_joints.j1, "scarakins iflags0 roundtrip j1");
|
||||
ok &= expect_near(scara_inverse_joints.j2, scara_joints.j2, "scarakins iflags0 roundtrip j2");
|
||||
ok &= expect_near(scara_inverse_joints.j3, scara_joints.j3, "scarakins iflags0 roundtrip j3");
|
||||
|
||||
axis_joints = {};
|
||||
axis_joints.x = 1.0;
|
||||
axis_joints.y = 2.0;
|
||||
axis_joints.z = 3.0;
|
||||
axis_joints.a = 4.0;
|
||||
axis_joints.b = 5.0;
|
||||
axis_joints.c = 6.0;
|
||||
CncSimPose xyzab_identity_pose = linuxcnc_xyzab_tdr_identity_forward(axis_joints);
|
||||
ok &= expect_near(xyzab_identity_pose.x, 1.0, "xyzab-tdr type0 identity forward x");
|
||||
ok &= expect_near(xyzab_identity_pose.y, 2.0, "xyzab-tdr type0 identity forward y");
|
||||
ok &= expect_near(xyzab_identity_pose.z, 3.0, "xyzab-tdr type0 identity forward z");
|
||||
ok &= expect_near(xyzab_identity_pose.a, 4.0, "xyzab-tdr type0 identity forward a");
|
||||
ok &= expect_near(xyzab_identity_pose.b, 5.0, "xyzab-tdr type0 identity forward b");
|
||||
ok &= expect_near(xyzab_identity_pose.c, 0.0, "xyzab-tdr type0 identity drops unconfigured c");
|
||||
LinuxCncAxisJoints xyzab_identity_joints = linuxcnc_xyzab_tdr_identity_inverse(xyzab_identity_pose);
|
||||
ok &= expect_near(xyzab_identity_joints.x, 1.0, "xyzab-tdr type0 identity inverse x");
|
||||
ok &= expect_near(xyzab_identity_joints.y, 2.0, "xyzab-tdr type0 identity inverse y");
|
||||
ok &= expect_near(xyzab_identity_joints.z, 3.0, "xyzab-tdr type0 identity inverse z");
|
||||
ok &= expect_near(xyzab_identity_joints.a, 4.0, "xyzab-tdr type0 identity inverse a");
|
||||
ok &= expect_near(xyzab_identity_joints.b, 5.0, "xyzab-tdr type0 identity inverse b");
|
||||
ok &= expect_near(xyzab_identity_joints.c, 0.0, "xyzab-tdr type0 identity inverse drops c");
|
||||
|
||||
LinuxCncXyzabTdrParameters xyzab_parameters = linuxcnc_xyzab_tdr_default_parameters(250.0);
|
||||
axis_joints = {};
|
||||
axis_joints.x = 10.0;
|
||||
axis_joints.y = 20.0;
|
||||
axis_joints.z = 30.0;
|
||||
axis_joints.a = 90.0;
|
||||
axis_joints.b = 0.0;
|
||||
CncSimPose xyzab_tcp_pose = linuxcnc_xyzab_tdr_tcp_forward(axis_joints, xyzab_parameters);
|
||||
ok &= expect_near(xyzab_tcp_pose.x, 10.0, "xyzab-tdr type1 A90 B0 forward x");
|
||||
ok &= expect_near(xyzab_tcp_pose.y, 220.0, "xyzab-tdr type1 A90 B0 forward y");
|
||||
ok &= expect_near(xyzab_tcp_pose.z, 270.0, "xyzab-tdr type1 A90 B0 forward z");
|
||||
|
||||
axis_joints.a = 0.0;
|
||||
axis_joints.b = 90.0;
|
||||
xyzab_tcp_pose = linuxcnc_xyzab_tdr_tcp_forward(axis_joints, xyzab_parameters);
|
||||
ok &= expect_near(xyzab_tcp_pose.x, -220.0, "xyzab-tdr type1 A0 B90 forward x");
|
||||
ok &= expect_near(xyzab_tcp_pose.y, 20.0, "xyzab-tdr type1 A0 B90 forward y");
|
||||
ok &= expect_near(xyzab_tcp_pose.z, 240.0, "xyzab-tdr type1 A0 B90 forward z");
|
||||
|
||||
xyzab_parameters.x_rot_point = 3.0;
|
||||
xyzab_parameters.y_rot_point = -4.0;
|
||||
xyzab_parameters.z_rot_point = 5.0;
|
||||
xyzab_parameters.x_offset = 2.0;
|
||||
xyzab_parameters.z_offset = 7.0;
|
||||
xyzab_parameters.tool_offset_z = 11.0;
|
||||
axis_joints.x = -12.5;
|
||||
axis_joints.y = 4.0;
|
||||
axis_joints.z = 81.25;
|
||||
axis_joints.a = 37.0;
|
||||
axis_joints.b = -23.0;
|
||||
xyzab_tcp_pose = linuxcnc_xyzab_tdr_tcp_forward(axis_joints, xyzab_parameters);
|
||||
LinuxCncAxisJoints xyzab_tcp_roundtrip =
|
||||
linuxcnc_xyzab_tdr_tcp_inverse(xyzab_tcp_pose, xyzab_parameters);
|
||||
ok &= expect_near(xyzab_tcp_roundtrip.x, axis_joints.x, "xyzab-tdr type1 roundtrip x");
|
||||
ok &= expect_near(xyzab_tcp_roundtrip.y, axis_joints.y, "xyzab-tdr type1 roundtrip y");
|
||||
ok &= expect_near(xyzab_tcp_roundtrip.z, axis_joints.z, "xyzab-tdr type1 roundtrip z");
|
||||
ok &= expect_near(xyzab_tcp_roundtrip.a, axis_joints.a, "xyzab-tdr type1 roundtrip a");
|
||||
ok &= expect_near(xyzab_tcp_roundtrip.b, axis_joints.b, "xyzab-tdr type1 roundtrip b");
|
||||
|
||||
LinuxCncPumaParameters puma_parameters = linuxcnc_puma_default_parameters();
|
||||
LinuxCncAxisJoints puma_joints{};
|
||||
puma_joints.x = 20.0;
|
||||
puma_joints.y = -35.0;
|
||||
puma_joints.z = 45.0;
|
||||
puma_joints.a = 30.0;
|
||||
puma_joints.b = 40.0;
|
||||
puma_joints.c = -25.0;
|
||||
int puma_iflags = 0;
|
||||
CncSimPose puma_pose = linuxcnc_puma_forward(puma_joints, puma_parameters, &puma_iflags);
|
||||
int puma_fflags = 0;
|
||||
LinuxCncAxisJoints puma_roundtrip =
|
||||
linuxcnc_puma_inverse(puma_pose, puma_joints, puma_parameters, puma_iflags, &puma_fflags);
|
||||
ok &= expect_near(puma_roundtrip.x, puma_joints.x, "pumakins roundtrip j0");
|
||||
ok &= expect_near(puma_roundtrip.y, puma_joints.y, "pumakins roundtrip j1");
|
||||
ok &= expect_near(puma_roundtrip.z, puma_joints.z, "pumakins roundtrip j2");
|
||||
ok &= expect_near(puma_roundtrip.a, puma_joints.a, "pumakins roundtrip j3");
|
||||
ok &= expect_near(puma_roundtrip.b, puma_joints.b, "pumakins roundtrip j4");
|
||||
ok &= expect_near(puma_roundtrip.c, puma_joints.c, "pumakins roundtrip j5");
|
||||
ok &= expect_near(puma_fflags, 0, "pumakins non-singular inverse flags");
|
||||
|
||||
LinuxCncGenserParameters genser_parameters = linuxcnc_genser_puma560_parameters();
|
||||
LinuxCncAxisJoints genser_joints{};
|
||||
CncSimPose genser_pose = linuxcnc_genser_forward(genser_joints, genser_parameters);
|
||||
ok &= expect_near(genser_pose.x, 17.0, "genserkins puma560 zero forward x");
|
||||
ok &= expect_near(genser_pose.y, 5.4999999693964785, "genserkins puma560 zero forward y");
|
||||
ok &= expect_near(genser_pose.z, 7.199999995628068, "genserkins puma560 zero forward z");
|
||||
ok &= expect_near(genser_pose.a, 179.99999990891155, "genserkins puma560 zero forward a");
|
||||
ok &= expect_near(genser_pose.b, 0.0, "genserkins puma560 zero forward b");
|
||||
ok &= expect_near(genser_pose.c, 0.0, "genserkins puma560 zero forward c");
|
||||
|
||||
genser_joints.x = 20.0;
|
||||
genser_joints.y = -35.0;
|
||||
genser_joints.z = 45.0;
|
||||
genser_joints.a = 30.0;
|
||||
genser_joints.b = 40.0;
|
||||
genser_joints.c = -25.0;
|
||||
genser_pose = linuxcnc_genser_forward(genser_joints, genser_parameters);
|
||||
ok &= expect_near(genser_pose.x, 15.636973119039572, "genserkins puma560 forward x");
|
||||
ok &= expect_near(genser_pose.y, 10.791926162750677, "genserkins puma560 forward y");
|
||||
ok &= expect_near(genser_pose.z, -1.5388033640849728, "genserkins puma560 forward z");
|
||||
ok &= expect_near(genser_pose.a, 160.1443654010874, "genserkins puma560 forward a");
|
||||
ok &= expect_near(genser_pose.b, -45.62792804902442, "genserkins puma560 forward b");
|
||||
ok &= expect_near(genser_pose.c, 21.545586017440204, "genserkins puma560 forward c");
|
||||
|
||||
int genser_iterations = -1;
|
||||
LinuxCncAxisJoints genser_inverse_joints =
|
||||
linuxcnc_genser_inverse(genser_pose,
|
||||
genser_joints,
|
||||
genser_parameters,
|
||||
&genser_iterations);
|
||||
ok &= expect_near(genser_inverse_joints.x, genser_joints.x, "genserkins puma560 inverse x");
|
||||
ok &= expect_near(genser_inverse_joints.y, genser_joints.y, "genserkins puma560 inverse y");
|
||||
ok &= expect_near(genser_inverse_joints.z, genser_joints.z, "genserkins puma560 inverse z");
|
||||
ok &= expect_near(genser_inverse_joints.a, genser_joints.a, "genserkins puma560 inverse a");
|
||||
ok &= expect_near(genser_inverse_joints.b, genser_joints.b, "genserkins puma560 inverse b");
|
||||
ok &= expect_near(genser_inverse_joints.c, genser_joints.c, "genserkins puma560 inverse c");
|
||||
ok &= expect_near(genser_iterations, 0, "genserkins puma560 inverse exact-estimate iterations");
|
||||
|
||||
LinuxCncAxisJoints genser_estimate = genser_joints;
|
||||
genser_estimate.x += 0.25;
|
||||
genser_estimate.y -= 0.2;
|
||||
genser_estimate.z += 0.15;
|
||||
genser_estimate.a -= 0.1;
|
||||
genser_estimate.b += 0.12;
|
||||
genser_estimate.c -= 0.08;
|
||||
genser_inverse_joints =
|
||||
linuxcnc_genser_inverse(genser_pose,
|
||||
genser_estimate,
|
||||
genser_parameters,
|
||||
&genser_iterations);
|
||||
ok &= expect_near_eps(genser_inverse_joints.x, genser_joints.x, 1e-5,
|
||||
"genserkins puma560 iterative inverse x");
|
||||
ok &= expect_near_eps(genser_inverse_joints.y, genser_joints.y, 1e-5,
|
||||
"genserkins puma560 iterative inverse y");
|
||||
ok &= expect_near_eps(genser_inverse_joints.z, genser_joints.z, 1e-5,
|
||||
"genserkins puma560 iterative inverse z");
|
||||
ok &= expect_near_eps(genser_inverse_joints.a, genser_joints.a, 1e-5,
|
||||
"genserkins puma560 iterative inverse a");
|
||||
ok &= expect_near_eps(genser_inverse_joints.b, genser_joints.b, 1e-5,
|
||||
"genserkins puma560 iterative inverse b");
|
||||
ok &= expect_near_eps(genser_inverse_joints.c, genser_joints.c, 1e-5,
|
||||
"genserkins puma560 iterative inverse c");
|
||||
ok &= expect(genser_iterations > 0, "genserkins puma560 inverse should iterate from perturbed estimate");
|
||||
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -24,16 +24,88 @@ int main() {
|
||||
ok &= expect(actions.size() == 3, "expected three kinematics actions");
|
||||
ok &= expect(actions[0].kind == SimulatorGcodeControlKind::KinematicsSwitch &&
|
||||
actions[0].value == 1 &&
|
||||
actions[0].rtcp_enabled,
|
||||
"expected M428 original kinematics action");
|
||||
!actions[0].rtcp_enabled,
|
||||
"expected M428 kinematics switch without RTCP state change");
|
||||
ok &= expect(actions[1].kind == SimulatorGcodeControlKind::KinematicsSwitch &&
|
||||
actions[1].value == 0 &&
|
||||
!actions[1].rtcp_enabled,
|
||||
"expected M429 identity kinematics action");
|
||||
ok &= expect(actions[2].kind == SimulatorGcodeControlKind::KinematicsSwitch &&
|
||||
actions[2].value == 2 &&
|
||||
actions[2].rtcp_enabled,
|
||||
"expected M430 five-axis BC kinematics action");
|
||||
!actions[2].rtcp_enabled,
|
||||
"expected M430 userk switch without RTCP state change");
|
||||
ok &= expect(parse_simulator_gcode_control_line("/M428", false, &actions),
|
||||
"expected disabled block-delete M428 control line to execute");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::KinematicsSwitch &&
|
||||
actions[0].value == 1,
|
||||
"expected disabled block-delete M428 action");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("/M428", true, &actions),
|
||||
"expected enabled block-delete M428 control line to be skipped");
|
||||
ok &= expect(actions.empty(), "expected no actions for enabled block-delete M428");
|
||||
ok &= expect(parse_simulator_gcode_control_line("/N10 M428", false, &actions),
|
||||
"expected disabled block-delete leading-N M428 control line to execute");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::KinematicsSwitch &&
|
||||
actions[0].value == 1,
|
||||
"expected disabled block-delete /N10 M428 action");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("/N10 M428", true, &actions),
|
||||
"expected enabled block-delete leading-N M428 control line to be skipped");
|
||||
ok &= expect(actions.empty(), "expected no actions for enabled block-delete /N10 M428");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("M428 (unterminated", &actions),
|
||||
"expected unclosed comment on M428 line to fall through to LinuxCNC error handling");
|
||||
ok &= expect(actions.empty(), "expected no actions for M428 line with unclosed comment");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("M428 (outer (nested))", &actions),
|
||||
"expected nested comment on M428 line to fall through to LinuxCNC error handling");
|
||||
ok &= expect(actions.empty(), "expected no actions for M428 line with nested comment");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("(comment) /M428", false, &actions),
|
||||
"expected comment-prefixed slash M428 to fall through to LinuxCNC error handling");
|
||||
ok &= expect(actions.empty(), "expected no actions for comment-prefixed slash M428");
|
||||
ok &= expect(parse_simulator_gcode_control_line("M428.00009", &actions),
|
||||
"expected LinuxCNC integer tolerance to accept near-integer M428");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::KinematicsSwitch &&
|
||||
actions[0].value == 1,
|
||||
"expected near-integer M428 to parse as M428");
|
||||
ok &= expect(parse_simulator_gcode_control_line("M427.99995", &actions),
|
||||
"expected LinuxCNC integer tolerance to round high-fraction M word");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::KinematicsSwitch &&
|
||||
actions[0].value == 1,
|
||||
"expected high-fraction M427.99995 to parse as M428");
|
||||
ok &= expect(parse_simulator_gcode_control_line("M++428", &actions),
|
||||
"expected LinuxCNC unary plus M value to parse as M428");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::KinematicsSwitch &&
|
||||
actions[0].value == 1,
|
||||
"expected M++428 to parse as M428");
|
||||
ok &= expect(parse_simulator_gcode_control_line("N10 M428", &actions),
|
||||
"expected LinuxCNC leading N number before M428");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::KinematicsSwitch &&
|
||||
actions[0].value == 1,
|
||||
"expected N10 M428 to parse as M428");
|
||||
ok &= expect(parse_simulator_gcode_control_line("N10.25 M428", &actions),
|
||||
"expected LinuxCNC fractional N number before M428");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::KinematicsSwitch &&
|
||||
actions[0].value == 1,
|
||||
"expected N10.25 M428 to parse as M428");
|
||||
ok &= expect(parse_simulator_gcode_control_line("M[428]", &actions),
|
||||
"expected LinuxCNC bracketed M expression value to parse as M428");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::KinematicsSwitch &&
|
||||
actions[0].value == 1,
|
||||
"expected M[428] to parse as M428");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("M428.00011", &actions),
|
||||
"expected non-integer M word above lower tolerance to fall through");
|
||||
ok &= expect(actions.empty(), "expected no actions for lower-bound non-integer M word");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("M427.99989", &actions),
|
||||
"expected M word below upper round-up tolerance to fall through");
|
||||
ok &= expect(actions.empty(), "expected no actions for upper-bound non-integer M word");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("M4.28e2", &actions),
|
||||
"expected LinuxCNC non-exponent M-number parsing to leave trailing e2");
|
||||
ok &= expect(actions.empty(), "expected no actions for exponent M word");
|
||||
|
||||
ok &= expect(parse_simulator_gcode_control_line("G49 (cancel RTCP)", &actions),
|
||||
"expected G49 control line");
|
||||
@@ -42,6 +114,15 @@ int main() {
|
||||
!actions[0].rtcp_enabled &&
|
||||
actions[0].h_code == 0,
|
||||
"expected G49 RTCP off action");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("G49 (unterminated", &actions),
|
||||
"expected unclosed comment on G49 line to fall through to LinuxCNC error handling");
|
||||
ok &= expect(actions.empty(), "expected no actions for G49 line with unclosed comment");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("G49 (outer (nested))", &actions),
|
||||
"expected nested comment on G49 line to fall through to LinuxCNC error handling");
|
||||
ok &= expect(actions.empty(), "expected no actions for G49 line with nested comment");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("(comment) /G49", false, &actions),
|
||||
"expected comment-prefixed slash G49 to fall through to LinuxCNC error handling");
|
||||
ok &= expect(actions.empty(), "expected no actions for comment-prefixed slash G49");
|
||||
|
||||
ok &= expect(parse_simulator_gcode_control_line("G43.4 H7", &actions),
|
||||
"expected G43.4 H7 control line");
|
||||
@@ -50,6 +131,116 @@ int main() {
|
||||
actions[0].rtcp_enabled &&
|
||||
actions[0].h_code == 7,
|
||||
"expected G43.4 RTCP on action with H7");
|
||||
ok &= expect(parse_simulator_gcode_control_line("G43.5 H7", &actions),
|
||||
"expected G43.5 H7 control line");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::RtcpState &&
|
||||
actions[0].value == 435 &&
|
||||
actions[0].rtcp_enabled &&
|
||||
actions[0].h_code == 7,
|
||||
"expected G43.5 RTCP on action with H7");
|
||||
ok &= expect(parse_simulator_gcode_control_line("/G43.4 H7", false, &actions),
|
||||
"expected disabled block-delete G43.4 control line to execute");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::RtcpState &&
|
||||
actions[0].rtcp_enabled &&
|
||||
actions[0].h_code == 7,
|
||||
"expected disabled block-delete G43.4 action");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("/G43.4 H7", true, &actions),
|
||||
"expected enabled block-delete G43.4 control line to be skipped");
|
||||
ok &= expect(actions.empty(), "expected no actions for enabled block-delete G43.4");
|
||||
ok &= expect(parse_simulator_gcode_control_line("/N20 G43.4 H7", false, &actions),
|
||||
"expected disabled block-delete leading-N G43.4 control line to execute");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::RtcpState &&
|
||||
actions[0].rtcp_enabled &&
|
||||
actions[0].h_code == 7,
|
||||
"expected disabled block-delete /N20 G43.4 H7 action");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("/N20 G43.4 H7", true, &actions),
|
||||
"expected enabled block-delete leading-N G43.4 control line to be skipped");
|
||||
ok &= expect(actions.empty(), "expected no actions for enabled block-delete /N20 G43.4 H7");
|
||||
ok &= expect(parse_simulator_gcode_control_line("G43.40009 H7", &actions),
|
||||
"expected LinuxCNC read_g tolerance to accept near G43.4");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::RtcpState &&
|
||||
actions[0].value == 434 &&
|
||||
actions[0].rtcp_enabled &&
|
||||
actions[0].h_code == 7,
|
||||
"expected near G43.4 to parse as G43.4");
|
||||
ok &= expect(parse_simulator_gcode_control_line("G43.39995 H7", &actions),
|
||||
"expected LinuxCNC read_g tolerance to round high-fraction G word");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::RtcpState &&
|
||||
actions[0].value == 434 &&
|
||||
actions[0].rtcp_enabled &&
|
||||
actions[0].h_code == 7,
|
||||
"expected high-fraction G43.39995 to parse as G43.4");
|
||||
ok &= expect(parse_simulator_gcode_control_line("G+43.4 H+7", &actions),
|
||||
"expected LinuxCNC unary plus G/H values to parse");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::RtcpState &&
|
||||
actions[0].value == 434 &&
|
||||
actions[0].rtcp_enabled &&
|
||||
actions[0].h_code == 7,
|
||||
"expected G+43.4 H+7 to parse as G43.4 H7");
|
||||
ok &= expect(parse_simulator_gcode_control_line("N20 G43.4 H7", &actions),
|
||||
"expected LinuxCNC leading N number before G43.4");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::RtcpState &&
|
||||
actions[0].value == 434 &&
|
||||
actions[0].rtcp_enabled &&
|
||||
actions[0].h_code == 7,
|
||||
"expected N20 G43.4 H7 to parse as G43.4 H7");
|
||||
ok &= expect(parse_simulator_gcode_control_line("G[43.4] H[7]", &actions),
|
||||
"expected LinuxCNC bracketed G/H expression values to parse");
|
||||
ok &= expect(actions.size() == 1 &&
|
||||
actions[0].kind == SimulatorGcodeControlKind::RtcpState &&
|
||||
actions[0].value == 434 &&
|
||||
actions[0].rtcp_enabled &&
|
||||
actions[0].h_code == 7,
|
||||
"expected G[43.4] H[7] to parse as G43.4 H7");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("G43.4002 H7", &actions),
|
||||
"expected G word above read_g out-of-range tolerance to fall through");
|
||||
ok &= expect(actions.empty(), "expected no actions for out-of-range G word");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("G43.3998 H7", &actions),
|
||||
"expected G word below read_g round-up tolerance to fall through");
|
||||
ok &= expect(actions.empty(), "expected no actions below G word round-up tolerance");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("G4.34e1 H7", &actions),
|
||||
"expected LinuxCNC non-exponent G-number parsing to leave trailing e1");
|
||||
ok &= expect(actions.empty(), "expected no actions for exponent G word");
|
||||
ok &= expect(parse_simulator_gcode_control_line("G43.4 H7.00009", &actions),
|
||||
"expected LinuxCNC integer tolerance to accept near-integer H");
|
||||
ok &= expect(actions.size() == 1 && actions[0].h_code == 7,
|
||||
"expected near-integer H to keep the lower integer");
|
||||
ok &= expect(parse_simulator_gcode_control_line("G43.4 H7.99995", &actions),
|
||||
"expected LinuxCNC integer tolerance to round high-fraction H");
|
||||
ok &= expect(actions.size() == 1 && actions[0].h_code == 8,
|
||||
"expected high-fraction H to round up");
|
||||
ok &= expect(parse_simulator_gcode_control_line("G43.4 H++7", &actions),
|
||||
"expected LinuxCNC recursive unary plus H value to parse");
|
||||
ok &= expect(actions.size() == 1 && actions[0].h_code == 7,
|
||||
"expected H++7 to parse as H7");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("G43.4 H7.00011", &actions),
|
||||
"expected non-integer H above lower tolerance to fall through");
|
||||
ok &= expect(actions.empty(), "expected no actions for lower-bound non-integer H");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("G43.4 H7.99989", &actions),
|
||||
"expected H below the upper round-up tolerance to fall through");
|
||||
ok &= expect(actions.empty(), "expected no actions for upper-bound non-integer H");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("G43.4 H7e0", &actions),
|
||||
"expected LinuxCNC non-exponent H-number parsing to leave trailing e0");
|
||||
ok &= expect(actions.empty(), "expected no actions for exponent H word");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("G43.4 H-2", &actions),
|
||||
"expected LinuxCNC negative-H rule to fall through");
|
||||
ok &= expect(actions.empty(), "expected no actions for invalid negative H");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("G43.4 H7 H8", &actions),
|
||||
"expected duplicate H words to fall through to LinuxCNC error handling");
|
||||
ok &= expect(actions.empty(), "expected no actions for duplicate H words");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("G43.4 G49", &actions),
|
||||
"expected duplicate RTCP-state G words to fall through to LinuxCNC modal-group handling");
|
||||
ok &= expect(actions.empty(), "expected no actions for duplicate RTCP-state G words");
|
||||
ok &= expect(!parse_simulator_gcode_control_line("G49 H7", &actions),
|
||||
"expected G49 with unused H word to fall through to LinuxCNC error handling");
|
||||
ok &= expect(actions.empty(), "expected no actions for G49 with unused H word");
|
||||
|
||||
ok &= expect(!parse_simulator_gcode_control_line("G43.4 H7 X10", &actions),
|
||||
"expected mixed RTCP/motion line to fall through to interpreter");
|
||||
|
||||
@@ -18,6 +18,9 @@ The event callback emits normalized `CncSimEvent` records. JavaScript can transf
|
||||
|
||||
## LinuxCNC integration plan
|
||||
|
||||
Functional behavior must come from LinuxCNC source code, not independently
|
||||
designed project code. See `docs/linuxcnc-source-policy.md`.
|
||||
|
||||
1. Build a native `CanonEventSink` that implements all functions declared in `canon.hh`.
|
||||
2. Link the sink with `src/emc/rs274ngc` and `src/emc/nml_intf` instead of the task controller.
|
||||
3. Stub or remove Python remap support for the first browser target.
|
||||
@@ -58,10 +61,18 @@ Feature parity needs more than G-code parsing:
|
||||
|
||||
## Five-axis and RTCP
|
||||
|
||||
The first RTCP implementation is a geometry kernel, not the full LinuxCNC motion
|
||||
controller. It treats programmed XYZ as the tool-center point, applies A/B/C
|
||||
orientation to a local tool vector, and computes the compensated pivot/spindle
|
||||
point needed to keep the tool tip fixed.
|
||||
RTCP pivot events are emitted only for known LinuxCNC switchkins modes. These
|
||||
paths must use formulas copied from LinuxCNC source code, not independently
|
||||
derived geometry. The current source mapping is:
|
||||
|
||||
- `M428` / `XYZBC_TRT`: `linuxcnc/src/emc/kinematics/trtfuncs.c`,
|
||||
`xyzbcKinematicsForward()` and `xyzbcKinematicsInverse()`
|
||||
- `M430` / `USERK_IDENTITY`: `linuxcnc/src/emc/kinematics/userkfuncs.c`,
|
||||
delegating to `identityKinematicsForward()` and
|
||||
`identityKinematicsInverse()` in `kins_util.c`
|
||||
- The retained `5axiskins` helpers map to
|
||||
`linuxcnc/src/emc/kinematics/5axiskins.c`,
|
||||
`fiveaxis_KinematicsForward()` and `fiveaxis_KinematicsInverse()`
|
||||
|
||||
RTCP is opt-in through config JSON. When enabled, the original motion events
|
||||
remain programmed tool-tip motion and an additional `rtcp-pivot` event is emitted
|
||||
@@ -74,7 +85,5 @@ Current files:
|
||||
- `core/src/rtcp_kinematics.cpp`
|
||||
- `core/tests/rtcp_kinematics_smoke.cpp`
|
||||
|
||||
The next integration step is to add machine configuration for rotary topology,
|
||||
pivot offsets, tool length sources, and rotation order, then apply RTCP
|
||||
compensation while converting LinuxCNC Canon motion events into renderable
|
||||
machine/tool-tip trajectories.
|
||||
The next integration step is to add more LinuxCNC source-backed kinematics for
|
||||
additional switchkins or machine topologies.
|
||||
|
||||
@@ -19,7 +19,7 @@ g++ -std=c++17 -I core/include core/src/cnc_sim_api.cpp core/tests/cnc_sim_api_s
|
||||
|
||||
Status: in progress.
|
||||
|
||||
This parser only exists to test the ABI and UI before Emscripten and LinuxCNC are wired in. It currently handles:
|
||||
This parser only exists to test the ABI and UI before Emscripten and LinuxCNC are wired in. It is not a production feature implementation. Do not extend it with independently designed G-code behavior; when a behavior needs to change, first locate the LinuxCNC source implementation and either route to that source-backed backend or port the corresponding source logic. It currently handles:
|
||||
|
||||
- multiple G/M words on one line
|
||||
- `G0`, `G1`, `G2`, `G3`
|
||||
@@ -39,7 +39,7 @@ This parser only exists to test the ABI and UI before Emscripten and LinuxCNC ar
|
||||
- canned cycles `G73`, `G74`, `G81`, `G82`, `G83`, `G84`, `G85`, `G86`, `G87`, `G88`, `G89` with `G80`, `G98`, `G99`, `L`
|
||||
- coordinate offset events for `G10 L2`, `G10 L20`, `G54`-`G59.3`, `G52`, `G92`, `G92.1`, `G92.2`, and `G92.3`
|
||||
|
||||
It is not the production interpreter.
|
||||
It is not the production interpreter. Any remaining smoke-only behavior is technical debt to replace with LinuxCNC source-backed code.
|
||||
|
||||
## Step 2: Canon event sink
|
||||
|
||||
|
||||
32
docs/linuxcnc-source-policy.md
Normal file
32
docs/linuxcnc-source-policy.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# LinuxCNC Source Policy
|
||||
|
||||
The simulator must not grow independently designed functional behavior.
|
||||
Functional behavior must come from LinuxCNC source code.
|
||||
|
||||
Allowed project code:
|
||||
|
||||
- Thin adapters between LinuxCNC source code and the simulator C API.
|
||||
- Platform shims needed to compile LinuxCNC code for native tests or wasm.
|
||||
- Event serialization, test fixtures, build scripts, and documentation.
|
||||
- Temporary smoke scaffolding only when it is explicitly marked as temporary.
|
||||
|
||||
Not allowed as final behavior:
|
||||
|
||||
- Hand-written G-code interpretation semantics.
|
||||
- Hand-derived kinematics, RTCP, coordinate transform, cutter compensation, canned cycle, modal, parameter, or expression behavior.
|
||||
- Behavior copied from documentation, controller intuition, or examples without checking the LinuxCNC implementation.
|
||||
|
||||
Required workflow for every functional change:
|
||||
|
||||
1. Identify the LinuxCNC source file and function that defines the behavior.
|
||||
2. Add or update a test that demonstrates the LinuxCNC behavior.
|
||||
3. Port, wrap, or route to that LinuxCNC implementation.
|
||||
4. Record the source file/function in code comments or nearby documentation when the mapping is not obvious.
|
||||
5. Run `./test-native.sh` and `./test-linuxcnc-source-link.sh`.
|
||||
|
||||
Current temporary exceptions:
|
||||
|
||||
- The smoke parser exists only to exercise the public API and UI while the LinuxCNC RS274 backend is being wired in.
|
||||
- RTCP pivot behavior is limited to LinuxCNC source-backed switchkins paths; unsupported switchkins types must not fall back to hand-derived geometry.
|
||||
|
||||
Both exceptions should shrink over time. New functional behavior should not be added to them unless it is directly copied from, or routed to, LinuxCNC source code.
|
||||
@@ -34,4 +34,19 @@ binding:src/emc/rs274ngc/pyparamclass.cc:Boost.Python bindings; exclude from was
|
||||
tooldata:src/emc/tooldata/tooldata_common.cc:shared tool table parser/format logic
|
||||
tooldata:src/emc/tooldata/tooldata_mmap.cc:native mmap implementation; replace for wasm
|
||||
tooldata:src/emc/tooldata/tooldata_db.cc:external database integration; exclude from wasm core
|
||||
|
||||
header:src/emc/rs274ngc/array1.hh:LinuxCNC rs274 header tracked for full interpreter source coverage
|
||||
header:src/emc/rs274ngc/boost_pyenum_macros.hh:LinuxCNC rs274 Boost.Python enum helper header
|
||||
header:src/emc/rs274ngc/interp_array_types.hh:LinuxCNC rs274 block array type definitions
|
||||
header:src/emc/rs274ngc/interp_base.hh:LinuxCNC rs274 base interpreter declarations
|
||||
header:src/emc/rs274ngc/interp_fwd.hh:LinuxCNC rs274 forward declarations
|
||||
header:src/emc/rs274ngc/interp_inspection.hh:LinuxCNC rs274 inspection declarations
|
||||
header:src/emc/rs274ngc/interp_internal.hh:LinuxCNC rs274 internal interpreter declarations
|
||||
header:src/emc/rs274ngc/interp_parameter_def.hh:LinuxCNC rs274 parameter definitions
|
||||
header:src/emc/rs274ngc/interp_python.hh:LinuxCNC rs274 Python/remap declarations
|
||||
header:src/emc/rs274ngc/interp_queue.hh:LinuxCNC rs274 queue declarations
|
||||
header:src/emc/rs274ngc/modal_state.hh:LinuxCNC rs274 modal state declarations
|
||||
header:src/emc/rs274ngc/paramclass.hh:LinuxCNC rs274 parameter class declarations
|
||||
header:src/emc/rs274ngc/rs274ngc.hh:LinuxCNC rs274 public interface header
|
||||
header:src/emc/rs274ngc/rs274ngc_interp.hh:LinuxCNC rs274 interpreter class header
|
||||
header:src/emc/rs274ngc/rs274ngc_return.hh:LinuxCNC rs274 return code header
|
||||
header:src/emc/rs274ngc/units.h:LinuxCNC rs274 units helper header
|
||||
|
||||
@@ -26,3 +26,19 @@ core:src/emc/rs274ngc/rs274ngc_pre.cc:Interp implementation covered by rs274ngc_
|
||||
core:src/emc/tooldata/tooldata_common.cc:shared tool table parser/format logic linked with wasm-safe mmap backend
|
||||
core:src/emc/ini/inifile.cc:INI reader needed by rs274ngc_pre source-link probe
|
||||
blocked:src/emc/tooldata/tooldata_mmap.cc:native mmap implementation
|
||||
header:src/emc/rs274ngc/array1.hh:LinuxCNC rs274 header tracked for full interpreter source coverage
|
||||
blocked-header:src/emc/rs274ngc/boost_pyenum_macros.hh:Boost.Python helper header, tracked but not wasm-safe API surface
|
||||
header:src/emc/rs274ngc/interp_array_types.hh:LinuxCNC rs274 block array type definitions
|
||||
header:src/emc/rs274ngc/interp_base.hh:LinuxCNC rs274 base interpreter declarations
|
||||
header:src/emc/rs274ngc/interp_fwd.hh:LinuxCNC rs274 forward declarations
|
||||
header:src/emc/rs274ngc/interp_inspection.hh:LinuxCNC rs274 inspection declarations
|
||||
header:src/emc/rs274ngc/interp_internal.hh:LinuxCNC rs274 internal interpreter declarations
|
||||
header:src/emc/rs274ngc/interp_parameter_def.hh:LinuxCNC rs274 parameter definitions
|
||||
header:src/emc/rs274ngc/interp_python.hh:LinuxCNC rs274 Python/remap declarations, compile-satisfied by wasm shims
|
||||
header:src/emc/rs274ngc/interp_queue.hh:LinuxCNC rs274 queue declarations
|
||||
header:src/emc/rs274ngc/modal_state.hh:LinuxCNC rs274 modal state declarations
|
||||
header:src/emc/rs274ngc/paramclass.hh:LinuxCNC rs274 parameter class declarations
|
||||
header:src/emc/rs274ngc/rs274ngc.hh:LinuxCNC rs274 public interface header
|
||||
header:src/emc/rs274ngc/rs274ngc_interp.hh:LinuxCNC rs274 interpreter class header
|
||||
header:src/emc/rs274ngc/rs274ngc_return.hh:LinuxCNC rs274 return code header
|
||||
header:src/emc/rs274ngc/units.h:LinuxCNC rs274 units helper header
|
||||
|
||||
45
list-cmake-set-plus-append-sources.sh
Executable file
45
list-cmake-set-plus-append-sources.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
if [[ "$#" -lt 2 || "$#" -gt 3 ]]; then
|
||||
echo "usage: $0 <set-name> <append-name> [relative-prefix]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set_name=$1
|
||||
append_name=$2
|
||||
relative_prefix=${3:-}
|
||||
|
||||
awk -v set_name="$set_name" -v append_name="$append_name" -v relative_prefix="$relative_prefix" '
|
||||
$0 ~ "^[[:space:]]*set\\(" set_name "([[:space:]]|$)" {
|
||||
in_set = 1
|
||||
next
|
||||
}
|
||||
in_set && /^[[:space:]]*\)/ {
|
||||
in_set = 0
|
||||
next
|
||||
}
|
||||
$0 ~ "^[[:space:]]*list\\(APPEND " append_name "([[:space:]]|$)" {
|
||||
in_append = 1
|
||||
next
|
||||
}
|
||||
in_append && /^[[:space:]]*\)/ {
|
||||
in_append = 0
|
||||
next
|
||||
}
|
||||
in_set || in_append {
|
||||
line = $0
|
||||
sub(/^[[:space:]]*/, "", line)
|
||||
sub(/[[:space:]]*$/, "", line)
|
||||
if (line == "") {
|
||||
next
|
||||
}
|
||||
sub(/^\$\{CMAKE_CURRENT_SOURCE_DIR\}\//, "core/", line)
|
||||
if (line !~ /^core\// && relative_prefix != "") {
|
||||
line = relative_prefix line
|
||||
}
|
||||
print line
|
||||
}
|
||||
' core/CMakeLists.txt
|
||||
35
list-cmake-set-sources.sh
Executable file
35
list-cmake-set-sources.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
if [[ "$#" -lt 1 || "$#" -gt 2 ]]; then
|
||||
echo "usage: $0 <cmake-set-name> [relative-prefix]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set_name=$1
|
||||
relative_prefix=${2:-}
|
||||
|
||||
awk -v set_name="$set_name" -v relative_prefix="$relative_prefix" '
|
||||
$0 ~ "^[[:space:]]*set\\(" set_name "([[:space:]]|$)" {
|
||||
in_list = 1
|
||||
next
|
||||
}
|
||||
in_list && /^[[:space:]]*\)/ {
|
||||
exit
|
||||
}
|
||||
in_list {
|
||||
line = $0
|
||||
sub(/^[[:space:]]*/, "", line)
|
||||
sub(/[[:space:]]*$/, "", line)
|
||||
if (line == "") {
|
||||
next
|
||||
}
|
||||
sub(/^\$\{CMAKE_CURRENT_SOURCE_DIR\}\//, "core/", line)
|
||||
if (line !~ /^core\// && relative_prefix != "") {
|
||||
line = relative_prefix line
|
||||
}
|
||||
print line
|
||||
}
|
||||
' core/CMakeLists.txt
|
||||
@@ -5,40 +5,7 @@ cd "$(dirname "$0")"
|
||||
|
||||
filter=${1:-}
|
||||
|
||||
awk '
|
||||
/set\(cnc_sim_core_sources/ {
|
||||
in_list = 1
|
||||
next
|
||||
}
|
||||
in_list && /^[[:space:]]*\)/ {
|
||||
exit
|
||||
}
|
||||
in_list {
|
||||
line = $0
|
||||
sub(/^[[:space:]]*/, "", line)
|
||||
sub(/[[:space:]]*$/, "", line)
|
||||
if (line == "") {
|
||||
next
|
||||
}
|
||||
print "core/" line
|
||||
}
|
||||
' core/CMakeLists.txt | while IFS= read -r source; do
|
||||
if [[ ! -f "$source" ]]; then
|
||||
echo "missing cnc sim core source: $source" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "$filter" && "$(basename "$source")" != "$filter" ]]; then
|
||||
continue
|
||||
fi
|
||||
printf '%s\n' "$source"
|
||||
done | {
|
||||
found=0
|
||||
while IFS= read -r source; do
|
||||
found=1
|
||||
printf '%s\n' "$source"
|
||||
done
|
||||
if [[ -n "$filter" && "$found" -eq 0 ]]; then
|
||||
echo "missing cnc sim core source in CMake list: $filter" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
./list-cmake-set-sources.sh cnc_sim_core_sources core/ | ./list-filtered-existing-paths.sh \
|
||||
"$filter" \
|
||||
"missing cnc sim core source" \
|
||||
"missing cnc sim core source in CMake list"
|
||||
|
||||
36
list-filtered-existing-paths.sh
Executable file
36
list-filtered-existing-paths.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
if [[ "$#" -lt 3 ]]; then
|
||||
echo "usage: $0 <filter> <missing-path-message> <missing-filter-message> [missing-path-hint]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
filter=$1
|
||||
missing_path_message=$2
|
||||
missing_filter_message=$3
|
||||
missing_path_hint=${4:-}
|
||||
|
||||
found=0
|
||||
while IFS= read -r path; do
|
||||
[[ -z "$path" ]] && continue
|
||||
if [[ ! -f "$path" ]]; then
|
||||
echo "$missing_path_message: $path" >&2
|
||||
if [[ -n "$missing_path_hint" ]]; then
|
||||
echo "$missing_path_hint" >&2
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "$filter" && "$(basename "$path")" != "$filter" ]]; then
|
||||
continue
|
||||
fi
|
||||
found=1
|
||||
printf '%s\n' "$path"
|
||||
done
|
||||
|
||||
if [[ -n "$filter" && "$found" -eq 0 ]]; then
|
||||
echo "$missing_filter_message: $filter" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -5,26 +5,4 @@ cd "$(dirname "$0")"
|
||||
|
||||
filter=${1:-}
|
||||
|
||||
sources=(
|
||||
core/src/canon_event_sink.cpp
|
||||
core/src/linuxcnc_canon_bridge.cpp
|
||||
core/src/rtcp_kinematics.cpp
|
||||
)
|
||||
|
||||
found=0
|
||||
for source in "${sources[@]}"; do
|
||||
if [[ ! -f "$source" ]]; then
|
||||
echo "missing LinuxCNC bridge smoke project source: $source" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "$filter" && "$(basename "$source")" != "$filter" ]]; then
|
||||
continue
|
||||
fi
|
||||
found=1
|
||||
printf '%s\n' "$source"
|
||||
done
|
||||
|
||||
if [[ -n "$filter" && "$found" -eq 0 ]]; then
|
||||
echo "missing LinuxCNC bridge smoke project source in list: $filter" >&2
|
||||
exit 1
|
||||
fi
|
||||
./list-project-source-set.sh linuxcnc-bridge-smoke "$filter"
|
||||
|
||||
73
list-linuxcnc-manifest-sources.sh
Executable file
73
list-linuxcnc-manifest-sources.sh
Executable file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
manifest=${1:?manifest required}
|
||||
filter_group=${2:?filter group required}
|
||||
output_mode=${3:?output mode required}
|
||||
allowed_groups=${4:?allowed groups required}
|
||||
duplicate_groups=${5:?duplicate groups required}
|
||||
missing_source_message=${6:?missing source message required}
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
|
||||
contains_group() {
|
||||
local groups=$1
|
||||
local group=$2
|
||||
[[ ",$groups," == *",$group,"* ]]
|
||||
}
|
||||
|
||||
checks_duplicate_group() {
|
||||
local groups=$1
|
||||
local group=$2
|
||||
[[ "$groups" == "all" ]] || contains_group "$groups" "$group"
|
||||
}
|
||||
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "$manifest"
|
||||
|
||||
if [[ "$filter_group" != "all" ]] && ! contains_group "$allowed_groups" "$filter_group"; then
|
||||
echo "unknown manifest source filter: $filter_group" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$output_mode" in
|
||||
relative|full)
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest source output mode: $output_mode" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
seen_sources=()
|
||||
while IFS=: read -r group path note; do
|
||||
case "$group" in
|
||||
""|\#*)
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
|
||||
if ! contains_group "$allowed_groups" "$group"; then
|
||||
echo "unknown manifest group: $group" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
full_path=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh \
|
||||
--missing-message "$missing_source_message" \
|
||||
"$path")
|
||||
if checks_duplicate_group "$duplicate_groups" "$group"; then
|
||||
if printf '%s\n' "${seen_sources[@]}" | grep -Fx -- "$path" >/dev/null; then
|
||||
echo "duplicate manifest source: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
seen_sources+=("$path")
|
||||
fi
|
||||
|
||||
if [[ "$filter_group" == "all" || "$filter_group" == "$group" ]]; then
|
||||
if [[ "$output_mode" == "full" ]]; then
|
||||
printf '%s\n' "$full_path"
|
||||
else
|
||||
printf '%s\n' "$path"
|
||||
fi
|
||||
fi
|
||||
done < "$manifest"
|
||||
12
list-linuxcnc-native-linkflags.sh
Executable file
12
list-linuxcnc-native-linkflags.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
|
||||
printf '%s\n' \
|
||||
-L "$linuxcnc_root/lib" \
|
||||
-Wl,-rpath,"$linuxcnc_root/lib"
|
||||
@@ -5,49 +5,7 @@ cd "$(dirname "$0")"
|
||||
|
||||
filter=${1:-}
|
||||
|
||||
awk '
|
||||
/set\(cnc_sim_core_sources/ {
|
||||
in_core = 1
|
||||
next
|
||||
}
|
||||
in_core && /^[[:space:]]*\)/ {
|
||||
in_core = 0
|
||||
next
|
||||
}
|
||||
/list\(APPEND cnc_sim_core_sources/ {
|
||||
in_backend_sources = 1
|
||||
next
|
||||
}
|
||||
in_backend_sources && /^[[:space:]]*\)/ {
|
||||
in_backend_sources = 0
|
||||
next
|
||||
}
|
||||
in_core || in_backend_sources {
|
||||
line = $0
|
||||
sub(/^[[:space:]]*/, "", line)
|
||||
sub(/[[:space:]]*$/, "", line)
|
||||
if (line == "") {
|
||||
next
|
||||
}
|
||||
print "core/" line
|
||||
}
|
||||
' core/CMakeLists.txt | while IFS= read -r source; do
|
||||
if [[ ! -f "$source" ]]; then
|
||||
echo "missing LinuxCNC rs274 API project source: $source" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "$filter" && "$(basename "$source")" != "$filter" ]]; then
|
||||
continue
|
||||
fi
|
||||
printf '%s\n' "$source"
|
||||
done | {
|
||||
found=0
|
||||
while IFS= read -r source; do
|
||||
found=1
|
||||
printf '%s\n' "$source"
|
||||
done
|
||||
if [[ -n "$filter" && "$found" -eq 0 ]]; then
|
||||
echo "missing LinuxCNC rs274 API project source in CMake list: $filter" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
./list-cmake-set-plus-append-sources.sh cnc_sim_core_sources cnc_sim_core_sources core/ | ./list-filtered-existing-paths.sh \
|
||||
"$filter" \
|
||||
"missing LinuxCNC rs274 API project source" \
|
||||
"missing LinuxCNC rs274 API project source in CMake list"
|
||||
|
||||
@@ -5,29 +5,4 @@ cd "$(dirname "$0")"
|
||||
|
||||
filter=${1:-}
|
||||
|
||||
sources=(
|
||||
core/src/canon_event_sink.cpp
|
||||
core/src/linuxcnc_canon_bridge.cpp
|
||||
core/src/linuxcnc_tooldata_fixture.cpp
|
||||
core/src/rtcp_kinematics.cpp
|
||||
core/src/simulator_gcode_controls.cpp
|
||||
core/tools/linuxcnc_rs274_dump.cpp
|
||||
)
|
||||
|
||||
found=0
|
||||
for source in "${sources[@]}"; do
|
||||
if [[ ! -f "$source" ]]; then
|
||||
echo "missing LinuxCNC rs274 dump project source: $source" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "$filter" && "$(basename "$source")" != "$filter" ]]; then
|
||||
continue
|
||||
fi
|
||||
found=1
|
||||
printf '%s\n' "$source"
|
||||
done
|
||||
|
||||
if [[ -n "$filter" && "$found" -eq 0 ]]; then
|
||||
echo "missing LinuxCNC rs274 dump project source in list: $filter" >&2
|
||||
exit 1
|
||||
fi
|
||||
./list-project-source-set.sh linuxcnc-rs274-dump "$filter"
|
||||
|
||||
67
list-linuxcnc-source-common-cxxflags.sh
Executable file
67
list-linuxcnc-source-common-cxxflags.sh
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
include_python=0
|
||||
include_core_include=0
|
||||
include_core_src=0
|
||||
syntax_only=0
|
||||
emit_ulapi=1
|
||||
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--python)
|
||||
include_python=1
|
||||
shift
|
||||
;;
|
||||
--core-include)
|
||||
include_core_include=1
|
||||
shift
|
||||
;;
|
||||
--core-src)
|
||||
include_core_src=1
|
||||
shift
|
||||
;;
|
||||
--syntax-only)
|
||||
syntax_only=1
|
||||
shift
|
||||
;;
|
||||
--no-ulapi)
|
||||
emit_ulapi=0
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "unknown source cxxflag option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
|
||||
python_includes=()
|
||||
if [[ "$include_python" -eq 1 ]]; then
|
||||
python_include_output=$(python3.13-config --includes 2>/dev/null || python3-config --includes)
|
||||
read -r -a python_includes <<<"$python_include_output"
|
||||
fi
|
||||
|
||||
printf '%s\n' \
|
||||
-std=c++17 \
|
||||
$([[ "$emit_ulapi" -eq 1 ]] && printf '%s\n' -DULAPI) \
|
||||
$([[ "$syntax_only" -eq 1 ]] && printf '%s\n' -fsyntax-only) \
|
||||
"${python_includes[@]}" \
|
||||
$([[ "$include_core_include" -eq 1 ]] && printf '%s\n' -I core/include) \
|
||||
$([[ "$include_core_src" -eq 1 ]] && printf '%s\n' -I core/src) \
|
||||
-I "$linuxcnc_root/src" \
|
||||
-I "$linuxcnc_root/src/emc" \
|
||||
-I "$linuxcnc_root/src/emc/nml_intf" \
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc" \
|
||||
-I "$linuxcnc_root/src/emc/motion" \
|
||||
-I "$linuxcnc_root/src/emc/pythonplugin" \
|
||||
-I "$linuxcnc_root/include"
|
||||
@@ -4,21 +4,43 @@ set -euo pipefail
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
missing_source_message="missing LinuxCNC source"
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--missing-message)
|
||||
if [[ "$#" -lt 2 ]]; then
|
||||
echo "missing --missing-message value" >&2
|
||||
exit 1
|
||||
fi
|
||||
missing_source_message=$2
|
||||
shift 2
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
echo "unknown source file option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "$#" -eq 0 ]]; then
|
||||
echo "usage: $0 <linuxcnc-relative-source>..." >&2
|
||||
echo "usage: $0 [--missing-message <message>] <linuxcnc-relative-source>..." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for source in "$@"; do
|
||||
full_source="$linuxcnc_root/$source"
|
||||
if [[ ! -f "$full_source" ]]; then
|
||||
echo "missing LinuxCNC source: $source" >&2
|
||||
echo "$missing_source_message: $source" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf '%s\n' "$full_source"
|
||||
|
||||
@@ -6,67 +6,11 @@ cd "$(dirname "$0")"
|
||||
manifest=${1:-linuxcnc-rs274-source-files.txt}
|
||||
filter_group=${2:-core}
|
||||
output_mode=${3:-relative}
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$filter_group" in
|
||||
core|binding|tooldata|all)
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest source filter: $filter_group" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$output_mode" in
|
||||
relative|full)
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest source output mode: $output_mode" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
seen_sources=()
|
||||
while IFS=: read -r group path note; do
|
||||
case "$group" in
|
||||
""|\#*)
|
||||
continue
|
||||
;;
|
||||
core|binding|tooldata)
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest group: $group" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ ! -f "$linuxcnc_root/$path" ]]; then
|
||||
echo "missing manifest file: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$group" == "core" ]]; then
|
||||
if printf '%s\n' "${seen_sources[@]}" | grep -Fx -- "$path" >/dev/null; then
|
||||
echo "duplicate manifest source: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
seen_sources+=("$path")
|
||||
fi
|
||||
|
||||
if [[ "$filter_group" == "all" || "$filter_group" == "$group" ]]; then
|
||||
if [[ "$output_mode" == "full" ]]; then
|
||||
printf '%s\n' "$linuxcnc_root/$path"
|
||||
else
|
||||
printf '%s\n' "$path"
|
||||
fi
|
||||
fi
|
||||
done < "$manifest"
|
||||
./list-linuxcnc-manifest-sources.sh \
|
||||
"$manifest" \
|
||||
"$filter_group" \
|
||||
"$output_mode" \
|
||||
core,header,binding,tooldata \
|
||||
core \
|
||||
"missing manifest file"
|
||||
|
||||
@@ -6,10 +6,7 @@ cd "$(dirname "$0")"
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
filter=${1:-}
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
|
||||
objects=(
|
||||
src/objects/emc/rs274ngc/interpmodule.o
|
||||
@@ -24,22 +21,10 @@ objects=(
|
||||
src/objects/libnml/nml/stat_msg.o
|
||||
)
|
||||
|
||||
found=0
|
||||
for object in "${objects[@]}"; do
|
||||
full_object="$linuxcnc_root/$object"
|
||||
if [[ ! -f "$full_object" ]]; then
|
||||
echo "missing LinuxCNC support object: $full_object" >&2
|
||||
echo "build LinuxCNC first or set LINUXCNC_ROOT to a built tree" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "$filter" && "$(basename "$object")" != "$filter" ]]; then
|
||||
continue
|
||||
fi
|
||||
found=1
|
||||
printf '%s\n' "$full_object"
|
||||
done
|
||||
|
||||
if [[ -n "$filter" && "$found" -eq 0 ]]; then
|
||||
echo "missing LinuxCNC support object in list: $filter" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf '%s\n' "$linuxcnc_root/$object"
|
||||
done | ./list-filtered-existing-paths.sh \
|
||||
"$filter" \
|
||||
"missing LinuxCNC support object" \
|
||||
"missing LinuxCNC support object in list" \
|
||||
"build LinuxCNC first or set LINUXCNC_ROOT to a built tree"
|
||||
|
||||
117
list-linuxcnc-wasm-common-cxxflags.sh
Executable file
117
list-linuxcnc-wasm-common-cxxflags.sh
Executable file
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
std_flag=-std=c++17
|
||||
include_core_include=0
|
||||
include_core_src=0
|
||||
include_tooldata=0
|
||||
include_wctype=0
|
||||
syntax_only=0
|
||||
function_sections=0
|
||||
data_sections=0
|
||||
profile=base
|
||||
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--profile)
|
||||
if [[ "$#" -lt 2 ]]; then
|
||||
echo "missing --profile value" >&2
|
||||
exit 1
|
||||
fi
|
||||
profile=$2
|
||||
shift 2
|
||||
;;
|
||||
--std)
|
||||
if [[ "$#" -lt 2 ]]; then
|
||||
echo "missing --std value" >&2
|
||||
exit 1
|
||||
fi
|
||||
std_flag=-std="$2"
|
||||
shift 2
|
||||
;;
|
||||
--core-include)
|
||||
include_core_include=1
|
||||
shift
|
||||
;;
|
||||
--core-src)
|
||||
include_core_src=1
|
||||
shift
|
||||
;;
|
||||
--tooldata-include)
|
||||
include_tooldata=1
|
||||
shift
|
||||
;;
|
||||
--wctype)
|
||||
include_wctype=1
|
||||
shift
|
||||
;;
|
||||
--syntax-only)
|
||||
syntax_only=1
|
||||
shift
|
||||
;;
|
||||
--function-sections)
|
||||
function_sections=1
|
||||
shift
|
||||
;;
|
||||
--data-sections)
|
||||
data_sections=1
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "unknown wasm cxxflag option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$profile" in
|
||||
base|core20|core20-sections)
|
||||
;;
|
||||
*)
|
||||
echo "unknown wasm cxxflag profile: $profile" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$profile" in
|
||||
core20|core20-sections)
|
||||
std_flag=-std=c++20
|
||||
include_core_include=1
|
||||
include_core_src=1
|
||||
include_wctype=1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$profile" in
|
||||
core20-sections)
|
||||
function_sections=1
|
||||
data_sections=1
|
||||
;;
|
||||
esac
|
||||
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
|
||||
printf '%s\n' \
|
||||
"$std_flag" \
|
||||
-DULAPI \
|
||||
$([[ "$syntax_only" -eq 1 ]] && printf '%s\n' -fsyntax-only) \
|
||||
$([[ "$include_wctype" -eq 1 ]] && printf '%s\n' -include wctype.h) \
|
||||
$([[ "$function_sections" -eq 1 ]] && printf '%s\n' -ffunction-sections) \
|
||||
$([[ "$data_sections" -eq 1 ]] && printf '%s\n' -fdata-sections) \
|
||||
$([[ "$include_core_include" -eq 1 ]] && printf '%s\n' -I "$(pwd)/core/include") \
|
||||
$([[ "$include_core_src" -eq 1 ]] && printf '%s\n' -I "$(pwd)/core/src") \
|
||||
$([[ "$include_tooldata" -eq 1 ]] && printf '%s\n' -I "$linuxcnc_root/src/emc/tooldata") \
|
||||
-I "$(pwd)/core/wasm_shims" \
|
||||
-I "$linuxcnc_root/src" \
|
||||
-I "$linuxcnc_root/src/emc" \
|
||||
-I "$linuxcnc_root/src/emc/nml_intf" \
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc" \
|
||||
-I "$linuxcnc_root/src/emc/motion" \
|
||||
-I "$linuxcnc_root/include"
|
||||
@@ -6,65 +6,11 @@ cd "$(dirname "$0")"
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
filter_group=${2:-core}
|
||||
output_mode=${3:-relative}
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$filter_group" in
|
||||
core|blocked|all)
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest source filter: $filter_group" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$output_mode" in
|
||||
relative|full)
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest source output mode: $output_mode" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
seen_sources=()
|
||||
while IFS=: read -r group path note; do
|
||||
case "$group" in
|
||||
""|\#*)
|
||||
continue
|
||||
;;
|
||||
core|blocked)
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest group: $group" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ ! -f "$linuxcnc_root/$path" ]]; then
|
||||
echo "missing manifest source: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
if printf '%s\n' "${seen_sources[@]}" | grep -Fx -- "$path" >/dev/null; then
|
||||
echo "duplicate manifest source: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
seen_sources+=("$path")
|
||||
|
||||
if [[ "$filter_group" == "all" || "$filter_group" == "$group" ]]; then
|
||||
if [[ "$output_mode" == "full" ]]; then
|
||||
printf '%s\n' "$linuxcnc_root/$path"
|
||||
else
|
||||
printf '%s\n' "$path"
|
||||
fi
|
||||
fi
|
||||
done < "$manifest"
|
||||
./list-linuxcnc-manifest-sources.sh \
|
||||
"$manifest" \
|
||||
"$filter_group" \
|
||||
"$output_mode" \
|
||||
core,header,blocked,blocked-header \
|
||||
all \
|
||||
"missing manifest source"
|
||||
|
||||
@@ -5,41 +5,7 @@ cd "$(dirname "$0")"
|
||||
|
||||
filter=${1:-}
|
||||
|
||||
awk '
|
||||
/set\(linuxcnc_rs274_wasm_safe_probe_project_sources/ {
|
||||
in_list = 1
|
||||
next
|
||||
}
|
||||
in_list && /^[[:space:]]*\)/ {
|
||||
exit
|
||||
}
|
||||
in_list {
|
||||
line = $0
|
||||
sub(/^[[:space:]]*/, "", line)
|
||||
sub(/[[:space:]]*$/, "", line)
|
||||
if (line == "") {
|
||||
next
|
||||
}
|
||||
sub(/^\$\{CMAKE_CURRENT_SOURCE_DIR\}\//, "core/", line)
|
||||
print line
|
||||
}
|
||||
' core/CMakeLists.txt | while IFS= read -r source; do
|
||||
if [[ ! -f "$source" ]]; then
|
||||
echo "missing wasm-safe project source: $source" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "$filter" && "$(basename "$source")" != "$filter" ]]; then
|
||||
continue
|
||||
fi
|
||||
printf '%s\n' "$source"
|
||||
done | {
|
||||
found=0
|
||||
while IFS= read -r source; do
|
||||
found=1
|
||||
printf '%s\n' "$source"
|
||||
done
|
||||
if [[ -n "$filter" && "$found" -eq 0 ]]; then
|
||||
echo "missing wasm-safe project source in CMake list: $filter" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
./list-cmake-set-sources.sh linuxcnc_rs274_wasm_safe_probe_project_sources | ./list-filtered-existing-paths.sh \
|
||||
"$filter" \
|
||||
"missing wasm-safe project source" \
|
||||
"missing wasm-safe project source in CMake list"
|
||||
|
||||
@@ -5,41 +5,7 @@ cd "$(dirname "$0")"
|
||||
|
||||
filter=${1:-}
|
||||
|
||||
awk '
|
||||
/set\(linuxcnc_wasm_safe_probe_shims/ {
|
||||
in_list = 1
|
||||
next
|
||||
}
|
||||
in_list && /^[[:space:]]*\)/ {
|
||||
exit
|
||||
}
|
||||
in_list {
|
||||
line = $0
|
||||
sub(/^[[:space:]]*/, "", line)
|
||||
sub(/[[:space:]]*$/, "", line)
|
||||
if (line == "") {
|
||||
next
|
||||
}
|
||||
sub(/^\$\{CMAKE_CURRENT_SOURCE_DIR\}\//, "core/", line)
|
||||
print line
|
||||
}
|
||||
' core/CMakeLists.txt | while IFS= read -r source; do
|
||||
if [[ ! -f "$source" ]]; then
|
||||
echo "missing wasm-safe shim source: $source" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "$filter" && "$(basename "$source")" != "$filter" ]]; then
|
||||
continue
|
||||
fi
|
||||
printf '%s\n' "$source"
|
||||
done | {
|
||||
found=0
|
||||
while IFS= read -r source; do
|
||||
found=1
|
||||
printf '%s\n' "$source"
|
||||
done
|
||||
if [[ -n "$filter" && "$found" -eq 0 ]]; then
|
||||
echo "missing wasm-safe shim in CMake list: $filter" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
./list-cmake-set-sources.sh linuxcnc_wasm_safe_probe_shims | ./list-filtered-existing-paths.sh \
|
||||
"$filter" \
|
||||
"missing wasm-safe shim source" \
|
||||
"missing wasm-safe shim in CMake list"
|
||||
|
||||
45
list-project-source-set.sh
Executable file
45
list-project-source-set.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
if [[ "$#" -lt 1 || "$#" -gt 2 ]]; then
|
||||
echo "usage: $0 <source-set> [filter]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source_set=$1
|
||||
filter=${2:-}
|
||||
|
||||
case "$source_set" in
|
||||
linuxcnc-rs274-dump)
|
||||
sources=(
|
||||
core/src/canon_event_sink.cpp
|
||||
core/src/linuxcnc_canon_bridge.cpp
|
||||
core/src/linuxcnc_tooldata_fixture.cpp
|
||||
core/src/rtcp_kinematics.cpp
|
||||
core/src/simulator_gcode_controls.cpp
|
||||
core/tools/linuxcnc_rs274_dump.cpp
|
||||
)
|
||||
missing_source_message="missing LinuxCNC rs274 dump project source"
|
||||
missing_filter_message="missing LinuxCNC rs274 dump project source in list"
|
||||
;;
|
||||
linuxcnc-bridge-smoke)
|
||||
sources=(
|
||||
core/src/canon_event_sink.cpp
|
||||
core/src/linuxcnc_canon_bridge.cpp
|
||||
core/src/rtcp_kinematics.cpp
|
||||
)
|
||||
missing_source_message="missing LinuxCNC bridge smoke project source"
|
||||
missing_filter_message="missing LinuxCNC bridge smoke project source in list"
|
||||
;;
|
||||
*)
|
||||
echo "unknown project source set: $source_set" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
printf '%s\n' "${sources[@]}" | ./list-filtered-existing-paths.sh \
|
||||
"$filter" \
|
||||
"$missing_source_message" \
|
||||
"$missing_filter_message"
|
||||
@@ -8,12 +8,128 @@ linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
|
||||
missing_root=/tmp/does-not-exist-linuxcnc
|
||||
missing_root_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_missing_root.XXXXXX.log")
|
||||
missing_manifest=${TMPDIR:-/tmp}/cnc_sim_missing_native_manifest.txt
|
||||
missing_manifest_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_native_manifest.XXXXXX.log")
|
||||
unknown_group_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_unknown_manifest_group.XXXXXX.txt")
|
||||
unknown_group_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_unknown_manifest_group.XXXXXX.log")
|
||||
duplicate_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_duplicate_manifest.XXXXXX.txt")
|
||||
duplicate_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_duplicate_manifest.XXXXXX.log")
|
||||
unknown_filter_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_unknown_manifest_filter.XXXXXX.log")
|
||||
unknown_output_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_unknown_manifest_output.XXXXXX.log")
|
||||
missing_dump_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_rs274_dump_project_source.XXXXXX.log")
|
||||
missing_api_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_rs274_api_project_source.XXXXXX.log")
|
||||
missing_core_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_core_source.XXXXXX.log")
|
||||
missing_bridge_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_bridge_smoke_project_source.XXXXXX.log")
|
||||
missing_support_object_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_linuxcnc_support_object.XXXXXX.log")
|
||||
missing_source_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_syntax_missing_source_manifest.XXXXXX.txt")
|
||||
missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_syntax_missing_source.XXXXXX.log")
|
||||
|
||||
cleanup_native_test_temps() {
|
||||
rm -f \
|
||||
"$missing_root_log" \
|
||||
"$missing_manifest" \
|
||||
"$missing_manifest_log" \
|
||||
"$unknown_group_manifest" \
|
||||
"$unknown_group_log" \
|
||||
"$duplicate_manifest" \
|
||||
"$duplicate_log" \
|
||||
"$unknown_filter_log" \
|
||||
"$unknown_output_log" \
|
||||
"$missing_dump_source_log" \
|
||||
"$missing_api_source_log" \
|
||||
"$missing_core_source_log" \
|
||||
"$missing_bridge_source_log" \
|
||||
"$missing_support_object_log" \
|
||||
"$missing_source_manifest" \
|
||||
"$missing_source_log"
|
||||
}
|
||||
trap cleanup_native_test_temps EXIT
|
||||
|
||||
grep -Fx 'trap cleanup_native_test_temps EXIT' test-all-native.sh >/dev/null
|
||||
if ! awk '
|
||||
/cleanup_native_test_temps\(\)/ { in_cleanup = 1 }
|
||||
in_cleanup && index($0, "\"$missing_manifest\"") { found_missing_manifest = 1 }
|
||||
in_cleanup && /^}/ { in_cleanup = 0 }
|
||||
END { exit !found_missing_manifest }
|
||||
' test-all-native.sh; then
|
||||
echo "native aggregate test cleanup no longer removes fixed missing-manifest path" >&2
|
||||
exit 1
|
||||
fi
|
||||
for forbidden_manual_cleanup in \
|
||||
'rm -f "$missing_root_log"' \
|
||||
'rm -f "$missing_manifest_log"' \
|
||||
'rm -f "$unknown_group_manifest" "$unknown_group_log"' \
|
||||
'rm -f "$duplicate_manifest" "$duplicate_log"' \
|
||||
'rm -f "$unknown_filter_log"' \
|
||||
'rm -f "$unknown_output_log"' \
|
||||
'rm -f "$missing_dump_source_log"' \
|
||||
'rm -f "$missing_api_source_log"' \
|
||||
'rm -f "$missing_core_source_log"' \
|
||||
'rm -f "$missing_bridge_source_log"' \
|
||||
'rm -f "$missing_support_object_log"' \
|
||||
'rm -f "$missing_source_manifest" "$missing_source_log"'; do
|
||||
if grep -Fx "$forbidden_manual_cleanup" test-all-native.sh >/dev/null; then
|
||||
echo "native aggregate test still relies on manual cleanup: $forbidden_manual_cleanup" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
grep -F 'exec 9>"${TMPDIR:-/tmp}/cnc_sim_rs274_source_link.lock"' test-linuxcnc-source-link.sh >/dev/null
|
||||
grep -F "flock 9" test-linuxcnc-source-link.sh >/dev/null
|
||||
grep -F "missing LinuxCNC support object:" list-linuxcnc-source-support-objects.sh >/dev/null
|
||||
grep -F "missing LinuxCNC support object" list-linuxcnc-source-support-objects.sh >/dev/null
|
||||
grep -F 'echo "$missing_path_message: $path"' list-filtered-existing-paths.sh >/dev/null
|
||||
grep -F "build LinuxCNC first or set LINUXCNC_ROOT to a built tree" list-linuxcnc-source-support-objects.sh >/dev/null
|
||||
native_link_flags=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-native-linkflags.sh)
|
||||
grep -Fx -- "-L" <<<"$native_link_flags" >/dev/null
|
||||
grep -Fx -- "$linuxcnc_root/lib" <<<"$native_link_flags" >/dev/null
|
||||
grep -Fx -- "-Wl,-rpath,$linuxcnc_root/lib" <<<"$native_link_flags" >/dev/null
|
||||
grep -F 'exec 9>"${TMPDIR:-/tmp}/cnc_sim_linuxcnc_rs274_native.lock"' test-linuxcnc-rs274-native.sh >/dev/null
|
||||
grep -F "flock 9" test-linuxcnc-rs274-native.sh >/dev/null
|
||||
for build_dir_probe_script in \
|
||||
test-linuxcnc-source-objects.sh \
|
||||
test-linuxcnc-source-link.sh \
|
||||
test-linuxcnc-bridge-native.sh \
|
||||
test-linuxcnc-rs274-native.sh \
|
||||
test-linuxcnc-api-native.sh; do
|
||||
if ! awk '
|
||||
index($0, "trap '\''rm -rf \"$build_dir\"'\'' EXIT") { trap_line = NR }
|
||||
index($0, "./check-linuxcnc-inputs.sh") && !check_line { check_line = NR }
|
||||
END { exit !(trap_line && check_line && trap_line < check_line) }
|
||||
' "$build_dir_probe_script"; then
|
||||
echo "$build_dir_probe_script installs build_dir cleanup after input validation" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
grep -F 'python_include_output=$(python3.13-config --includes 2>/dev/null || python3-config --includes)' list-linuxcnc-source-common-cxxflags.sh >/dev/null
|
||||
if grep -F 'read -r -a python_includes <<<"$(' list-linuxcnc-source-common-cxxflags.sh >/dev/null; then
|
||||
echo "source common cxxflags still hides python-config failures behind read" >&2
|
||||
exit 1
|
||||
fi
|
||||
forbidden_common_flags_process_substitution='readarray -t common_flags < <('
|
||||
forbidden_link_flags_process_substitution='readarray -t link_flags < <('
|
||||
forbidden_source_common_flags_helper='./list-linuxcnc-source-common-cxxflags.sh'
|
||||
forbidden_native_link_flags_helper='./list-linuxcnc-native-linkflags.sh'
|
||||
if grep -RInF "${forbidden_common_flags_process_substitution}LINUXCNC_ROOT=\"\$linuxcnc_root\" ${forbidden_source_common_flags_helper}" test-linuxcnc-*.sh >/dev/null; then
|
||||
echo "native probes still read source common flags through process substitution" >&2
|
||||
grep -RInF "${forbidden_common_flags_process_substitution}LINUXCNC_ROOT=\"\$linuxcnc_root\" ${forbidden_source_common_flags_helper}" test-linuxcnc-*.sh >&2
|
||||
exit 1
|
||||
fi
|
||||
if grep -RInF "${forbidden_link_flags_process_substitution}LINUXCNC_ROOT=\"\$linuxcnc_root\" ${forbidden_native_link_flags_helper}" test-linuxcnc-*.sh >/dev/null; then
|
||||
echo "native probes still read link flags through process substitution" >&2
|
||||
grep -RInF "${forbidden_link_flags_process_substitution}LINUXCNC_ROOT=\"\$linuxcnc_root\" ${forbidden_native_link_flags_helper}" test-linuxcnc-*.sh >&2
|
||||
exit 1
|
||||
fi
|
||||
syntax_only_source_common_flags=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-common-cxxflags.sh --syntax-only)
|
||||
grep -Fx -- "-fsyntax-only" <<<"$syntax_only_source_common_flags" >/dev/null
|
||||
core_include_source_common_flags=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-common-cxxflags.sh --core-include)
|
||||
grep -Fx -- "-I" <<<"$core_include_source_common_flags" >/dev/null
|
||||
grep -Fx -- "core/include" <<<"$core_include_source_common_flags" >/dev/null
|
||||
python_source_common_flags=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-common-cxxflags.sh --python)
|
||||
grep -F "include/python" <<<"$python_source_common_flags" >/dev/null
|
||||
no_ulapi_source_common_flags=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-common-cxxflags.sh --no-ulapi)
|
||||
if grep -Fx -- "-DULAPI" <<<"$no_ulapi_source_common_flags" >/dev/null; then
|
||||
echo "source common cxxflags emitted ULAPI with --no-ulapi" >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -F "CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND is native-only; it links LinuxCNC librs274" core/CMakeLists.txt >/dev/null
|
||||
grep -F "Set CNC_SIM_LINUXCNC_ROOT to the LinuxCNC source root" core/CMakeLists.txt >/dev/null
|
||||
grep -F "find_package(Python3 REQUIRED COMPONENTS Development)" core/CMakeLists.txt >/dev/null
|
||||
@@ -34,6 +150,11 @@ grep -F './list-linuxcnc-rs274-api-project-sources.sh > "$project_source_list"'
|
||||
grep -F './list-cnc-sim-core-sources.sh > "$core_source_list"' test-native.sh >/dev/null
|
||||
grep -F './list-linuxcnc-bridge-smoke-project-sources.sh > "$project_source_list"' test-linuxcnc-bridge-native.sh >/dev/null
|
||||
grep -F 'LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-support-objects.sh > "$support_object_list"' test-linuxcnc-source-link.sh >/dev/null
|
||||
grep -F 'trap '\''rm -f "$source_list" "$missing_source_manifest" "$missing_source_log"'\'' EXIT' test-linuxcnc-source-syntax.sh >/dev/null
|
||||
if grep -F 'rm -f "$missing_source_manifest" "$missing_source_log"' test-linuxcnc-source-syntax.sh >/dev/null; then
|
||||
echo "linuxcnc source syntax probe still relies on manual cleanup for missing-source temporaries" >&2
|
||||
exit 1
|
||||
fi
|
||||
for script in \
|
||||
test-linuxcnc-source-syntax.sh \
|
||||
test-linuxcnc-source-objects.sh \
|
||||
@@ -51,10 +172,7 @@ for script in \
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
rm -f "$missing_root_log"
|
||||
|
||||
missing_manifest=${TMPDIR:-/tmp}/cnc_sim_missing_native_manifest.txt
|
||||
missing_manifest_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_native_manifest.XXXXXX.log")
|
||||
rm -f "$missing_manifest"
|
||||
for script in \
|
||||
list-linuxcnc-source-manifest-sources.sh \
|
||||
@@ -71,10 +189,7 @@ for script in \
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
rm -f "$missing_manifest_log"
|
||||
|
||||
unknown_group_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_unknown_manifest_group.XXXXXX.txt")
|
||||
unknown_group_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_unknown_manifest_group.XXXXXX.log")
|
||||
printf 'bogus:src/emc/rs274ngc/interp_arc.cc:test unknown group\n' >"$unknown_group_manifest"
|
||||
for script in \
|
||||
list-linuxcnc-source-manifest-sources.sh \
|
||||
@@ -91,10 +206,7 @@ for script in \
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
rm -f "$unknown_group_manifest" "$unknown_group_log"
|
||||
|
||||
duplicate_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_duplicate_manifest.XXXXXX.txt")
|
||||
duplicate_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_duplicate_manifest.XXXXXX.log")
|
||||
printf 'core:src/emc/rs274ngc/interp_arc.cc:test duplicate source\ncore:src/emc/rs274ngc/interp_arc.cc:test duplicate source\n' >"$duplicate_manifest"
|
||||
for script in \
|
||||
list-linuxcnc-source-manifest-sources.sh \
|
||||
@@ -111,16 +223,20 @@ for script in \
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
rm -f "$duplicate_manifest" "$duplicate_log"
|
||||
|
||||
./list-linuxcnc-source-manifest-sources.sh "$manifest" core >/dev/null
|
||||
grep -Fx "src/emc/rs274ngc/interp_arc.cc" \
|
||||
< <(./list-linuxcnc-source-manifest-sources.sh "$manifest" core) >/dev/null
|
||||
grep -Fx "src/emc/rs274ngc/interpmodule.cc" \
|
||||
< <(./list-linuxcnc-source-manifest-sources.sh "$manifest" binding) >/dev/null
|
||||
grep -Fx "src/emc/tooldata/tooldata_common.cc" \
|
||||
< <(./list-linuxcnc-source-manifest-sources.sh "$manifest" tooldata) >/dev/null
|
||||
unknown_filter_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_unknown_manifest_filter.XXXXXX.log")
|
||||
native_manifest_core=$(./list-linuxcnc-source-manifest-sources.sh "$manifest" core)
|
||||
grep -Fx "src/emc/rs274ngc/interp_arc.cc" <<<"$native_manifest_core" >/dev/null
|
||||
native_manifest_binding=$(./list-linuxcnc-source-manifest-sources.sh "$manifest" binding)
|
||||
grep -Fx "src/emc/rs274ngc/interpmodule.cc" <<<"$native_manifest_binding" >/dev/null
|
||||
native_manifest_tooldata=$(./list-linuxcnc-source-manifest-sources.sh "$manifest" tooldata)
|
||||
grep -Fx "src/emc/tooldata/tooldata_common.cc" <<<"$native_manifest_tooldata" >/dev/null
|
||||
native_manifest_header=$(./list-linuxcnc-source-manifest-sources.sh "$manifest" header)
|
||||
grep -Fx "src/emc/rs274ngc/rs274ngc_interp.hh" <<<"$native_manifest_header" >/dev/null
|
||||
if grep -E '\.(hh|h)$' <<<"$native_manifest_core" >/dev/null; then
|
||||
echo "native manifest core compile group includes headers" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ./list-linuxcnc-source-manifest-sources.sh "$manifest" bogus >"$unknown_filter_log" 2>&1; then
|
||||
echo "native manifest source lister accepted unknown filter" >&2
|
||||
exit 1
|
||||
@@ -130,8 +246,6 @@ if ! grep -F "unknown manifest source filter: bogus" "$unknown_filter_log" >/dev
|
||||
sed -n '1,20p' "$unknown_filter_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$unknown_filter_log"
|
||||
unknown_output_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_unknown_manifest_output.XXXXXX.log")
|
||||
if ./list-linuxcnc-source-manifest-sources.sh "$manifest" core bogus >"$unknown_output_log" 2>&1; then
|
||||
echo "native manifest source lister accepted unknown output mode" >&2
|
||||
exit 1
|
||||
@@ -141,14 +255,12 @@ if ! grep -F "unknown manifest source output mode: bogus" "$unknown_output_log"
|
||||
sed -n '1,20p' "$unknown_output_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$unknown_output_log"
|
||||
grep -Fx "$linuxcnc_root/src/emc/rs274ngc/interp_arc.cc" \
|
||||
< <(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-manifest-sources.sh "$manifest" core full) >/dev/null
|
||||
native_manifest_core_full=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-manifest-sources.sh "$manifest" core full)
|
||||
grep -Fx "$linuxcnc_root/src/emc/rs274ngc/interp_arc.cc" <<<"$native_manifest_core_full" >/dev/null
|
||||
|
||||
./list-linuxcnc-rs274-dump-project-sources.sh >/dev/null
|
||||
grep -Fx "core/tools/linuxcnc_rs274_dump.cpp" \
|
||||
< <(./list-linuxcnc-rs274-dump-project-sources.sh linuxcnc_rs274_dump.cpp) >/dev/null
|
||||
missing_dump_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_rs274_dump_project_source.XXXXXX.log")
|
||||
rs274_dump_source=$(./list-linuxcnc-rs274-dump-project-sources.sh linuxcnc_rs274_dump.cpp)
|
||||
grep -Fx "core/tools/linuxcnc_rs274_dump.cpp" <<<"$rs274_dump_source" >/dev/null
|
||||
if ./list-linuxcnc-rs274-dump-project-sources.sh does_not_exist.cc >"$missing_dump_source_log" 2>&1; then
|
||||
echo "rs274 dump project source lister accepted missing source filter" >&2
|
||||
exit 1
|
||||
@@ -158,12 +270,10 @@ if ! grep -F "missing LinuxCNC rs274 dump project source in list: does_not_exist
|
||||
sed -n '1,20p' "$missing_dump_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_dump_source_log"
|
||||
|
||||
./list-linuxcnc-rs274-api-project-sources.sh >/dev/null
|
||||
grep -Fx "core/src/linuxcnc_rs274_backend.cpp" \
|
||||
< <(./list-linuxcnc-rs274-api-project-sources.sh linuxcnc_rs274_backend.cpp) >/dev/null
|
||||
missing_api_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_rs274_api_project_source.XXXXXX.log")
|
||||
rs274_api_source=$(./list-linuxcnc-rs274-api-project-sources.sh linuxcnc_rs274_backend.cpp)
|
||||
grep -Fx "core/src/linuxcnc_rs274_backend.cpp" <<<"$rs274_api_source" >/dev/null
|
||||
if ./list-linuxcnc-rs274-api-project-sources.sh does_not_exist.cc >"$missing_api_source_log" 2>&1; then
|
||||
echo "rs274 API project source lister accepted missing source filter" >&2
|
||||
exit 1
|
||||
@@ -173,12 +283,10 @@ if ! grep -F "missing LinuxCNC rs274 API project source in CMake list: does_not_
|
||||
sed -n '1,20p' "$missing_api_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_api_source_log"
|
||||
|
||||
./list-cnc-sim-core-sources.sh >/dev/null
|
||||
grep -Fx "core/src/smoke_gcode_parser.cpp" \
|
||||
< <(./list-cnc-sim-core-sources.sh smoke_gcode_parser.cpp) >/dev/null
|
||||
missing_core_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_core_source.XXXXXX.log")
|
||||
cnc_sim_core_source=$(./list-cnc-sim-core-sources.sh smoke_gcode_parser.cpp)
|
||||
grep -Fx "core/src/smoke_gcode_parser.cpp" <<<"$cnc_sim_core_source" >/dev/null
|
||||
if ./list-cnc-sim-core-sources.sh does_not_exist.cc >"$missing_core_source_log" 2>&1; then
|
||||
echo "cnc sim core source lister accepted missing source filter" >&2
|
||||
exit 1
|
||||
@@ -188,12 +296,10 @@ if ! grep -F "missing cnc sim core source in CMake list: does_not_exist.cc" "$mi
|
||||
sed -n '1,20p' "$missing_core_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_core_source_log"
|
||||
|
||||
./list-linuxcnc-bridge-smoke-project-sources.sh >/dev/null
|
||||
grep -Fx "core/src/linuxcnc_canon_bridge.cpp" \
|
||||
< <(./list-linuxcnc-bridge-smoke-project-sources.sh linuxcnc_canon_bridge.cpp) >/dev/null
|
||||
missing_bridge_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_bridge_smoke_project_source.XXXXXX.log")
|
||||
bridge_smoke_source=$(./list-linuxcnc-bridge-smoke-project-sources.sh linuxcnc_canon_bridge.cpp)
|
||||
grep -Fx "core/src/linuxcnc_canon_bridge.cpp" <<<"$bridge_smoke_source" >/dev/null
|
||||
if ./list-linuxcnc-bridge-smoke-project-sources.sh does_not_exist.cc >"$missing_bridge_source_log" 2>&1; then
|
||||
echo "LinuxCNC bridge smoke project source lister accepted missing source filter" >&2
|
||||
exit 1
|
||||
@@ -203,12 +309,10 @@ if ! grep -F "missing LinuxCNC bridge smoke project source in list: does_not_exi
|
||||
sed -n '1,20p' "$missing_bridge_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_bridge_source_log"
|
||||
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-support-objects.sh >/dev/null
|
||||
grep -F "/src/objects/emc/rs274ngc/interpmodule.o" \
|
||||
< <(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-support-objects.sh interpmodule.o) >/dev/null
|
||||
missing_support_object_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_linuxcnc_support_object.XXXXXX.log")
|
||||
interpmodule_support_object=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-support-objects.sh interpmodule.o)
|
||||
grep -F "/src/objects/emc/rs274ngc/interpmodule.o" <<<"$interpmodule_support_object" >/dev/null
|
||||
if LINUXCNC_ROOT="$missing_root" ./list-linuxcnc-source-support-objects.sh >"$missing_support_object_log" 2>&1; then
|
||||
echo "LinuxCNC support object lister accepted missing LinuxCNC root: $missing_root" >&2
|
||||
exit 1
|
||||
@@ -227,10 +331,7 @@ if ! grep -F "missing LinuxCNC support object in list: does_not_exist.o" "$missi
|
||||
sed -n '1,20p' "$missing_support_object_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_support_object_log"
|
||||
|
||||
missing_source_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_syntax_missing_source_manifest.XXXXXX.txt")
|
||||
missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_syntax_missing_source.XXXXXX.log")
|
||||
printf 'core:src/emc/rs274ngc/does_not_exist.cc:test missing source\n' >"$missing_source_manifest"
|
||||
if ./test-linuxcnc-source-syntax.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then
|
||||
echo "test-linuxcnc-source-syntax.sh accepted missing manifest file" >&2
|
||||
@@ -241,7 +342,6 @@ if ! grep -F "missing manifest file: src/emc/rs274ngc/does_not_exist.cc" "$missi
|
||||
sed -n '1,20p' "$missing_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_source_manifest" "$missing_source_log"
|
||||
|
||||
./test-native.sh
|
||||
./test-linuxcnc-source-syntax.sh "$manifest"
|
||||
|
||||
@@ -7,12 +7,8 @@ linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_native.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
var_file="$build_dir/rs274ngc-api.var"
|
||||
cp "$linuxcnc_root/tests/halui/jogging/sim.var" "$var_file"
|
||||
|
||||
@@ -20,21 +16,22 @@ project_source_list="$build_dir/linuxcnc_rs274_api_project_sources.txt"
|
||||
./list-linuxcnc-rs274-api-project-sources.sh > "$project_source_list"
|
||||
mapfile -t project_sources < "$project_source_list"
|
||||
|
||||
"$cxx" -std=c++17 \
|
||||
common_flag_output=$(
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-common-cxxflags.sh \
|
||||
--no-ulapi \
|
||||
--python \
|
||||
--core-include \
|
||||
--core-src
|
||||
)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
link_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-native-linkflags.sh)
|
||||
mapfile -t link_flags <<<"$link_flag_output"
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-DCNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND \
|
||||
$(python3.13-config --includes 2>/dev/null || python3-config --includes) \
|
||||
-I core/include \
|
||||
-I core/src \
|
||||
-I "$linuxcnc_root/src" \
|
||||
-I "$linuxcnc_root/src/emc" \
|
||||
-I "$linuxcnc_root/src/emc/nml_intf" \
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc" \
|
||||
-I "$linuxcnc_root/src/emc/motion" \
|
||||
-I "$linuxcnc_root/include" \
|
||||
"${project_sources[@]}" \
|
||||
core/tests/cnc_sim_api_linuxcnc_rs274_smoke.cpp \
|
||||
-L "$linuxcnc_root/lib" \
|
||||
-Wl,-rpath,"$linuxcnc_root/lib" \
|
||||
"${link_flags[@]}" \
|
||||
-lrs274 \
|
||||
-ltooldata \
|
||||
-lpython3.13 \
|
||||
|
||||
@@ -7,29 +7,26 @@ linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_native.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
project_source_list="$build_dir/linuxcnc_bridge_smoke_project_sources.txt"
|
||||
./list-linuxcnc-bridge-smoke-project-sources.sh > "$project_source_list"
|
||||
mapfile -t project_sources < "$project_source_list"
|
||||
|
||||
"$cxx" -std=c++17 \
|
||||
-I core/include \
|
||||
-I core/src \
|
||||
-I "$linuxcnc_root/src/emc" \
|
||||
-I "$linuxcnc_root/src/emc/nml_intf" \
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc" \
|
||||
-I "$linuxcnc_root/src/emc/motion" \
|
||||
-I "$linuxcnc_root/src" \
|
||||
-I "$linuxcnc_root/include" \
|
||||
common_flag_output=$(
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-common-cxxflags.sh \
|
||||
--no-ulapi \
|
||||
--core-include \
|
||||
--core-src
|
||||
)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
link_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-native-linkflags.sh)
|
||||
mapfile -t link_flags <<<"$link_flag_output"
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
"${project_sources[@]}" \
|
||||
core/tests/linuxcnc_canon_bridge_smoke.cpp \
|
||||
-L "$linuxcnc_root/lib" \
|
||||
-Wl,-rpath,"$linuxcnc_root/lib" \
|
||||
"${link_flags[@]}" \
|
||||
-ltooldata \
|
||||
-o "$build_dir/linuxcnc_canon_bridge_smoke"
|
||||
|
||||
|
||||
@@ -7,12 +7,8 @@ linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_native.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
# The LinuxCNC rs274 backend path can bus-error when two dumps run concurrently.
|
||||
exec 9>"${TMPDIR:-/tmp}/cnc_sim_linuxcnc_rs274_native.lock"
|
||||
flock 9
|
||||
@@ -29,19 +25,20 @@ project_source_list="$build_dir/linuxcnc_rs274_dump_project_sources.txt"
|
||||
./list-linuxcnc-rs274-dump-project-sources.sh > "$project_source_list"
|
||||
mapfile -t project_sources < "$project_source_list"
|
||||
|
||||
"$cxx" -std=c++17 \
|
||||
$(python3.13-config --includes 2>/dev/null || python3-config --includes) \
|
||||
-I core/include \
|
||||
-I core/src \
|
||||
-I "$linuxcnc_root/src" \
|
||||
-I "$linuxcnc_root/src/emc" \
|
||||
-I "$linuxcnc_root/src/emc/nml_intf" \
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc" \
|
||||
-I "$linuxcnc_root/src/emc/motion" \
|
||||
-I "$linuxcnc_root/include" \
|
||||
common_flag_output=$(
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-common-cxxflags.sh \
|
||||
--no-ulapi \
|
||||
--python \
|
||||
--core-include \
|
||||
--core-src
|
||||
)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
link_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-native-linkflags.sh)
|
||||
mapfile -t link_flags <<<"$link_flag_output"
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
"${project_sources[@]}" \
|
||||
-L "$linuxcnc_root/lib" \
|
||||
-Wl,-rpath,"$linuxcnc_root/lib" \
|
||||
"${link_flags[@]}" \
|
||||
-lrs274 \
|
||||
-ltooldata \
|
||||
-lpython3.13 \
|
||||
@@ -126,7 +123,7 @@ check(OUTPUT_DIR / "cnc_sim_linuxcnc_basic_mill.json", required_motion | {"tool-
|
||||
|
||||
controls = load("cnc_sim_linuxcnc_rtcp_controls.json")
|
||||
kin = [event for event in controls if event["type"] == "kinematics-switch"]
|
||||
if [(event["reserved"], event["feed"]) for event in kin] != [(1, 1), (0, 0), (2, 1)]:
|
||||
if [event["reserved"] for event in kin] != [1, 0, 2]:
|
||||
raise SystemExit("unexpected kinematics switch sequence")
|
||||
rtcp = [event for event in controls if event["type"] == "rtcp-state"]
|
||||
if [(event["line"], event["tool"], event["feed"]) for event in rtcp] != [(3, 0, 0), (4, 7, 1)]:
|
||||
|
||||
@@ -6,43 +6,26 @@ cd "$(dirname "$0")"
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_rs274_source_link.XXXXXX")
|
||||
python_includes=$(python3.13-config --includes 2>/dev/null || python3-config --includes)
|
||||
manifest=${1:-linuxcnc-rs274-source-files.txt}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "$manifest"
|
||||
# The LinuxCNC source-linked dump path is not concurrency-safe under parallel execution.
|
||||
exec 9>"${TMPDIR:-/tmp}/cnc_sim_rs274_source_link.lock"
|
||||
flock 9
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
$python_includes
|
||||
-I core/include
|
||||
-I core/src
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/src/emc/pythonplugin"
|
||||
-I "$linuxcnc_root/include"
|
||||
common_flag_output=$(
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-common-cxxflags.sh \
|
||||
--python \
|
||||
--core-include \
|
||||
--core-src
|
||||
)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
link_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-native-linkflags.sh)
|
||||
mapfile -t link_flags <<<"$link_flag_output"
|
||||
|
||||
linuxcnc_sources=()
|
||||
source_list="$build_dir/linuxcnc_core_sources.txt"
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-manifest-sources.sh "$manifest" core full > "$source_list"
|
||||
mapfile -t linuxcnc_sources < "$source_list"
|
||||
source_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-manifest-sources.sh "$manifest" core full)
|
||||
mapfile -t linuxcnc_sources <<<"$source_output"
|
||||
|
||||
objects=()
|
||||
linuxcnc_index=0
|
||||
@@ -73,8 +56,7 @@ LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-support-objects.sh > "$sup
|
||||
mapfile -t support_objects < "$support_object_list"
|
||||
|
||||
"$cxx" "${objects[@]}" "${support_objects[@]}" \
|
||||
-L "$linuxcnc_root/lib" \
|
||||
-Wl,-rpath,"$linuxcnc_root/lib" \
|
||||
"${link_flags[@]}" \
|
||||
-llinuxcnc-uspace-posix \
|
||||
-llinuxcncini \
|
||||
-llinuxcnchal \
|
||||
@@ -812,7 +794,7 @@ if not any(
|
||||
|
||||
controls = json.loads((OUTPUT_DIR / "cnc_sim_linuxcnc_source_rtcp_controls.json").read_text())
|
||||
kin = [event for event in controls if event["type"] == "kinematics-switch"]
|
||||
if [(event["reserved"], event["feed"]) for event in kin] != [(1, 1), (0, 0), (2, 1)]:
|
||||
if [event["reserved"] for event in kin] != [1, 0, 2]:
|
||||
raise SystemExit("unexpected source-linked kinematics switch sequence")
|
||||
rtcp = [event for event in controls if event["type"] == "rtcp-state"]
|
||||
if [(event["line"], event["tool"], event["feed"]) for event in rtcp] != [(3, 0, 0), (4, 7, 1)]:
|
||||
|
||||
@@ -6,43 +6,21 @@ cd "$(dirname "$0")"
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_rs274_objects.XXXXXX")
|
||||
python_includes=$(python3.13-config --includes 2>/dev/null || python3-config --includes)
|
||||
manifest=${1:-linuxcnc-rs274-source-files.txt}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "$manifest"
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/src/emc/pythonplugin"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-common-cxxflags.sh --python)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
sources=()
|
||||
source_list="$build_dir/linuxcnc_core_sources.txt"
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-manifest-sources.sh "$manifest" core full > "$source_list"
|
||||
mapfile -t sources < "$source_list"
|
||||
source_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-manifest-sources.sh "$manifest" core full)
|
||||
mapfile -t sources <<<"$source_output"
|
||||
|
||||
source_index=0
|
||||
for source in "${sources[@]}"; do
|
||||
obj="$build_dir/linuxcnc_${source_index}.o"
|
||||
# shellcheck disable=SC2086
|
||||
"$cxx" "${common_flags[@]}" $python_includes -c "$source" -o "$obj"
|
||||
"$cxx" "${common_flags[@]}" -c "$source" -o "$obj"
|
||||
source_index=$((source_index + 1))
|
||||
done
|
||||
|
||||
|
||||
@@ -5,25 +5,21 @@ cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
python_includes=$(python3.13-config --includes 2>/dev/null || python3-config --includes)
|
||||
manifest=${1:-linuxcnc-rs274-source-files.txt}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source_list=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_source_syntax_sources.XXXXXX.txt")
|
||||
trap 'rm -f "$source_list"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-manifest-sources.sh "$manifest" all full > "$source_list"
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "$manifest"
|
||||
|
||||
missing_source_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_rs274_manifest_source.XXXXXX.txt")
|
||||
missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_rs274_manifest_source.XXXXXX.log")
|
||||
source_list=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_source_syntax_sources.XXXXXX.txt")
|
||||
trap 'rm -f "$source_list" "$missing_source_manifest" "$missing_source_log"' EXIT
|
||||
grep -Fx 'trap '\''rm -f "$source_list" "$missing_source_manifest" "$missing_source_log"'\'' EXIT' test-linuxcnc-source-syntax.sh >/dev/null
|
||||
if awk '/^rm -f "\$missing_source_manifest" "\$missing_source_log"$/{ found = 1 } END { exit !found }' test-linuxcnc-source-syntax.sh >/dev/null; then
|
||||
echo "linuxcnc source syntax probe still relies on manual cleanup for missing-source temporaries" >&2
|
||||
exit 1
|
||||
fi
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-manifest-sources.sh "$manifest" all full > "$source_list"
|
||||
|
||||
printf 'core:src/emc/rs274ngc/does_not_exist.cc:test missing source\n' >"$missing_source_manifest"
|
||||
if ./test-linuxcnc-source-objects.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then
|
||||
echo "linuxcnc source object probe accepted missing manifest file" >&2
|
||||
@@ -43,25 +39,13 @@ if ! grep -F "missing manifest file: src/emc/rs274ngc/does_not_exist.cc" "$missi
|
||||
sed -n '1,20p' "$missing_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_source_manifest" "$missing_source_log"
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-fsyntax-only
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/src/emc/pythonplugin"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-common-cxxflags.sh --python --syntax-only)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
while IFS= read -r source; do
|
||||
[[ -z "$source" ]] && continue
|
||||
# shellcheck disable=SC2086
|
||||
"$cxx" "${common_flags[@]}" $python_includes "$source"
|
||||
"$cxx" "${common_flags[@]}" "$source"
|
||||
done < "$source_list"
|
||||
|
||||
echo "linuxcnc rs274 source syntax probe passed"
|
||||
|
||||
@@ -7,6 +7,26 @@ manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
|
||||
missing_manifest=${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocker_manifest.txt
|
||||
missing_manifest_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocker_manifest.XXXXXX.log")
|
||||
missing_root_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_wasm_blocker_missing_root.XXXXXX.log")
|
||||
missing_source_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocker_manifest_source.XXXXXX.txt")
|
||||
missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocker_manifest_source.XXXXXX.log")
|
||||
duplicate_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_blocker_manifest.XXXXXX.txt")
|
||||
duplicate_manifest_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_blocker_manifest.XXXXXX.log")
|
||||
missing_replacement_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocked_replacement.XXXXXX.txt")
|
||||
missing_replacement_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocked_replacement.XXXXXX.log")
|
||||
trap 'rm -f "$missing_manifest" "$missing_manifest_log" "$missing_root_log" "$missing_source_manifest" "$missing_source_log" "$duplicate_manifest" "$duplicate_manifest_log" "$missing_replacement_manifest" "$missing_replacement_log"' EXIT
|
||||
if ! awk '
|
||||
/^trap '\''rm -f "\$missing_manifest" "\$missing_manifest_log" "\$missing_root_log" "\$missing_source_manifest" "\$missing_source_log" "\$duplicate_manifest" "\$duplicate_manifest_log" "\$missing_replacement_manifest" "\$missing_replacement_log"'\'' EXIT$/ { found_trap = 1 }
|
||||
END { exit !found_trap }
|
||||
' test-linuxcnc-wasm-blockers.sh; then
|
||||
echo "wasm blocker scan cleanup trap no longer covers fixed blocker temporaries" >&2
|
||||
exit 1
|
||||
fi
|
||||
if awk '/^rm -f "\$missing_source_manifest" "\$missing_source_log"$/{ found = 1 } END { exit !found }' test-linuxcnc-wasm-blockers.sh >/dev/null; then
|
||||
echo "wasm blocker scan still relies on manual cleanup for missing-source temporaries" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f "$missing_manifest"
|
||||
if ./analyze-linuxcnc-wasm-blockers.sh "$missing_manifest" >"$missing_manifest_log" 2>&1; then
|
||||
echo "wasm blocker analyzer accepted missing manifest: $missing_manifest" >&2
|
||||
@@ -17,10 +37,8 @@ if ! grep -F "missing manifest: $missing_manifest" "$missing_manifest_log" >/dev
|
||||
sed -n '1,20p' "$missing_manifest_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_manifest_log"
|
||||
|
||||
missing_root=/tmp/does-not-exist-linuxcnc
|
||||
missing_root_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_wasm_blocker_missing_root.XXXXXX.log")
|
||||
if LINUXCNC_ROOT="$missing_root" ./analyze-linuxcnc-wasm-blockers.sh "$manifest" >"$missing_root_log" 2>&1; then
|
||||
echo "wasm blocker analyzer accepted missing LinuxCNC root" >&2
|
||||
exit 1
|
||||
@@ -30,12 +48,9 @@ if ! grep -F "missing LinuxCNC root: $missing_root" "$missing_root_log" >/dev/nu
|
||||
sed -n '1,20p' "$missing_root_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_root_log"
|
||||
|
||||
output=$(./analyze-linuxcnc-wasm-blockers.sh "$manifest")
|
||||
|
||||
missing_source_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocker_manifest_source.XXXXXX.txt")
|
||||
missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocker_manifest_source.XXXXXX.log")
|
||||
printf 'blocked:src/emc/tooldata/does_not_exist.cc:test missing blocked source\n' >"$missing_source_manifest"
|
||||
if ./analyze-linuxcnc-wasm-blockers.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then
|
||||
echo "wasm blocker analyzer accepted missing manifest source" >&2
|
||||
@@ -46,10 +61,7 @@ if ! grep -F "missing manifest source: src/emc/tooldata/does_not_exist.cc" "$mis
|
||||
sed -n '1,20p' "$missing_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_source_manifest" "$missing_source_log"
|
||||
|
||||
duplicate_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_blocker_manifest.XXXXXX.txt")
|
||||
duplicate_manifest_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_blocker_manifest.XXXXXX.log")
|
||||
cat >"$duplicate_manifest" <<'EOF'
|
||||
core:src/emc/rs274ngc/interp_arc.cc:duplicate core entry
|
||||
core:src/emc/rs274ngc/interp_arc.cc:duplicate core entry
|
||||
@@ -64,10 +76,7 @@ if ! grep -F "duplicate manifest source: src/emc/rs274ngc/interp_arc.cc" "$dupli
|
||||
sed -n '1,20p' "$duplicate_manifest_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$duplicate_manifest" "$duplicate_manifest_log"
|
||||
|
||||
missing_replacement_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocked_replacement.XXXXXX.txt")
|
||||
missing_replacement_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocked_replacement.XXXXXX.log")
|
||||
cat >"$missing_replacement_manifest" <<'EOF'
|
||||
core:src/emc/rs274ngc/interp_arc.cc:core entry
|
||||
blocked:src/emc/tooldata/tooldata_db.cc:blocked entry without wasm replacement
|
||||
@@ -81,7 +90,6 @@ if ! grep -F "missing blocked replacement mapping: src/emc/tooldata/tooldata_db.
|
||||
sed -n '1,20p' "$missing_replacement_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_replacement_manifest" "$missing_replacement_log"
|
||||
|
||||
grep -F "[manifest]" <<<"$output" >/dev/null
|
||||
grep -F "core=25" <<<"$(sed -n '/^\[manifest\]/,/^$/p' <<<"$output")" >/dev/null
|
||||
|
||||
@@ -6,20 +6,61 @@ cd "$(dirname "$0")"
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_cmake_safe_probe.XXXXXX")
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
missing_manifest=${TMPDIR:-/tmp}/cnc_sim_missing_build_wasm_manifest.txt
|
||||
missing_manifest_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_build_wasm_manifest.XXXXXX.log")
|
||||
missing_root=/tmp/does-not-exist-linuxcnc
|
||||
missing_root_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_build_wasm_missing_root.XXXXXX.log")
|
||||
|
||||
cleanup_wasm_cmake_probe_temps() {
|
||||
local temp_path
|
||||
for temp_path in \
|
||||
"$build_dir" \
|
||||
"$missing_manifest" \
|
||||
"$missing_manifest_log" \
|
||||
"$missing_root_log" \
|
||||
"${unknown_manifest_filter_log:-}" \
|
||||
"${unknown_manifest_output_log:-}" \
|
||||
"${missing_shim_log:-}" \
|
||||
"${missing_project_source_log:-}" \
|
||||
"${missing_wasm_script_manifest:-}" \
|
||||
"${missing_wasm_script_manifest_log:-}" \
|
||||
"${missing_source_root:-}" \
|
||||
"${missing_source_log:-}" \
|
||||
"${missing_interp_find_root:-}" \
|
||||
"${missing_interp_find_log:-}" \
|
||||
"${missing_tooldata_runtime_root:-}" \
|
||||
"${missing_tooldata_runtime_log:-}" \
|
||||
"${unknown_group_manifest:-}" \
|
||||
"${unknown_group_log:-}" \
|
||||
"${blocker_scan_log:-}" \
|
||||
"${blocker_report_file:-}" \
|
||||
"${missing_source_manifest:-}" \
|
||||
"${empty_partition_log:-}" \
|
||||
"${empty_core_manifest:-}" \
|
||||
"${empty_blocked_manifest:-}" \
|
||||
"${bad_default_manifest_dir:-}" \
|
||||
"${bad_default_manifest_log:-}" \
|
||||
"${duplicate_manifest:-}" \
|
||||
"${duplicate_manifest_log:-}" \
|
||||
"${comment_manifest:-}" \
|
||||
"${comment_manifest_log:-}" \
|
||||
"${duplicate_source_manifest:-}" \
|
||||
"${duplicate_source_log:-}" \
|
||||
"${duplicate_syntax_manifest:-}" \
|
||||
"${duplicate_syntax_log:-}" \
|
||||
"${duplicate_pre_blocker_manifest:-}" \
|
||||
"${duplicate_pre_blocker_log:-}" \
|
||||
"${duplicate_pre_link_manifest:-}" \
|
||||
"${duplicate_pre_link_log:-}"; do
|
||||
if [[ -n "$temp_path" ]]; then
|
||||
rm -rf "$temp_path"
|
||||
fi
|
||||
done
|
||||
}
|
||||
trap cleanup_wasm_cmake_probe_temps EXIT
|
||||
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "$manifest"
|
||||
|
||||
rm -f "$missing_manifest"
|
||||
if ./build-wasm.sh "$missing_manifest" >"$missing_manifest_log" 2>&1; then
|
||||
echo "build-wasm accepted missing manifest: $missing_manifest" >&2
|
||||
@@ -30,10 +71,7 @@ if ! grep -F "missing manifest: $missing_manifest" "$missing_manifest_log" >/dev
|
||||
sed -n '1,20p' "$missing_manifest_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_manifest_log"
|
||||
|
||||
missing_root=/tmp/does-not-exist-linuxcnc
|
||||
missing_root_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_build_wasm_missing_root.XXXXXX.log")
|
||||
if LINUXCNC_ROOT="$missing_root" ./build-wasm.sh >"$missing_root_log" 2>&1; then
|
||||
echo "build-wasm accepted missing LinuxCNC root: $missing_root" >&2
|
||||
exit 1
|
||||
@@ -59,21 +97,135 @@ grep -F -- './test-linuxcnc-wasm-python-plugin-link.sh' build-wasm.sh >/dev/null
|
||||
grep -F -- './test-linuxcnc-wasm-rs274ngc-pre-object.sh' build-wasm.sh >/dev/null
|
||||
grep -F -- './test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh "$manifest"' build-wasm.sh >/dev/null
|
||||
grep -F -- './test-linuxcnc-wasm-rs274ngc-pre-link.sh "$manifest"' build-wasm.sh >/dev/null
|
||||
if grep -F '} > "$report_file" || true' test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh >/dev/null; then
|
||||
echo "rs274ngc_pre blocker scan still hides report pipeline failures with || true" >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -Fx 'keep_report_file=0' test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh >/dev/null
|
||||
grep -Fx 'trap cleanup_rs274ngc_pre_blocker_temps EXIT' test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh >/dev/null
|
||||
grep -Fx 'keep_report_file=1' test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh >/dev/null
|
||||
if ! awk '
|
||||
index($0, "if [[ \"$keep_report_file\" -eq 0 && -n \"${report_file:-}\" ]]; then") { cleanup_line = NR }
|
||||
index($0, "keep_report_file=1") { keep_line = NR }
|
||||
index($0, "echo \"wrote $report_file\"") { wrote_line = NR }
|
||||
END { exit !(cleanup_line && keep_line && wrote_line && cleanup_line < keep_line && keep_line < wrote_line) }
|
||||
' test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh; then
|
||||
echo "rs274ngc_pre blocker scan does not clean failed reports before preserving successful ones" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! awk '
|
||||
index($0, "LINUXCNC_ROOT=\"$linuxcnc_root\" ./check-linuxcnc-inputs.sh \"$manifest\"") { check_line = NR }
|
||||
index($0, "report_file=$(mktemp ") { report_line = NR }
|
||||
END { exit !(check_line && report_line && check_line < report_line) }
|
||||
' test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh; then
|
||||
echo "rs274ngc_pre blocker scan creates its report before input validation" >&2
|
||||
exit 1
|
||||
fi
|
||||
for build_dir_probe_script in \
|
||||
test-linuxcnc-wasm-interp-base-link.sh \
|
||||
test-linuxcnc-wasm-interp-find-link.sh \
|
||||
test-linuxcnc-wasm-python-plugin-link.sh \
|
||||
test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh \
|
||||
test-linuxcnc-wasm-rs274ngc-pre-link.sh \
|
||||
test-linuxcnc-wasm-rs274ngc-pre-object.sh \
|
||||
test-linuxcnc-wasm-source-objects.sh \
|
||||
test-linuxcnc-wasm-tooldata-common-link.sh \
|
||||
test-linuxcnc-wasm-tooldata-link.sh \
|
||||
test-linuxcnc-wasm-tooldata-mmap-symbols.sh \
|
||||
test-linuxcnc-wasm-tooldata-runtime-symbols.sh; do
|
||||
if ! awk '
|
||||
$0 ~ /^trap .* EXIT$/ { trap_line = NR }
|
||||
index($0, "./check-linuxcnc-inputs.sh") && !check_line { check_line = NR }
|
||||
END { exit !(trap_line && check_line && trap_line < check_line) }
|
||||
' "$build_dir_probe_script"; then
|
||||
echo "$build_dir_probe_script installs build_dir cleanup after input validation" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
grep -F 'trap '\''rm -f "$missing_manifest" "$missing_manifest_log" "$missing_root_log" "$missing_source_manifest" "$missing_source_log" "$duplicate_manifest" "$duplicate_manifest_log" "$missing_replacement_manifest" "$missing_replacement_log"'\'' EXIT' test-linuxcnc-wasm-blockers.sh >/dev/null
|
||||
if grep -F 'rm -f "$missing_source_manifest" "$missing_source_log"' test-linuxcnc-wasm-blockers.sh >/dev/null; then
|
||||
echo "wasm blocker scan still relies on manual cleanup for missing-source temporaries" >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -Fx 'trap cleanup_wasm_cmake_probe_temps EXIT' test-linuxcnc-wasm-cmake-safe-probe.sh >/dev/null
|
||||
if ! awk '
|
||||
/cleanup_wasm_cmake_probe_temps\(\)/ { in_cleanup = 1 }
|
||||
in_cleanup && index($0, "\"$missing_manifest\"") { found_missing_manifest = 1 }
|
||||
in_cleanup && index($0, "\"${missing_wasm_script_manifest:-}\"") { found_missing_script_manifest = 1 }
|
||||
in_cleanup && /^}/ { in_cleanup = 0 }
|
||||
END { exit !(found_missing_manifest && found_missing_script_manifest) }
|
||||
' test-linuxcnc-wasm-cmake-safe-probe.sh; then
|
||||
echo "wasm CMake safe probe cleanup no longer removes fixed missing-manifest paths" >&2
|
||||
exit 1
|
||||
fi
|
||||
for forbidden_manual_cleanup in \
|
||||
'rm -f "$missing_manifest_log"' \
|
||||
'rm -f "$unknown_manifest_filter_log"' \
|
||||
'rm -f "$unknown_manifest_output_log"' \
|
||||
'rm -f "$missing_shim_log"' \
|
||||
'rm -f "$missing_project_source_log"' \
|
||||
'rm -f "$missing_wasm_script_manifest_log"' \
|
||||
'rm -rf "$missing_source_root"' \
|
||||
'rm -f "$missing_source_log"' \
|
||||
'rm -rf "$missing_interp_find_root"' \
|
||||
'rm -f "$missing_interp_find_log"' \
|
||||
'rm -rf "$missing_tooldata_runtime_root"' \
|
||||
'rm -f "$missing_tooldata_runtime_log"' \
|
||||
'rm -f "$unknown_group_manifest" "$unknown_group_log"' \
|
||||
'rm -f "$blocker_report_file" "$blocker_scan_log"' \
|
||||
'rm -f "$missing_source_manifest" "$missing_source_log"' \
|
||||
'rm -f "$empty_core_manifest" "$empty_blocked_manifest" "$empty_partition_log"' \
|
||||
'rm -rf "$bad_default_manifest_dir"' \
|
||||
'rm -f "$bad_default_manifest_log"' \
|
||||
'rm -f "$duplicate_manifest" "$duplicate_manifest_log"' \
|
||||
'rm -f "$comment_manifest" "$comment_manifest_log"' \
|
||||
'rm -f "$duplicate_source_manifest" "$duplicate_source_log"' \
|
||||
'rm -f "$duplicate_syntax_manifest" "$duplicate_syntax_log"' \
|
||||
'rm -f "$duplicate_pre_blocker_manifest" "$duplicate_pre_blocker_log"' \
|
||||
'rm -f "$duplicate_pre_link_manifest" "$duplicate_pre_link_log"'; do
|
||||
if grep -Fx "$forbidden_manual_cleanup" test-linuxcnc-wasm-cmake-safe-probe.sh >/dev/null; then
|
||||
echo "wasm CMake safe probe still relies on manual cleanup: $forbidden_manual_cleanup" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
forbidden_common_flags_process_substitution='readarray -t common_flags < <('
|
||||
forbidden_common_flags_helper='./list-linuxcnc-wasm-common-cxxflags.sh'
|
||||
if grep -RInF "${forbidden_common_flags_process_substitution}LINUXCNC_ROOT=\"\$linuxcnc_root\" ${forbidden_common_flags_helper}" test-linuxcnc-wasm-*.sh >/dev/null; then
|
||||
echo "wasm probes still read common flags through process substitution" >&2
|
||||
grep -RInF "${forbidden_common_flags_process_substitution}LINUXCNC_ROOT=\"\$linuxcnc_root\" ${forbidden_common_flags_helper}" test-linuxcnc-wasm-*.sh >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -F -- '-DCNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST="$manifest"' build-wasm.sh >/dev/null
|
||||
grep -F -- 'if ! command -v emcmake >/dev/null 2>&1; then' build-wasm.sh >/dev/null
|
||||
grep -F "Emscripten is required. Install/activate emsdk so emcmake and emcc are in PATH." build-wasm.sh >/dev/null
|
||||
grep -F -- 'emcmake cmake -S core -B build/wasm \' build-wasm.sh >/dev/null
|
||||
grep -F -- 'default_manifest="$PWD/linuxcnc-rs274-wasm-source-files.txt"' build-wasm.sh >/dev/null
|
||||
grep -F -- 'LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core > "$manifest_core_sources"' build-wasm.sh >/dev/null
|
||||
grep -F -- 'LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" blocked > "$manifest_blocked_sources"' build-wasm.sh >/dev/null
|
||||
grep -F -- 'manifest_core_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core)' build-wasm.sh >/dev/null
|
||||
grep -F -- 'manifest_blocked_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" blocked)' build-wasm.sh >/dev/null
|
||||
grep -F -- 'count_nonempty_lines() {' build-wasm.sh >/dev/null
|
||||
grep -F -- 'manifest_core_count=$(count_nonempty_lines "$manifest_core_output")' build-wasm.sh >/dev/null
|
||||
grep -F -- 'manifest_blocked_count=$(count_nonempty_lines "$manifest_blocked_output")' build-wasm.sh >/dev/null
|
||||
if grep -F 'grep -c . <<<"$manifest_core_output" || true' build-wasm.sh >/dev/null; then
|
||||
echo "build-wasm still counts manifest output through grep -c with || true" >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -F -- 'if [[ "$manifest" == "$default_manifest" ]] && [[ "$manifest_core_count" -ne 25 || "$manifest_blocked_count" -ne 1 ]]; then' build-wasm.sh >/dev/null
|
||||
grep -Fx 'LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "$manifest"' test-linuxcnc-wasm-cmake-safe-probe.sh >/dev/null
|
||||
./list-linuxcnc-wasm-safe-shims.sh >/dev/null
|
||||
./list-linuxcnc-wasm-safe-project-sources.sh >/dev/null
|
||||
./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core >/dev/null
|
||||
grep -Fx "src/emc/rs274ngc/interp_arc.cc" \
|
||||
< <(./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core) >/dev/null
|
||||
grep -Fx "src/emc/tooldata/tooldata_mmap.cc" \
|
||||
< <(./list-linuxcnc-wasm-manifest-sources.sh "$manifest" blocked) >/dev/null
|
||||
wasm_manifest_core=$(./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core)
|
||||
grep -Fx "src/emc/rs274ngc/interp_arc.cc" <<<"$wasm_manifest_core" >/dev/null
|
||||
if grep -E '\.(hh|h)$' <<<"$wasm_manifest_core" >/dev/null; then
|
||||
echo "wasm manifest core compile group includes headers" >&2
|
||||
exit 1
|
||||
fi
|
||||
wasm_manifest_header=$(./list-linuxcnc-wasm-manifest-sources.sh "$manifest" header)
|
||||
grep -Fx "src/emc/rs274ngc/rs274ngc_interp.hh" <<<"$wasm_manifest_header" >/dev/null
|
||||
wasm_manifest_blocked=$(./list-linuxcnc-wasm-manifest-sources.sh "$manifest" blocked)
|
||||
grep -Fx "src/emc/tooldata/tooldata_mmap.cc" <<<"$wasm_manifest_blocked" >/dev/null
|
||||
wasm_manifest_blocked_header=$(./list-linuxcnc-wasm-manifest-sources.sh "$manifest" blocked-header)
|
||||
grep -Fx "src/emc/rs274ngc/boost_pyenum_macros.hh" <<<"$wasm_manifest_blocked_header" >/dev/null
|
||||
unknown_manifest_filter_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_unknown_wasm_manifest_filter.XXXXXX.log")
|
||||
if ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" bogus >"$unknown_manifest_filter_log" 2>&1; then
|
||||
echo "wasm manifest source lister accepted unknown filter" >&2
|
||||
@@ -84,7 +236,6 @@ if ! grep -F "unknown manifest source filter: bogus" "$unknown_manifest_filter_l
|
||||
sed -n '1,20p' "$unknown_manifest_filter_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$unknown_manifest_filter_log"
|
||||
unknown_manifest_output_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_unknown_wasm_manifest_output.XXXXXX.log")
|
||||
if ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core bogus >"$unknown_manifest_output_log" 2>&1; then
|
||||
echo "wasm manifest source lister accepted unknown output mode" >&2
|
||||
@@ -95,20 +246,20 @@ if ! grep -F "unknown manifest source output mode: bogus" "$unknown_manifest_out
|
||||
sed -n '1,20p' "$unknown_manifest_output_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$unknown_manifest_output_log"
|
||||
grep -Fx "$linuxcnc_root/src/emc/rs274ngc/interp_arc.cc" \
|
||||
< <(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core full) >/dev/null
|
||||
grep -Fx "core/wasm_shims/dlfcn.cc" < <(./list-linuxcnc-wasm-safe-shims.sh dlfcn.cc) >/dev/null
|
||||
grep -Fx "core/wasm_shims/pythonplugin/python_plugin.cc" \
|
||||
< <(./list-linuxcnc-wasm-safe-shims.sh python_plugin.cc) >/dev/null
|
||||
grep -Fx "core/wasm_shims/rtapi_compat.cc" \
|
||||
< <(./list-linuxcnc-wasm-safe-shims.sh rtapi_compat.cc) >/dev/null
|
||||
grep -Fx "core/wasm_shims/tooldata/tooldata_mmap_backend.cc" \
|
||||
< <(./list-linuxcnc-wasm-safe-shims.sh tooldata_mmap_backend.cc) >/dev/null
|
||||
grep -Fx "core/wasm_shims/tooldata/tooldata_runtime_stubs.cc" \
|
||||
< <(./list-linuxcnc-wasm-safe-shims.sh tooldata_runtime_stubs.cc) >/dev/null
|
||||
grep -Fx "core/src/linuxcnc_canon_bridge.cpp" \
|
||||
< <(./list-linuxcnc-wasm-safe-project-sources.sh linuxcnc_canon_bridge.cpp) >/dev/null
|
||||
wasm_manifest_core_full=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core full)
|
||||
grep -Fx "$linuxcnc_root/src/emc/rs274ngc/interp_arc.cc" <<<"$wasm_manifest_core_full" >/dev/null
|
||||
dlfcn_shim=$(./list-linuxcnc-wasm-safe-shims.sh dlfcn.cc)
|
||||
grep -Fx "core/wasm_shims/dlfcn.cc" <<<"$dlfcn_shim" >/dev/null
|
||||
python_plugin_shim=$(./list-linuxcnc-wasm-safe-shims.sh python_plugin.cc)
|
||||
grep -Fx "core/wasm_shims/pythonplugin/python_plugin.cc" <<<"$python_plugin_shim" >/dev/null
|
||||
rtapi_compat_shim=$(./list-linuxcnc-wasm-safe-shims.sh rtapi_compat.cc)
|
||||
grep -Fx "core/wasm_shims/rtapi_compat.cc" <<<"$rtapi_compat_shim" >/dev/null
|
||||
tooldata_mmap_backend_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_mmap_backend.cc)
|
||||
grep -Fx "core/wasm_shims/tooldata/tooldata_mmap_backend.cc" <<<"$tooldata_mmap_backend_shim" >/dev/null
|
||||
tooldata_runtime_stubs_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_runtime_stubs.cc)
|
||||
grep -Fx "core/wasm_shims/tooldata/tooldata_runtime_stubs.cc" <<<"$tooldata_runtime_stubs_shim" >/dev/null
|
||||
wasm_bridge_source=$(./list-linuxcnc-wasm-safe-project-sources.sh linuxcnc_canon_bridge.cpp)
|
||||
grep -Fx "core/src/linuxcnc_canon_bridge.cpp" <<<"$wasm_bridge_source" >/dev/null
|
||||
missing_shim_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_safe_shim.XXXXXX.log")
|
||||
if ./list-linuxcnc-wasm-safe-shims.sh does_not_exist.cc >"$missing_shim_log" 2>&1; then
|
||||
echo "wasm-safe shim lister accepted missing shim filter" >&2
|
||||
@@ -119,7 +270,6 @@ if ! grep -F "missing wasm-safe shim in CMake list: does_not_exist.cc" "$missing
|
||||
sed -n '1,20p' "$missing_shim_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_shim_log"
|
||||
missing_project_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_safe_project_source.XXXXXX.log")
|
||||
if ./list-linuxcnc-wasm-safe-project-sources.sh does_not_exist.cc >"$missing_project_source_log" 2>&1; then
|
||||
echo "wasm-safe project source lister accepted missing source filter" >&2
|
||||
@@ -130,8 +280,6 @@ if ! grep -F "missing wasm-safe project source in CMake list: does_not_exist.cc"
|
||||
sed -n '1,20p' "$missing_project_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_project_source_log"
|
||||
rm -f "$missing_root_log"
|
||||
|
||||
missing_wasm_script_manifest=${TMPDIR:-/tmp}/cnc_sim_missing_wasm_script_manifest.txt
|
||||
missing_wasm_script_manifest_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_script_manifest.XXXXXX.log")
|
||||
@@ -152,7 +300,6 @@ for script in \
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
rm -f "$missing_wasm_script_manifest_log"
|
||||
|
||||
missing_root_scripts=(
|
||||
test-linuxcnc-wasm-interp-base-link.sh
|
||||
@@ -179,7 +326,6 @@ for script in "${missing_root_scripts[@]}"; do
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
rm -f "$missing_root_log"
|
||||
|
||||
missing_source_root=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_missing_linuxcnc_source_root.XXXXXX")
|
||||
missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_linuxcnc_source.XXXXXX.log")
|
||||
@@ -207,8 +353,6 @@ for script_and_path in "${fixed_source_scripts[@]}"; do
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
rm -rf "$missing_source_root"
|
||||
rm -f "$missing_source_log"
|
||||
|
||||
missing_interp_find_root=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_missing_interp_find_source_root.XXXXXX")
|
||||
missing_interp_find_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_interp_find_source.XXXXXX.log")
|
||||
@@ -223,8 +367,6 @@ if ! grep -F "missing LinuxCNC source: src/emc/rs274ngc/interp_find.cc" "$missin
|
||||
sed -n '1,20p' "$missing_interp_find_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -rf "$missing_interp_find_root"
|
||||
rm -f "$missing_interp_find_log"
|
||||
|
||||
missing_tooldata_runtime_root=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_missing_tooldata_runtime_source_root.XXXXXX")
|
||||
missing_tooldata_runtime_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_tooldata_runtime_source.XXXXXX.log")
|
||||
@@ -239,8 +381,6 @@ if ! grep -F "missing LinuxCNC source: src/emc/tooldata/tooldata_nml.cc" "$missi
|
||||
sed -n '1,20p' "$missing_tooldata_runtime_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -rf "$missing_tooldata_runtime_root"
|
||||
rm -f "$missing_tooldata_runtime_log"
|
||||
|
||||
unknown_group_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_unknown_wasm_manifest_group.XXXXXX.txt")
|
||||
unknown_group_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_unknown_wasm_manifest_group.XXXXXX.log")
|
||||
@@ -270,7 +410,6 @@ for script in \
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
rm -f "$unknown_group_manifest" "$unknown_group_log"
|
||||
|
||||
blocker_scan_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_wasm_blocker_scan.XXXXXX.log")
|
||||
./test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh >"$blocker_scan_log" 2>&1
|
||||
@@ -280,7 +419,6 @@ if [[ -z "$blocker_report_file" || ! -f "$blocker_report_file" ]]; then
|
||||
sed -n '1,20p' "$blocker_scan_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$blocker_report_file" "$blocker_scan_log"
|
||||
|
||||
missing_source_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_manifest_source.XXXXXX.txt")
|
||||
missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_manifest_source.XXXXXX.log")
|
||||
@@ -330,7 +468,6 @@ if ! grep -F "missing manifest source: src/emc/rs274ngc/does_not_exist.cc" "$mis
|
||||
sed -n '1,20p' "$missing_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_source_manifest" "$missing_source_log"
|
||||
|
||||
empty_partition_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_empty_wasm_manifest_partition.XXXXXX.log")
|
||||
empty_core_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_empty_wasm_manifest_core.XXXXXX.txt")
|
||||
@@ -355,12 +492,14 @@ if ! grep -F "unexpected wasm manifest partition: core=1 blocked=0" "$empty_part
|
||||
sed -n '1,20p' "$empty_partition_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$empty_core_manifest" "$empty_blocked_manifest" "$empty_partition_log"
|
||||
|
||||
bad_default_manifest_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_bad_default_wasm_manifest.XXXXXX")
|
||||
bad_default_manifest_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_bad_default_wasm_manifest.XXXXXX.log")
|
||||
linuxcnc_root_abs=$(cd "$linuxcnc_root" && pwd)
|
||||
cp build-wasm.sh "$bad_default_manifest_dir/build-wasm.sh"
|
||||
cp check-linuxcnc-inputs.sh "$bad_default_manifest_dir/check-linuxcnc-inputs.sh"
|
||||
cp list-linuxcnc-source-files.sh "$bad_default_manifest_dir/list-linuxcnc-source-files.sh"
|
||||
cp list-linuxcnc-manifest-sources.sh "$bad_default_manifest_dir/list-linuxcnc-manifest-sources.sh"
|
||||
cp list-linuxcnc-wasm-manifest-sources.sh "$bad_default_manifest_dir/list-linuxcnc-wasm-manifest-sources.sh"
|
||||
printf 'core:src/emc/rs274ngc/interp_arc.cc:test bad default core count\nblocked:src/emc/tooldata/tooldata_mmap.cc:test bad default blocked count\n' \
|
||||
>"$bad_default_manifest_dir/linuxcnc-rs274-wasm-source-files.txt"
|
||||
@@ -373,8 +512,6 @@ if ! grep -F "unexpected wasm manifest partition: core=1 blocked=1" "$bad_defaul
|
||||
sed -n '1,20p' "$bad_default_manifest_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -rf "$bad_default_manifest_dir"
|
||||
rm -f "$bad_default_manifest_log"
|
||||
|
||||
duplicate_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_manifest.XXXXXX.txt")
|
||||
duplicate_manifest_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_manifest.XXXXXX.log")
|
||||
@@ -392,7 +529,6 @@ if ! grep -F "duplicate manifest source: src/emc/rs274ngc/interp_arc.cc" "$dupli
|
||||
sed -n '1,20p' "$duplicate_manifest_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$duplicate_manifest" "$duplicate_manifest_log"
|
||||
|
||||
comment_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_comment_wasm_manifest.XXXXXX.txt")
|
||||
comment_manifest_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_comment_wasm_manifest.XXXXXX.log")
|
||||
@@ -410,7 +546,6 @@ if grep -F "duplicate manifest source" "$comment_manifest_log" >/dev/null; then
|
||||
sed -n '1,20p' "$comment_manifest_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$comment_manifest" "$comment_manifest_log"
|
||||
|
||||
duplicate_source_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_source_manifest.XXXXXX.txt")
|
||||
duplicate_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_source_manifest.XXXXXX.log")
|
||||
@@ -428,7 +563,6 @@ if ! grep -F "duplicate manifest source: src/emc/rs274ngc/interp_arc.cc" "$dupli
|
||||
sed -n '1,20p' "$duplicate_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$duplicate_source_manifest" "$duplicate_source_log"
|
||||
|
||||
duplicate_syntax_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_syntax_manifest.XXXXXX.txt")
|
||||
duplicate_syntax_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_syntax_manifest.XXXXXX.log")
|
||||
@@ -446,7 +580,6 @@ if ! grep -F "duplicate manifest source: src/emc/rs274ngc/interp_arc.cc" "$dupli
|
||||
sed -n '1,20p' "$duplicate_syntax_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$duplicate_syntax_manifest" "$duplicate_syntax_log"
|
||||
|
||||
duplicate_pre_blocker_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_pre_blocker_manifest.XXXXXX.txt")
|
||||
duplicate_pre_blocker_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_pre_blocker_manifest.XXXXXX.log")
|
||||
@@ -464,7 +597,6 @@ if ! grep -F "duplicate manifest source: src/emc/rs274ngc/interp_arc.cc" "$dupli
|
||||
sed -n '1,20p' "$duplicate_pre_blocker_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$duplicate_pre_blocker_manifest" "$duplicate_pre_blocker_log"
|
||||
|
||||
duplicate_pre_link_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_pre_link_manifest.XXXXXX.txt")
|
||||
duplicate_pre_link_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_pre_link_manifest.XXXXXX.log")
|
||||
@@ -482,7 +614,6 @@ if ! grep -F "duplicate manifest source: src/emc/rs274ngc/interp_arc.cc" "$dupli
|
||||
sed -n '1,20p' "$duplicate_pre_link_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$duplicate_pre_link_manifest" "$duplicate_pre_link_log"
|
||||
|
||||
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||
default_manifest="$PWD/linuxcnc-rs274-wasm-source-files.txt"
|
||||
|
||||
@@ -7,26 +7,14 @@ linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_interp_base_link.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
|
||||
dlfcn_shim=$(./list-linuxcnc-wasm-safe-shims.sh dlfcn.cc)
|
||||
interp_base_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/rs274ngc/interp_base.cc)
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
"$dlfcn_shim" \
|
||||
|
||||
@@ -7,34 +7,21 @@ linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_interp_find_link.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
|
||||
tooldata_mmap_backend_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_mmap_backend.cc)
|
||||
tooldata_runtime_stubs_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_runtime_stubs.cc)
|
||||
rtapi_compat_shim=$(./list-linuxcnc-wasm-safe-shims.sh rtapi_compat.cc)
|
||||
readarray -t linuxcnc_sources < <(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh \
|
||||
linuxcnc_source_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh \
|
||||
src/emc/tooldata/tooldata_common.cc \
|
||||
src/emc/rs274ngc/interp_find.cc)
|
||||
mapfile -t linuxcnc_sources <<<"$linuxcnc_source_output"
|
||||
tooldata_common_source=${linuxcnc_sources[0]}
|
||||
interp_find_source=${linuxcnc_sources[1]}
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh --function-sections --data-sections)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c "$tooldata_common_source" \
|
||||
|
||||
@@ -7,25 +7,13 @@ linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_python_plugin_link.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
|
||||
python_plugin_shim=$(./list-linuxcnc-wasm-safe-shims.sh python_plugin.cc)
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
"$python_plugin_shim" \
|
||||
|
||||
@@ -6,48 +6,52 @@ cd "$(dirname "$0")"
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_rs274ngc_pre_link_blockers.XXXXXX")
|
||||
report_file=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_rs274ngc_pre_undefined.XXXXXX.txt")
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
keep_report_file=0
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
cleanup_rs274ngc_pre_blocker_temps() {
|
||||
rm -rf "$build_dir"
|
||||
if [[ "$keep_report_file" -eq 0 && -n "${report_file:-}" ]]; then
|
||||
rm -f "$report_file"
|
||||
fi
|
||||
}
|
||||
trap cleanup_rs274ngc_pre_blocker_temps EXIT
|
||||
grep -Fx 'trap cleanup_rs274ngc_pre_blocker_temps EXIT' test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh >/dev/null
|
||||
if awk '/^} > "\$report_file" \|\| true$/{ found = 1 } END { exit !found }' test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh >/dev/null; then
|
||||
echo "rs274ngc_pre blocker scan still hides report pipeline failures with || true" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
if ! awk '
|
||||
index($0, "LINUXCNC_ROOT=\"$linuxcnc_root\" ./check-linuxcnc-inputs.sh \"$manifest\"") { check_line = NR }
|
||||
index($0, "report_file=$(mktemp ") { report_line = NR }
|
||||
END { exit !(check_line && report_line && check_line < report_line) }
|
||||
' test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh; then
|
||||
echo "rs274ngc_pre blocker scan creates its report before input validation" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
if ! awk '
|
||||
index($0, "if [[ \"$keep_report_file\" -eq 0 && -n \"${report_file:-}\" ]]; then") { cleanup_line = NR }
|
||||
index($0, "keep_report_file=1") { keep_line = NR }
|
||||
index($0, "echo \"wrote $report_file\"") { wrote_line = NR }
|
||||
END { exit !(cleanup_line && keep_line && wrote_line && cleanup_line < keep_line && keep_line < wrote_line) }
|
||||
' test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh; then
|
||||
echo "rs274ngc_pre blocker scan does not clean failed reports before preserving successful ones" >&2
|
||||
exit 1
|
||||
fi
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "$manifest"
|
||||
report_file=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_rs274ngc_pre_undefined.XXXXXX.txt")
|
||||
|
||||
common_flags=(
|
||||
-std=c++20
|
||||
-DULAPI
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-include wctype.h
|
||||
-I "$(pwd)/core/include"
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh --profile core20-sections)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
shim_list="$build_dir/wasm_safe_shims.txt"
|
||||
./list-linuxcnc-wasm-safe-shims.sh > "$shim_list"
|
||||
mapfile -t shim_sources < "$shim_list"
|
||||
shim_output=$(./list-linuxcnc-wasm-safe-shims.sh)
|
||||
mapfile -t shim_sources <<<"$shim_output"
|
||||
|
||||
project_source_list="$build_dir/wasm_safe_project_sources.txt"
|
||||
./list-linuxcnc-wasm-safe-project-sources.sh > "$project_source_list"
|
||||
mapfile -t project_sources < "$project_source_list"
|
||||
project_source_output=$(./list-linuxcnc-wasm-safe-project-sources.sh)
|
||||
mapfile -t project_sources <<<"$project_source_output"
|
||||
|
||||
linuxcnc_sources=()
|
||||
source_list="$build_dir/wasm_core_sources.txt"
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core full > "$source_list"
|
||||
mapfile -t linuxcnc_sources < "$source_list"
|
||||
source_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core full)
|
||||
mapfile -t linuxcnc_sources <<<"$source_output"
|
||||
|
||||
shim_index=0
|
||||
for source in "${shim_sources[@]}"; do
|
||||
@@ -87,11 +91,14 @@ nm --defined-only "$build_dir"/*.o \
|
||||
|
||||
{
|
||||
comm -23 "$undefined_file" "$defined_file" \
|
||||
| grep -Ev '^(_GLOBAL_OFFSET_TABLE_|_Unwind_Resume)$' \
|
||||
| grep -Ev '^(__assert_fail|__cxa_|__divdc3|__dso_handle|__errno_location|__gxx_personality_v0|__isoc23_|__muldc3|__stack_chk_fail)' \
|
||||
| grep -Ev '^(abort|access|acos|asin|atan2|atof|atoi|basename|cabs|calloc|ceil|close|closedir|copysign|cos|cosl|exit|exp|fclose|fdatasync|fdopen|feof|fflush|fgetc|fgets|fileno|floor|fmod|fopen|fprintf|fputs|free|freelocale|fseek|fstat|ftell|fwrite|getcwd|getenv|getpid|gettimeofday|hypot|islower|isprint|isspace|isupper|isxdigit|link|localtime|log|lstat|malloc|memchr|memcmp|memcpy|memmove|memset|mkstemp|nearbyint|newlocale|open|opendir|perror|pow|printf|pthread_mutex_lock|pthread_mutex_unlock|putc|puts|read|readdir|realpath|realloc|remove|rename|setlocale|sin|sinl|snprintf|sprintf|sqrt|sscanf|stat|stderr|stdout|strcasecmp|strcat|strchr|strcmp|strcpy|strdup|strerror|strlen|strncasecmp|strncat|strncmp|strncpy|strrchr|strspn|strstr|strtod|strtok_r|strtol|strtoul|tan|tanl|tolower|toupper|towlower|unlink|uselocale|vfprintf|vsnprintf|wordexp|wordfree)$' \
|
||||
| grep -Ev '^(_ZN3fmt|_ZSt|_ZNSt|_ZNKSt|_ZNKRSt|_ZNS|_ZTI|_ZTS|_ZTV|_Zdl|_Znwm|_Znam|_Zda|_ZdaPv|_ZdaPvm|_ZdlPvm|_ZTv|_ZTh)'
|
||||
} > "$report_file" || true
|
||||
| awk '
|
||||
$0 ~ /^(_GLOBAL_OFFSET_TABLE_|_Unwind_Resume)$/ { next }
|
||||
$0 ~ /^(__assert_fail|__cxa_|__divdc3|__dso_handle|__errno_location|__gxx_personality_v0|__isoc23_|__muldc3|__stack_chk_fail)/ { next }
|
||||
$0 ~ /^(abort|access|acos|asin|atan2|atof|atoi|basename|cabs|calloc|ceil|close|closedir|copysign|cos|cosl|exit|exp|fclose|fdatasync|fdopen|feof|fflush|fgetc|fgets|fileno|floor|fmod|fopen|fprintf|fputs|free|freelocale|fseek|fstat|ftell|fwrite|getcwd|getenv|getpid|gettimeofday|hypot|islower|isprint|isspace|isupper|isxdigit|link|localtime|log|lstat|malloc|memchr|memcmp|memcpy|memmove|memset|mkstemp|nearbyint|newlocale|open|opendir|perror|pow|printf|pthread_mutex_lock|pthread_mutex_unlock|putc|puts|read|readdir|realpath|realloc|remove|rename|setlocale|sin|sinl|snprintf|sprintf|sqrt|sscanf|stat|stderr|stdout|strcasecmp|strcat|strchr|strcmp|strcpy|strdup|strerror|strlen|strncasecmp|strncat|strncmp|strncpy|strrchr|strspn|strstr|strtod|strtok_r|strtol|strtoul|tan|tanl|tolower|toupper|towlower|unlink|uselocale|vfprintf|vsnprintf|wordexp|wordfree)$/ { next }
|
||||
$0 ~ /^(_ZN3fmt|_ZSt|_ZNSt|_ZNKSt|_ZNKRSt|_ZNS|_ZTI|_ZTS|_ZTV|_Zdl|_Znwm|_Znam|_Zda|_ZdaPv|_ZdaPvm|_ZdlPvm|_ZTv|_ZTh)/ { next }
|
||||
{ print }
|
||||
'
|
||||
} > "$report_file"
|
||||
|
||||
if grep -F "_ZN6Interp13read_commentEPcPiP12block_structPd" "$report_file" >/dev/null; then
|
||||
echo "unexpected unresolved read_comment after interp_read.cc" >&2
|
||||
@@ -139,4 +146,5 @@ if [[ -s "$report_file" ]]; then
|
||||
fi
|
||||
|
||||
echo "linuxcnc wasm rs274ngc_pre link blocker scan passed"
|
||||
keep_report_file=1
|
||||
echo "wrote $report_file"
|
||||
|
||||
@@ -8,45 +8,20 @@ cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_rs274ngc_pre_link.XXXXXX")
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "$manifest"
|
||||
|
||||
common_flags=(
|
||||
-std=c++20
|
||||
-DULAPI
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-I "$(pwd)/core/src"
|
||||
-include wctype.h
|
||||
-I "$(pwd)/core/include"
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh --profile core20-sections)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
shim_list="$build_dir/wasm_safe_shims.txt"
|
||||
./list-linuxcnc-wasm-safe-shims.sh > "$shim_list"
|
||||
mapfile -t sources < "$shim_list"
|
||||
project_source_list="$build_dir/wasm_safe_project_sources.txt"
|
||||
./list-linuxcnc-wasm-safe-project-sources.sh > "$project_source_list"
|
||||
mapfile -t project_sources < "$project_source_list"
|
||||
shim_output=$(./list-linuxcnc-wasm-safe-shims.sh)
|
||||
mapfile -t sources <<<"$shim_output"
|
||||
project_source_output=$(./list-linuxcnc-wasm-safe-project-sources.sh)
|
||||
mapfile -t project_sources <<<"$project_source_output"
|
||||
sources+=("${project_sources[@]}")
|
||||
|
||||
source_list="$build_dir/wasm_core_sources.txt"
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core full > "$source_list"
|
||||
mapfile -t linuxcnc_sources < "$source_list"
|
||||
source_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core full)
|
||||
mapfile -t linuxcnc_sources <<<"$source_output"
|
||||
for source in "${linuxcnc_sources[@]}"; do
|
||||
sources+=("$source")
|
||||
done
|
||||
|
||||
@@ -7,24 +7,12 @@ linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_rs274ngc_pre_object.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
rs274ngc_pre_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/rs274ngc/rs274ngc_pre.cc)
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c "$rs274ngc_pre_source" \
|
||||
|
||||
@@ -8,39 +8,17 @@ manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_safe_probe.XXXXXX")
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "$manifest"
|
||||
|
||||
shim_list="$build_dir/wasm_safe_shims.txt"
|
||||
./list-linuxcnc-wasm-safe-shims.sh > "$shim_list"
|
||||
mapfile -t shim_sources < "$shim_list"
|
||||
shim_output=$(./list-linuxcnc-wasm-safe-shims.sh)
|
||||
mapfile -t shim_sources <<<"$shim_output"
|
||||
|
||||
common_flags=(
|
||||
-std=c++20
|
||||
-DULAPI
|
||||
-include wctype.h
|
||||
-I "$(pwd)/core/include"
|
||||
-I "$(pwd)/core/src"
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh --profile core20)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
source_list="$build_dir/wasm_core_sources.txt"
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core full > "$source_list"
|
||||
mapfile -t sources < "$source_list"
|
||||
source_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core full)
|
||||
mapfile -t sources <<<"$source_output"
|
||||
|
||||
shim_index=0
|
||||
for source in "${shim_sources[@]}"; do
|
||||
|
||||
@@ -7,36 +7,13 @@ linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
cxx=${CXX:-g++}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh "$manifest"
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh --profile core20 --syntax-only)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
common_flags=(
|
||||
-std=c++20
|
||||
-DULAPI
|
||||
-fsyntax-only
|
||||
-include wctype.h
|
||||
-I "$(pwd)/core/include"
|
||||
-I "$(pwd)/core/src"
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
|
||||
source_list=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_source_syntax_sources.XXXXXX.txt")
|
||||
trap 'rm -f "$source_list"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core full > "$source_list"
|
||||
mapfile -t sources < "$source_list"
|
||||
source_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-manifest-sources.sh "$manifest" core full)
|
||||
mapfile -t sources <<<"$source_output"
|
||||
|
||||
for source in "${sources[@]}"; do
|
||||
"$cxx" "${common_flags[@]}" "$source"
|
||||
|
||||
@@ -7,27 +7,15 @@ linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_tooldata_common_link.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
|
||||
tooldata_mmap_backend_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_mmap_backend.cc)
|
||||
tooldata_runtime_stubs_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_runtime_stubs.cc)
|
||||
tooldata_common_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/tooldata/tooldata_common.cc)
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$linuxcnc_root/src/emc/tooldata"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh --tooldata-include)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
"$tooldata_common_source" \
|
||||
|
||||
@@ -7,27 +7,15 @@ linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_tooldata_link.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
|
||||
tooldata_mmap_backend_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_mmap_backend.cc)
|
||||
tooldata_runtime_stubs_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_runtime_stubs.cc)
|
||||
tooldata_common_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/tooldata/tooldata_common.cc)
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
"$tooldata_common_source" \
|
||||
|
||||
@@ -7,26 +7,14 @@ linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_tooldata_mmap_symbols.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
|
||||
tooldata_mmap_backend_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_mmap_backend.cc)
|
||||
tooldata_mmap_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/tooldata/tooldata_mmap.cc)
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c "$tooldata_mmap_backend_shim" \
|
||||
|
||||
@@ -7,31 +7,20 @@ linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_tooldata_runtime_symbols.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs.sh --root-only
|
||||
|
||||
tooldata_mmap_backend_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_mmap_backend.cc)
|
||||
tooldata_runtime_stubs_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_runtime_stubs.cc)
|
||||
readarray -t linuxcnc_sources < <(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh \
|
||||
linuxcnc_source_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh \
|
||||
src/emc/tooldata/tooldata_db.cc \
|
||||
src/emc/tooldata/tooldata_nml.cc)
|
||||
mapfile -t linuxcnc_sources <<<"$linuxcnc_source_output"
|
||||
tooldata_db_source=${linuxcnc_sources[0]}
|
||||
tooldata_nml_source=${linuxcnc_sources[1]}
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh)
|
||||
mapfile -t common_flags <<<"$common_flag_output"
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c "$tooldata_runtime_stubs_shim" \
|
||||
|
||||
Reference in New Issue
Block a user