按规划持续工作
This commit is contained in:
@@ -12,6 +12,12 @@ The primary native validation command is:
|
||||
wasm-port/tests/native/verify_native_probes.sh
|
||||
```
|
||||
|
||||
The native LinuxCNC `nc_files` basic/example validation command is:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/native/verify_nc_files.sh
|
||||
```
|
||||
|
||||
The current WASM smoke validation command is:
|
||||
|
||||
```bash
|
||||
@@ -24,6 +30,18 @@ The current WASM interpreter-core smoke validation command is:
|
||||
wasm-port/tests/wasm/node/verify_interp_wasm.sh
|
||||
```
|
||||
|
||||
The current WASM sim-config smoke validation command is:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
|
||||
```
|
||||
|
||||
The current WASM `nc_files` smoke validation command is:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/wasm/node/verify_nc_files_wasm.sh
|
||||
```
|
||||
|
||||
The current WASM trajectory-planner smoke validation command is:
|
||||
|
||||
```bash
|
||||
@@ -74,10 +92,58 @@ The native validation script runs these checks in order:
|
||||
5. `tools/build_native_probes.sh`
|
||||
Builds native source probes and standalone harnesses from vendored
|
||||
LinuxCNC source plus narrow runtime wrappers.
|
||||
6. `tests/native/verify_native_probes.sh`
|
||||
6. `tests/native/verify_sim_configs.sh`
|
||||
Runs LinuxCNC `configs/sim` `.ngc` programs through the upstream
|
||||
`../linuxcnc/bin/rs274` standalone entry point, using nearest or explicit
|
||||
sim INI/tool-table mappings and classifying main programs, macro-load
|
||||
checks, and remap subroutines separately.
|
||||
7. `tests/native/verify_nc_files.sh`
|
||||
Runs the basic/example subset of upstream `linuxcnc/nc_files` through
|
||||
`../linuxcnc/bin/rs274`, with complete programs executed strictly and
|
||||
macro/library files wrapped only for load/parse validation.
|
||||
8. `tests/native/verify_native_probes.sh`
|
||||
Checks probe exit codes, source-probe coverage, harness stdout, canonical
|
||||
fixture events, and expected error behavior.
|
||||
|
||||
Current `nc_files` basic-suite baseline:
|
||||
|
||||
```text
|
||||
total: 107
|
||||
pass: 101
|
||||
fail: 6
|
||||
timeout: 0
|
||||
expected_fail: 6
|
||||
unexpected_fail: 0
|
||||
```
|
||||
|
||||
The six expected failures are LinuxCNC-native entry-point/context edges:
|
||||
`cone.ngc` needs a W-axis 5-axis machine context; `g76.ngc` and
|
||||
`lathe-g76.ngc` need lathe cutter-compensation/tool context;
|
||||
`lathe_g70_71_demo.ngc` needs lathe profile/tool context; `nestedcall.ngc`
|
||||
uses an upstream O-word `callsub` syntax edge; and `tool-length-probe.ngc`
|
||||
needs probe runtime context.
|
||||
|
||||
The same runner also supports exploratory full-directory inventory:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/native/verify_nc_files.sh --all
|
||||
```
|
||||
|
||||
Current full-directory `nc_files` inventory:
|
||||
|
||||
```text
|
||||
total: 247
|
||||
pass: 219
|
||||
fail: 28
|
||||
timeout: 0
|
||||
expected_fail: 28
|
||||
unexpected_fail: 0
|
||||
```
|
||||
|
||||
The additional expected failures are probe/plasmac runtime-context files and
|
||||
one NURBS sample using `G2.2`, which the current upstream `bin/rs274`
|
||||
standalone entry point reports as `Unknown g code used`.
|
||||
|
||||
The WASM INI smoke script builds `runtime/ui/ini-panel/linuxcnc_ini.js` and
|
||||
`linuxcnc_ini.wasm` from vendored LinuxCNC `inifile.cc`, then loads that
|
||||
module through `runtime/sdk/src/index.js` in Node and verifies INI string and
|
||||
@@ -109,8 +175,10 @@ Emscripten filesystem through the SDK and runs them through LinuxCNC
|
||||
`Interp::open()`, `Interp::read()`, and `Interp::execute()` to validate the
|
||||
file execution path. It also writes the vendored LinuxCNC `xyzac-trt` and
|
||||
`xyzbc-trt` table-rotary-tilting sample machine INI, `remap_subs/*.ngc`, and
|
||||
`xyzac_switchkins.ngc`/`xyzbc_switchkins.ngc`, `boat-xyzac.ngc`,
|
||||
`boat-xyzbc.ngc`, and `impeller-7bl-xyzac.ngc` demo files into the Emscripten
|
||||
`xyzac_switchkins.ngc`/`xyzbc_switchkins.ngc`,
|
||||
`xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_2.ngc`,
|
||||
`xyzac_switchkins_test_3.ngc`, `boat-xyzac.ngc`, `boat-xyzbc.ngc`, and
|
||||
`impeller-7bl-xyzac.ngc` demo files into the Emscripten
|
||||
filesystem. It also writes the vendored LinuxCNC `xyzab-tdr` table-dual-rotary
|
||||
INI, tool table, `remap_subs/*.ngc`, and `xyzab-tdr-demo.ngc` into the
|
||||
Emscripten filesystem. It also writes the vendored LinuxCNC bridge-mill
|
||||
@@ -119,7 +187,52 @@ Emscripten filesystem. These checks validate the WASM C ABI/SDK path for
|
||||
vendored LinuxCNC `REMAP` parsing, vendored LinuxCNC tool-table loading from
|
||||
the machine INI, O-word remap execution, `M68`/`M66` HAL synchronization, and
|
||||
file `open()`/`read()`/`execute()` completion without JavaScript M-code or
|
||||
kinematics semantics. The same Node smoke writes
|
||||
kinematics semantics. The same Node smoke writes the vendored LinuxCNC
|
||||
`tests/remap/duplicate-o-word`, NGC-only `tests/remap/fail/args.0`,
|
||||
`tests/remap/fail/args.1`, `tests/remap/fail/args.2`,
|
||||
`tests/remap/fail/body-ngc`, `tests/remap/m30-interaction`,
|
||||
`tests/remap/nested-remaps-oword`, `tests/remap/posargs.0`, and
|
||||
`tests/remap/sequencing` INI, program, and remap subroutines into the
|
||||
Emscripten filesystem and validates those
|
||||
upstream NGC remap regressions through the generic `runRemapFile()` C ABI/SDK
|
||||
path, which only reads LinuxCNC INI `SUBROUTINE_PATH`, `REMAP`, and
|
||||
`OWORD_NARGS` entries and calls vendored `Interp::parse_remap()`, `open()`,
|
||||
`read()`, and `execute()`. The NGC-only failure cases that match upstream
|
||||
`rs274 -n 0` flow use the sibling `runRemapFileContinueOnError()` C ABI/SDK
|
||||
path, which records LinuxCNC error text and continues the same vendored
|
||||
`open()`/`read()`/`execute()` loop without implementing failure semantics in
|
||||
JavaScript. The same Node smoke also writes the NGC-only LinuxCNC
|
||||
`tests/remap/remap-io/test-ngc.ini` and `io_*.ngc` subroutines into the
|
||||
Emscripten filesystem, then calls `runRemapIoMdiSequence()` to feed the
|
||||
upstream test-driver MDI sequence into vendored `Interp::execute()`. The SDK
|
||||
does not implement M62-M68, M66 input, or REMAP semantics; the standalone
|
||||
boundary only pre-seeds deterministic external input values and captures
|
||||
LinuxCNC canonical events. The same WASM interpreter smoke also writes minimal `M110` and
|
||||
`M111` fixtures into the Emscripten filesystem, marks the `M1xx` files
|
||||
executable, and validates that the standalone machine-config boundary mirrors
|
||||
LinuxCNC task-layer `[DISPLAY]PROGRAM_PREFIX` plus `[RS274NGC]USER_M_PATH`
|
||||
lookup by registering `USER_DEFINED_FUNCTION` entries and recording
|
||||
deterministic `USER_M_COMMAND` events instead of spawning host processes. The
|
||||
same Node smoke writes the vendored LinuxCNC
|
||||
`tests/interp/do-while-break`, `tests/interp/oword-bug315`,
|
||||
`tests/interp/oword-bug315-p2`, `tests/interp/exists`,
|
||||
`tests/interp/return-value`, `tests/interp/subs-follow-main`,
|
||||
`tests/interp/fractional-linenumbers`, `tests/interp/namedparam-bug424`,
|
||||
selected `tests/interp/rotation` pure interpreter cases, `tests/interp/iniparam`,
|
||||
`tests/interp/iniparam-failassign`,
|
||||
`tests/interp/sub-call-from-sub`, `tests/interp/sequence-number`, and
|
||||
`tests/interp/nested-sub-error`, `tests/interp/nested-sub-in-file-error`, and
|
||||
`tests/interp/abort-hot-comment`
|
||||
files into the Emscripten filesystem and validates those upstream interpreter
|
||||
regressions through `runFile()` or
|
||||
`runFileWithIni()`, which only reads LinuxCNC INI `SUBROUTINE_PATH` where
|
||||
needed and calls vendored LinuxCNC `Interp::open()`, `read()`, and `execute()`.
|
||||
The `iniparam` fixtures validate vendored LinuxCNC `_ini[...]` lookup, missing
|
||||
INI-parameter error text, and read-only named-parameter assignment rejection
|
||||
through the `INI_FILE_NAME` runtime edge. It checks LinuxCNC canonical messages,
|
||||
canonical motion/events, and final interpreter state without JavaScript O-word,
|
||||
subroutine lookup, INI-variable, or read-only-parameter semantics. The
|
||||
same Node smoke writes
|
||||
LinuxCNC-format parameter files into the Emscripten filesystem and validates
|
||||
vendored `Interp::restore_parameters()` and `Interp::save_parameters()`,
|
||||
including the saved parameter values, missing required numeric parameter
|
||||
@@ -203,14 +316,59 @@ override INI-derived names before OPFS text is copied into the LinuxCNC-backed
|
||||
WASM filesystem, and that absent INI file-name values use the default OPFS
|
||||
parameter/tool-table paths in a real browser session. It also writes vendored
|
||||
LinuxCNC `xyzac-trt`/`xyzbc-trt` INI, remap subroutines, and switchkins demo
|
||||
files, including the larger `boat-xyzac.ngc`, `boat-xyzbc.ngc`, and
|
||||
`impeller-7bl-xyzac.ngc` demos, into the browser WASM filesystem. It also
|
||||
files, including `xyzac_switchkins_test_1.ngc`,
|
||||
`xyzac_switchkins_test_2.ngc`, `xyzac_switchkins_test_3.ngc`, and the larger
|
||||
`boat-xyzac.ngc`, `boat-xyzbc.ngc`, and `impeller-7bl-xyzac.ngc` demos, into
|
||||
the browser WASM filesystem. It also
|
||||
writes vendored LinuxCNC `xyzab-tdr` machine files and `xyzab-tdr-demo.ngc`
|
||||
into the browser WASM filesystem. It also writes vendored LinuxCNC bridge-mill
|
||||
machine files and `5axisgui.ngc` into the browser WASM filesystem. The browser
|
||||
smoke verifies `runFiveAxisRemapFile()` for the table-rotary-tilting,
|
||||
table-dual-rotary, and bridge-mill sample machines through the exported
|
||||
LinuxCNC remap/tool-table/file execution path.
|
||||
LinuxCNC remap/tool-table/file execution path. It also verifies the vendored
|
||||
LinuxCNC `configs/sim/axis/foam/foam.ngc`, `axis/geometry/xyzc.ngc`, and
|
||||
`axis/external_offsets/dyn_demo.ngc` programs through `runSimConfigProgram()`,
|
||||
which writes the browser WASM filesystem files and forwards to
|
||||
`runFileWithIni()`. It also verifies the bridge-mill
|
||||
`axis/vismach/5axis/bridgemill/5axisgui.ngc` program through
|
||||
`runSimConfigProgram()` with `executionMode: "fiveAxisRemap"`, which forwards
|
||||
to `runFiveAxisRemapFile()`. These paths use the real vendored executable
|
||||
`M110` and `M111` files for `USER_M_PATH` registration without spawning host
|
||||
processes. It
|
||||
also verifies the vendored
|
||||
LinuxCNC `tests/remap/duplicate-o-word`, NGC-only `tests/remap/fail/args.0`,
|
||||
`tests/remap/fail/args.1`, `tests/remap/fail/args.2`,
|
||||
`tests/remap/fail/body-ngc`, `tests/remap/m30-interaction`,
|
||||
`tests/remap/nested-remaps-oword`, `tests/remap/posargs.0`, and
|
||||
`tests/remap/sequencing` regressions through `runRemapFile()` or
|
||||
`runRemapFileContinueOnError()`, using the browser WASM filesystem and
|
||||
vendored LinuxCNC REMAP/O-word/file execution path without JavaScript remap
|
||||
semantics. It also writes the NGC-only vendored LinuxCNC
|
||||
`tests/remap/remap-io/test-ngc.ini` and `io_*.ngc` subroutines into the
|
||||
browser WASM filesystem and validates `runRemapIoMdiSequence()` through
|
||||
vendored LinuxCNC REMAP parsing and MDI execution without JavaScript M-code or
|
||||
I/O semantics. It also writes vendored LinuxCNC `tests/interp/do-while-break`,
|
||||
`tests/interp/oword-bug315`, `tests/interp/oword-bug315-p2`,
|
||||
`tests/interp/exists`, `tests/interp/return-value`,
|
||||
`tests/interp/subs-follow-main`, `tests/interp/fractional-linenumbers`,
|
||||
`tests/interp/namedparam-bug424`, and selected `tests/interp/rotation`
|
||||
`.ngc` files plus
|
||||
`tests/interp/sub-call-from-sub` `test.ini`, `test.ngc`, and `subs/*.ngc`
|
||||
files and `tests/interp/sequence-number` `test.ini`, `test.ngc`, and
|
||||
`rm400.ngc` plus `tests/interp/nested-sub-error` `test.ini`, `test.ngc`, and
|
||||
`subs/nested.ngc` and `tests/interp/nested-sub-in-file-error` `test.ini`,
|
||||
`test.ngc`, and `subs/sequential.ngc`, plus `tests/interp/abort-hot-comment`
|
||||
`test.ini` and `test.ngc`, plus `tests/interp/m19` `test.ini` and `test.ngc`,
|
||||
plus `tests/interp/magic_comments/param_format_printing` `test.ngc`,
|
||||
plus selected pure-interpreter `tests/interp/m98m99` cases covering
|
||||
Fanuc-style `M98/M99`, parameter scope, nested numbered subprograms,
|
||||
subprograms after main program text, leading-zero O-word lookup, named and
|
||||
numbered main programs, and expression-based O-sub/M98 calls,
|
||||
into the browser WASM filesystem and
|
||||
validates those upstream
|
||||
interpreter regressions through `runFile()` or `runFileWithIni()`, without
|
||||
JavaScript O-word, parameter, line-number, spindle-speed, spindle-orient,
|
||||
magic-comment formatting, M98/M99, subroutine lookup, or branch semantics.
|
||||
|
||||
The aggregate host smoke script builds the INI, interpreter-core, and
|
||||
trajectory-planner WASM artifacts once, then runs the Node WASM smokes, the
|
||||
@@ -240,7 +398,8 @@ The validation fails if:
|
||||
| `linuxcnc_interp_init_harness` | Validates vendored LinuxCNC `Interp::init()` emits canonical initialization boundaries, reads metric/inch machine units, and synchronizes current/selected tool slots through standalone status adapters. |
|
||||
| `linuxcnc_indexer_harness` | Validates vendored LinuxCNC single-axis rotary indexer dispatch emits lock/unlock and motion boundaries through the standalone event sink. |
|
||||
| `linuxcnc_remap_hal_sync_harness` | Validates vendored LinuxCNC `M68`/`M66` execution can drive the standalone HAL adapter boundary used by 5-axis switchkins remap files, including `_hal[motion.switchkins-type]` readback. |
|
||||
| `linuxcnc_5axis_remap_execute_harness` | Validates vendored LinuxCNC `REMAP` parsing plus NGC remap execution for the 5-axis `M429 -> M428 -> M430 -> M429` switchkins path in the `xyzac-trt` and `xyzbc-trt` sample machines, the two-remap `M429 -> M428 -> M429` path in the `xyzab-tdr` sample machine, and the bridge-mill `M429 -> M428 -> M430 -> M429` path where M428 selects the default bridge-mill kinematics. It loads vendored machine tool tables through LinuxCNC `tooldata_load()`, then runs vendored `xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`, `xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_3.ngc`, `boat-xyzac.ngc`, `boat-xyzbc.ngc`, `impeller-7bl-xyzac.ngc`, `xyzab-tdr-demo.ngc`, and `5axisgui.ngc` through the LinuxCNC file `open/read/execute` path. |
|
||||
| `linuxcnc_5axis_remap_execute_harness` | Validates vendored LinuxCNC `REMAP` parsing plus NGC remap execution for the 5-axis `M429 -> M428 -> M430 -> M429` switchkins path in the `xyzac-trt` and `xyzbc-trt` sample machines, the two-remap `M429 -> M428 -> M429` path in the `xyzab-tdr` sample machine, and the bridge-mill `M429 -> M428 -> M430 -> M429` path where M428 selects the default bridge-mill kinematics. It loads vendored machine tool tables through LinuxCNC `tooldata_load()`, then runs vendored `xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`, `xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_2.ngc`, `xyzac_switchkins_test_3.ngc`, `boat-xyzac.ngc`, `boat-xyzbc.ngc`, `impeller-7bl-xyzac.ngc`, `xyzab-tdr-demo.ngc`, and `5axisgui.ngc` through the LinuxCNC file `open/read/execute` path. |
|
||||
| `linuxcnc_duplicate_oword_remap_harness` | Validates vendored LinuxCNC upstream `tests/remap/duplicate-o-word`, NGC-only `tests/remap/fail/args.0`, `tests/remap/fail/args.1`, `tests/remap/fail/args.2`, `tests/remap/fail/body-ngc`, `tests/remap/m30-interaction`, `tests/remap/nested-remaps-oword`, `tests/remap/posargs.0`, `tests/remap/sequencing`, and the NGC-only `tests/remap/remap-io/test-ngc.ini` branch through LinuxCNC `REMAP` parsing, O-word remap dispatch, `OWORD_NARGS`, error-text reporting, G/M remap sequencing, remapped M62-M68/M66 MDI execution, and file `open/read/execute`. The standalone harness only supplies INI/file path setup, deterministic external input values, and canonical-event capture; it can continue after LinuxCNC errors for upstream `rs274 -n 0` style tests and does not implement duplicate-label, O-word, M30, positional-argument, failure, sequencing, M62-M68, M66 input, or remap semantics. |
|
||||
| `linuxcnc_tp_api_probe` | Validates vendored LinuxCNC trajectory planner calls for linear, arc, and queued motion paths. |
|
||||
| `linuxcnc_kinematics_probe` | Validates vendored LinuxCNC `trivkins.c` plus `kins_util.c` initialize and perform identity forward/inverse mapping through the standalone HAL/RTAPI boundary. |
|
||||
| `linuxcnc_5axis_kinematics_probe` | Validates vendored LinuxCNC `5axiskins.c` through `switchkins.c`, including 5-axis forward/inverse round-trip behavior and switching to identity kinematics. |
|
||||
@@ -265,11 +424,13 @@ The validation fails if:
|
||||
| Harness | Purpose |
|
||||
| --- | --- |
|
||||
| `tests/wasm/node/verify_ini_wasm.sh` | Validates the browser-facing INI WASM module can be built from vendored LinuxCNC `inifile.cc`, loaded through the JS SDK in Node, and queried through the exported C ABI, including LinuxCNC-backed boolean conversion and machine-session file-name string lookup. |
|
||||
| `tests/wasm/node/verify_interp_wasm.sh` | Validates the interpreter-core WASM module can be built from vendored LinuxCNC interpreter/remap source, loaded through the interpreter JS SDK, run the first fixture group through `Interp::execute()` and selected file fixtures through `Interp::open()`/`read()`/`execute()`, match the native canonical event plus required state readback fixtures, run vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo files through the WASM C ABI/SDK path, and run parameter-file restore/save through vendored LinuxCNC `Interp::restore_parameters()` and `Interp::save_parameters()`. |
|
||||
| `tests/wasm/node/verify_interp_wasm.sh` | Validates the interpreter-core WASM module can be built from vendored LinuxCNC interpreter/remap source, loaded through the interpreter JS SDK, run the first fixture group through `Interp::execute()` and selected file fixtures plus vendored upstream `tests/interp` regression files through `Interp::open()`/`read()`/`execute()`, match the native canonical event plus required state readback fixtures, run vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo files through the WASM C ABI/SDK path, and run parameter-file restore/save through vendored LinuxCNC `Interp::restore_parameters()` and `Interp::save_parameters()`. |
|
||||
| `tests/wasm/node/verify_sim_configs_wasm.sh` | Validates representative vendored LinuxCNC `configs/sim` programs in Node WASM through `runSimConfigProgram()`, copying `axis/foam`, `axis/geometry`, and `axis/external_offsets` INI/G-code/user-M assets into the Emscripten filesystem before forwarding to `runFileWithIni()`, plus bridge-mill `5axis.ini`, tool table, `remap_subs/*.ngc`, and `5axisgui.ngc` before forwarding to `runFiveAxisRemapFile()`. This covers INI-driven `U/V/W` axis mask handling, real `USER_M_PATH` registration for executable `M110`/`M111`, and vendored LinuxCNC bridge-mill NGC remap execution without spawning host processes. |
|
||||
| `tests/wasm/node/verify_nc_files_wasm.sh` | Validates representative vendored LinuxCNC `nc_files` examples in Node WASM by copying `arcspiral.ngc`, `hole-circle.ngc`, `factorial.ngc`, and `m6demo.ngc` into the Emscripten filesystem and forwarding to the LinuxCNC-backed `Interp::open()`/`read()`/`execute()` path. JavaScript only stages files and checks LinuxCNC output; it does not implement G-code, O-word, tool-change, or M-code behavior. |
|
||||
| `tests/wasm/node/verify_tp_wasm.sh` | Validates a standalone trajectory-planner WASM module can be built from vendored LinuxCNC TP/TC/Ruckig support source, loaded in Node, and run the same linear, arc, and queued-line planner probe paths covered by the native TP harness. |
|
||||
| `tests/opfs/node/verify_file_service.sh` | Validates the host-owned OPFS text-file adapter, path model, session snapshot store including custom filenames and envelope/path rejection paths, machine file store, G-code text store including filename rejection paths, OPFS-to-WASM parameter/tool-table bridges, and grouped machine-session loading without moving file persistence, parameter semantics, or tool-table semantics into the WASM core. |
|
||||
| `tests/browser/verify_ini_panel_browser.sh` | Validates the INI SDK, INI/interpreter WASM module loading, LinuxCNC-backed INI machine-session file-name string lookup, OPFS text-file round trip, generic session snapshot round trip plus custom filename and envelope/path rejection paths, machine file text round trip, G-code text round trip plus filename rejection paths, and the INI panel UI's machine-session load with default OPFS parameter/tool-table file mapping, G-code run, canonical-event display paths, and 5-axis remap demo action in a real browser runtime. |
|
||||
| `tests/browser/verify_interp_browser.sh` | Validates the interpreter-core WASM module loads through the interpreter JS SDK in a real browser runtime and runs selected positive and negative canonical fixtures through vendored LinuxCNC `Interp::execute()` plus `Interp::open()`/`read()`/`execute()` via the exported C ABI, including direct browser SDK and OPFS-backed parameter-file restore/save, non-random/random tool-table load/save through vendored LinuxCNC source, and vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo execution. |
|
||||
| `tests/browser/verify_interp_browser.sh` | Validates the interpreter-core WASM module loads through the interpreter JS SDK in a real browser runtime and runs selected positive and negative canonical fixtures plus vendored upstream `tests/interp` regression files through vendored LinuxCNC `Interp::execute()` and `Interp::open()`/`read()`/`execute()` via the exported C ABI, including direct browser SDK and OPFS-backed parameter-file restore/save, non-random/random tool-table load/save through vendored LinuxCNC source, vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo execution, representative vendored `configs/sim` `foam`, `geometry`, `external_offsets`, and bridge-mill programs through `runSimConfigProgram()`, and representative vendored `nc_files` examples through `runFile()`. |
|
||||
| `tests/host/verify_host_smokes.sh` | Runs the current host-side Node, WASM interpreter-core, WASM trajectory-planner, OPFS, and browser smoke validation with shared WASM builds. |
|
||||
|
||||
## Fixture Coverage
|
||||
@@ -593,7 +754,15 @@ comparable canonical runtime edge and program-end cleanup calls. The
|
||||
standalone vendored-source harness, Node WASM smoke, and browser smoke also
|
||||
pin `coordinate_offsets` MDI/file-path, `feed_control_modes`, the
|
||||
`position_params` MDI/file-path, `tool_semantics`, and `canon_runtime_edges`
|
||||
post-program modal, override, spindle, mist, and flood `_setup` state. The same upstream baseline also
|
||||
post-program modal, override, spindle, mist, and flood `_setup` state. Native
|
||||
and WASM standalone checks also cover the user M-code registration boundary for
|
||||
INI-declared `M110`/`M111` handlers while keeping process execution outside the
|
||||
browser/WASM runtime. Node and browser WASM sim-config coverage now run the real
|
||||
vendored `axis/geometry/xyzc.ngc` and
|
||||
`axis/external_offsets/dyn_demo.ngc` programs with their executable
|
||||
`M110`/`M111` files, `axis/foam/foam.ngc` with its `U/V` machine
|
||||
configuration, and bridge-mill `5axisgui.ngc` with its `W` machine
|
||||
coordinates. The same upstream baseline also
|
||||
validates the current negative fixture error text and absent canonical-event
|
||||
constraints. Fixtures that depend on standalone-only runtime
|
||||
adapters, HAL state, upstream `rs274` output gaps such as
|
||||
@@ -633,3 +802,38 @@ resulting `_setup.m_remapped` descriptors for each machine's LinuxCNC-defined
|
||||
`M428`/`M429`/`M430` set. Python callbacks remain runtime boundaries. Native
|
||||
and WASM validation now execute the NGC remap/file paths through vendored
|
||||
LinuxCNC O-word dispatch and the standalone HAL adapter boundary.
|
||||
|
||||
`linuxcnc_duplicate_oword_remap_harness` vendors LinuxCNC's upstream
|
||||
`tests/remap/duplicate-o-word` and `tests/remap/m30-interaction` files
|
||||
unchanged and runs each `test.ngc` with its `test.ini` through vendored
|
||||
`Interp::parse_remap()`, `open()`, `read()`, and `execute()`. Native, Node
|
||||
WASM, and browser interpreter validation assert the same successful LinuxCNC
|
||||
regression paths, including the remapped `M207`/`M208` messages and final
|
||||
`FINISH()` event for duplicate O-word, and the `M400 M30` remap-level
|
||||
interaction with `PROGRAM_END`.
|
||||
|
||||
`linuxcnc_interp_minimal_harness` now also runs selected vendored LinuxCNC
|
||||
upstream `tests/interp/*/test.ngc` files through vendored `Interp::open()`,
|
||||
`read()`, and `execute()`, using LinuxCNC INI `SUBROUTINE_PATH` for
|
||||
`tests/interp/sub-call-from-sub`, `tests/interp/sequence-number`, and
|
||||
`tests/interp/nested-sub-error`, `tests/interp/nested-sub-in-file-error`, and
|
||||
`tests/interp/abort-hot-comment`, plus LinuxCNC `[RS274NGC]ORIENT_OFFSET` for
|
||||
`tests/interp/m19`.
|
||||
Native, Node WASM, and browser interpreter validation assert the LinuxCNC
|
||||
canonical messages, canonical events, error texts, and interpreter state for
|
||||
O-word loop/break/subroutine paths, dynamic O-word calls, `EXISTS[]`,
|
||||
subroutine return values, subroutines after main programs, fractional line
|
||||
numbers, named-parameter parsing, M19 spindle-orient offset and wait timeout
|
||||
canonical events, magic-comment parameter formatting, valid external subroutine calls from another
|
||||
external subroutine, external-subroutine `#<_line>` reporting,
|
||||
nested-subroutine-definition rejection, and blocked forward seek to a later
|
||||
numbered subroutine in the same external file, selected `tests/interp/rotation`
|
||||
absolute-position `#<_abs_x>`, `#<_abs_y>`, and `#<_abs_z>` reporting under
|
||||
G54, G92, XY rotation, and unit changes plus rotated-coordinate `G28` and
|
||||
`G53` endpoint behavior, selected `tests/interp/m98m99`
|
||||
Fanuc-style `M98/M99` subprogram calls, parameter-scope differences,
|
||||
nested numbered subprograms, subprograms after main program text,
|
||||
leading-zero O-word lookup, named/numbered main programs, and O-expression
|
||||
calls, plus `(ABORT,...)` hot-comment numbered, named, and INI-parameter
|
||||
expansion, with skipped branch/subroutine messages and post-abort program end
|
||||
asserted absent where applicable.
|
||||
|
||||
@@ -45,6 +45,7 @@ semantic rewrites:
|
||||
| Go math C/C++ linkage | `genserkins` runtime probing compiles vendored `gomath.c` through a narrow C++ wrapper so LinuxCNC `genserfuncs.c` can link to the upstream Go math symbols without editing vendored source. |
|
||||
| Switchkins iterative forward | `genhexkins` runtime probing follows LinuxCNC switchkins iterative-forward behavior, including the first-call warmup path before asserting roundtrip convergence. |
|
||||
| Browser storage | OPFS remains outside the native core; `runtime/opfs/file-service.js` owns browser text-file persistence, `runtime/opfs/path-model.js` owns host-side storage paths for INI, tool table, parameter, G-code, preview-cache, and session-snapshot content, `runtime/opfs/snapshot-store.js` owns generic JSON session snapshot persistence, `runtime/opfs/machine-file-store.js` owns pure-text machine-file and G-code persistence, `runtime/opfs/linuxcnc-parameter-bridge.js` only copies parameter files between OPFS text storage and the LinuxCNC-backed WASM parameter-file ABI, `runtime/opfs/linuxcnc-tool-table-bridge.js` only copies tool tables between OPFS text storage and the LinuxCNC-backed WASM tool-table ABI, and `runtime/opfs/linuxcnc-machine-session-bridge.js` groups INI, parameter, and tool-table loading while using the LinuxCNC-backed INI SDK for `[EMCIO]RANDOM_TOOLCHANGER`, `[RS274NGC]PARAMETER_FILE`, and `[EMCIO]TOOL_TABLE` when available; explicit host session file-name options take precedence over INI-derived file names, missing INI file-name values fall back to host default parameter/tool-table paths, and path validation remains owned by the OPFS path model, including rejection of traversal or nested path segments from INI-derived file names. |
|
||||
| Sim-config SDK staging | `runtime/sdk/src/linuxcnc-interp.js` exposes `runSimConfigProgram()` as a host-boundary convenience only. It writes caller-provided text files into the Emscripten filesystem, applies executable bits for user M-code files, and forwards to existing LinuxCNC-backed C ABI entry points such as `runFileWithIni()` or `runFiveAxisRemapFile()`; it does not implement interpreter, axis, remap, or user M-code semantics. |
|
||||
|
||||
## Enforced Non-Drift Rules
|
||||
|
||||
@@ -78,7 +79,9 @@ semantic rewrites:
|
||||
paths.
|
||||
- Host-side smoke validation is aggregated by
|
||||
`tests/host/verify_host_smokes.sh` so Node, WASM, OPFS, and browser checks
|
||||
run from one command.
|
||||
run from one command. The current aggregate run passes with
|
||||
`host_wasm_opfs_browser_smokes=ok`, including the Node and browser
|
||||
sim-config paths staged through `runSimConfigProgram()`.
|
||||
- Identity/trivial, `5axiskins`, TRT `xyzac`/`xyzbc`, delta, SCARA, PUMA,
|
||||
serial, hexapod, pentapod, and related kinematics sources now have native
|
||||
source-probe coverage.
|
||||
|
||||
165
wasm-port/docs/linuxcnc-test-porting-tracker.md
Normal file
165
wasm-port/docs/linuxcnc-test-porting-tracker.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# LinuxCNC Test Porting Tracker
|
||||
|
||||
## Purpose
|
||||
|
||||
This file tracks the continuing work to validate this simulation port against
|
||||
LinuxCNC behavior by using LinuxCNC's own source files and test assets.
|
||||
|
||||
Hard rule: CNC semantics must come directly from LinuxCNC source. Project-owned
|
||||
code may provide build logic, runtime shims, filesystem adapters, C ABI, SDK,
|
||||
browser UI, and test runners, but must not reimplement interpreter, remap, tool,
|
||||
parameter, kinematics, planner, or machine-control behavior.
|
||||
|
||||
## Fixed Validation Gates
|
||||
|
||||
Run these checks as the baseline for every substantial porting step:
|
||||
|
||||
```bash
|
||||
wasm-port/tools/verify_upstream_baseline.sh
|
||||
wasm-port/tools/verify_vendor_sync.sh
|
||||
wasm-port/tests/native/verify_native_probes.sh
|
||||
wasm-port/tests/native/verify_nc_files.sh
|
||||
wasm-port/tests/wasm/node/verify_ini_wasm.sh
|
||||
wasm-port/tests/wasm/node/verify_interp_wasm.sh
|
||||
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
|
||||
wasm-port/tests/wasm/node/verify_nc_files_wasm.sh
|
||||
wasm-port/tests/wasm/node/verify_tp_wasm.sh
|
||||
wasm-port/tests/opfs/node/verify_file_service.sh
|
||||
wasm-port/tests/browser/verify_ini_panel_browser.sh
|
||||
wasm-port/tests/browser/verify_interp_browser.sh
|
||||
wasm-port/tests/host/verify_host_smokes.sh
|
||||
```
|
||||
|
||||
## Status Legend
|
||||
|
||||
| Status | Meaning |
|
||||
| --- | --- |
|
||||
| Done | Native, WASM, browser, docs, and source-sync validation are complete for the current scope. |
|
||||
| In progress | Test assets or runners are present, but coverage still needs extension or verification. |
|
||||
| Planned | The item is selected for future work. |
|
||||
| Blocked | The item needs missing LinuxCNC source, runtime boundary work, or upstream baseline clarification. |
|
||||
|
||||
## Continuing Steps
|
||||
|
||||
| Step | Status | Tracking notes |
|
||||
| --- | --- | --- |
|
||||
| Lock LinuxCNC upstream baseline | Done | Baseline commit is recorded in `wasm-port/tools/upstream-baseline.txt`; keep `docs/scope-and-baseline.md` synchronized when it changes. |
|
||||
| Verify vendored source byte identity | Done | `tools/verify_vendor_sync.sh` must pass for every file in `tools/source-manifest.txt`. |
|
||||
| Reject standalone CNC semantics | Done | `tools/verify_no_standalone_cnc_semantics.sh` guards project-owned `Interp::...` definitions outside documented runtime-edge stubs. |
|
||||
| Maintain source reuse map | Done | Current sim-config, remap, interpreter, kinematics, TP, user-M, tool, named-parameter, and OPFS runtime boundaries are recorded in `docs/source-reuse-map.md`; keep updating it whenever LinuxCNC source, test assets, or runtime boundaries are added. |
|
||||
| Maintain compatibility validation notes | Done | Current native, Node WASM, browser, OPFS, and host aggregate checks are recorded in `docs/compatibility-validation.md`; keep updating it whenever a validation command or fixture class is added. |
|
||||
| Build LinuxCNC test inventory | In progress | `linuxcnc/tests/remap` has been inventoried by dependency class; the first broader `linuxcnc/tests` pass now records full-process, HAL/realtime, linuxcncrsh, Python-binding, and external-component families in the blocked table. |
|
||||
| Prefer pure interpreter tests first | In progress | Continue with tests that can run through `Interp::open()`, `read()`, and `execute()` without realtime hardware or GUI. |
|
||||
| Add upstream-output comparison | In progress | Use upstream `../linuxcnc/bin/rs274` or original `test.sh` output where practical, then compare against native/WASM/browser output. |
|
||||
| Promote tests through three layers | In progress | Add each selected test first to native harnesses, then WASM Node, then browser smoke where meaningful. |
|
||||
| Record blocked tests | In progress | First broader family-level blocked batch is recorded below; continue expanding it as each `linuxcnc/tests` family is inspected. |
|
||||
| Add aggregate smoke coverage | Done | `tests/host/verify_host_smokes.sh` now runs stable Node WASM, sim-config WASM, `nc_files` WASM, OPFS, and browser smoke checks with shared builds. Current run passed with `host_wasm_opfs_browser_smokes=ok`. |
|
||||
| Add `linuxcnc/nc_files` basic examples | Done | `tests/native/verify_nc_files.sh` now runs the basic/example subset of upstream `linuxcnc/nc_files` through LinuxCNC `bin/rs274`; current native baseline is 107 total, 101 pass, 6 expected context/entry-point edges, 0 unexpected failures. Exploratory `--all` inventory is 247 total, 219 pass, 28 expected context/entry-point edges, 0 unexpected failures. A representative vendored subset now passes Node WASM and browser execution through LinuxCNC-backed `Interp::open()`/`read()`/`execute()`. |
|
||||
|
||||
## LinuxCNC Test Asset Queue
|
||||
|
||||
| LinuxCNC test path | Status | Current target | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| `nc_files` basic/example programs | Done | Native, WASM Node, browser | Native coverage is tracked by `wasm-port/tests/native/verify_nc_files.sh`; complete programs execute strictly, macro/library files are wrapped with temporary `M2` for load/parse validation, and six known LinuxCNC-native context edges are classified explicitly. `--all` also inventories probe/plasmac/NURBS files and currently classifies all 28 non-passing files as expected runtime-context or entry-point edges. The representative vendored WASM/browser subset covers `arcspiral.ngc`, `hole-circle.ngc`, `factorial.ngc`, and `m6demo.ngc` through LinuxCNC-backed file execution only. |
|
||||
| `tests/remap/duplicate-o-word` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word`; validates duplicate O-word behavior through vendored LinuxCNC remap/O-word/file execution paths. |
|
||||
| `tests/remap/fail/args.0` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/fail/args.0`; validates required `P`/`Q` remap arguments when both are present through vendored LinuxCNC remap argument handling. |
|
||||
| `tests/remap/fail/args.1` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/fail/args.1`; validates LinuxCNC missing-`Q` remap error text and upstream-style continue-after-error flow. |
|
||||
| `tests/remap/fail/args.2` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/fail/args.2`; validates LinuxCNC missing-`P,Q` remap error text and upstream-style continue-after-error flow. |
|
||||
| `tests/remap/fail/body-ngc` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc`; validates LinuxCNC NGC remap body failure text and remap level restoration after continue-on-error execution. |
|
||||
| `tests/remap/m30-interaction` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/m30-interaction`; validates LinuxCNC remap/M30 interaction through vendored interpreter paths. |
|
||||
| `tests/remap/nested-remaps-oword` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword`; validates nested NGC remaps through vendored LinuxCNC O-word dispatch. |
|
||||
| `tests/remap/posargs.0` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/posargs.0`; validates LinuxCNC positional remap arguments and `OWORD_NARGS` through vendored interpreter paths. |
|
||||
| `tests/remap/sequencing` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/sequencing`; validates LinuxCNC G/M remap execution ordering through vendored interpreter paths. |
|
||||
| `tests/remap/remap-io` NGC-only branch | Done | Native, WASM Node, browser | Vendored `test-ngc.ini` plus `io_*.ngc` subroutines validate LinuxCNC NGC remaps for M62-M68 and M66 immediate input through vendored `Interp::parse_remap()` and `Interp::execute()`; the standalone boundary only stages inputs and captures canonical events. |
|
||||
| `tests/interp/do-while-break` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/do-while-break`; validates LinuxCNC O-word do/while/break flow through vendored `Interp::open()`, `read()`, and `execute()` paths. |
|
||||
| `tests/interp/oword-bug315` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/oword-bug315`; validates LinuxCNC O-word break-out-of-subroutine behavior through vendored file execution paths. |
|
||||
| `tests/interp/oword-bug315-p2` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2`; validates LinuxCNC dynamic O-word subroutine call selection through vendored file execution paths. |
|
||||
| `tests/interp/exists` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/exists`; validates LinuxCNC `EXISTS[]` parameter handling through vendored file execution paths. |
|
||||
| `tests/interp/return-value` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/return-value`; validates LinuxCNC O-word return-value and `#<_value>` behavior through vendored file execution paths. |
|
||||
| `tests/interp/subs-follow-main` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/subs-follow-main`; validates LinuxCNC subroutines after main program text through vendored file execution paths. |
|
||||
| `tests/interp/fractional-linenumbers` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers`; validates LinuxCNC fractional line-number parsing through vendored file execution paths. |
|
||||
| `tests/interp/namedparam-bug424` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424`; validates LinuxCNC named-parameter parsing regression behavior through vendored file execution paths. |
|
||||
| `tests/interp/rotation` selected pure interpreter cases | Done | Native, WASM Node, browser | Vendored selected upstream cases under `wasm-port/vendor/linuxcnc/tests/interp/rotation`; validates LinuxCNC machine-coordinate `G53` absolute-position named parameters `#<_abs_x>`, `#<_abs_y>`, and `#<_abs_z>` across G54 offsets, G92 offsets, XY rotation, and inch/millimeter modes, plus rotated-coordinate `G28` and `G53` endpoint behavior through vendored file execution paths. |
|
||||
| `tests/interp/iniparam` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/iniparam`; validates LinuxCNC `_ini[...]` lookup, missing INI-parameter error text, and continued file execution through vendored file execution paths and `INI_FILE_NAME`. |
|
||||
| `tests/interp/iniparam-failassign` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign`; validates LinuxCNC `_ini[...]` read-only named-parameter assignment rejection through vendored file execution paths and `INI_FILE_NAME`. |
|
||||
| `tests/interp/m19` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/m19`; validates LinuxCNC `M19` spindle orient canonical events, wait timeout, and `[RS274NGC]ORIENT_OFFSET` handling through vendored file execution paths. |
|
||||
| `tests/interp/magic_comments/param_format_printing` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/magic_comments/param_format_printing`; validates LinuxCNC `(DEBUG,...)` magic-comment parameter formatting for integer, default float, and explicit precision formats through vendored file execution paths. |
|
||||
| `tests/interp/m98m99` selected pure interpreter cases | Done | Native, WASM Node, browser | Vendored selected upstream cases under `wasm-port/vendor/linuxcnc/tests/interp/m98m99`; validates LinuxCNC Fanuc-style `M98/M99`, parameter scope, nested numbered subprograms, subprograms after main program text, leading-zero O-word lookup, named and numbered main programs, and expression-based O-sub/M98 calls through vendored file execution paths. |
|
||||
| `tests/interp/sub-call-from-sub` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub`; validates LinuxCNC external subroutine calls from another external subroutine through vendored file execution paths and LinuxCNC INI `SUBROUTINE_PATH`. |
|
||||
| `tests/interp/sequence-number` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/sequence-number`; validates LinuxCNC `#<_line>` reporting in main files and external subroutines through vendored file execution paths and LinuxCNC INI `SUBROUTINE_PATH`. |
|
||||
| `tests/interp/nested-sub-error` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error`; validates LinuxCNC nested-subroutine-definition rejection through vendored file execution paths and LinuxCNC INI `SUBROUTINE_PATH`. |
|
||||
| `tests/interp/nested-sub-in-file-error` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error`; validates LinuxCNC rejection of forward seek to a later numbered subroutine in the same external subroutine file through vendored file execution paths and LinuxCNC INI `SUBROUTINE_PATH`. |
|
||||
| `tests/interp/abort-hot-comment` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment`; validates LinuxCNC `(ABORT,...)` hot-comment parameter expansion for numbered, named, and INI named parameters through vendored file execution paths and `INI_FILE_NAME`. |
|
||||
| `configs/sim/axis/foam/foam.ngc` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/configs/sim/axis/foam`; validates LinuxCNC INI-driven `U/V` axis mask handling through `axis_foam.ini` and vendored file execution paths. |
|
||||
| `configs/sim/axis/geometry/xyzc.ngc` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/configs/sim/axis/geometry`; validates LinuxCNC `USER_M_PATH` registration with the real executable `M110` while process execution remains a deterministic standalone `USER_M_COMMAND` boundary. |
|
||||
| `configs/sim/axis/external_offsets/dyn_demo.ngc` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets`; validates LinuxCNC `USER_M_PATH` registration with the real executable `M111` against an upstream sim program while process execution remains a deterministic standalone boundary. |
|
||||
| More `tests/remap/*` interpreter-only cases | Planned | Native first | Select cases that do not require Python behavior beyond documented runtime-edge stubs unless the required LinuxCNC source path is ported. |
|
||||
| More `tests/interp/*` interpreter-only cases | Planned | Native first | Select upstream interpreter cases that can run through vendored file execution without Python, HAL, realtime motion, or GUI. |
|
||||
| `tests/rs274ngc/*` candidates | Planned | Native first | Use upstream `rs274` as the baseline where output is comparable. |
|
||||
| Tool-table regression assets | Planned | Native and WASM Node | Must call vendored `tooldata_common.cc`; project code may only provide storage callbacks and filesystem boundaries. |
|
||||
| Kinematics tests | Planned | Native probes first | Add runtime probes only around LinuxCNC kinematics entry points; HAL lifecycle remains a shim boundary. |
|
||||
| Trajectory-planner tests | Planned | Native then WASM Node | Must call vendored LinuxCNC TP APIs; project code may only seed deterministic status/config state. |
|
||||
|
||||
## Per-Test Intake Checklist
|
||||
|
||||
Use this checklist when adding each LinuxCNC upstream test:
|
||||
|
||||
- Record the upstream test path.
|
||||
- Copy or extract the original LinuxCNC files into `wasm-port/vendor/linuxcnc/`.
|
||||
- Add the copied files to the relevant manifest or vendor-sync rule.
|
||||
- Keep `.ini`, `.ngc`, `expected`, and original support files unchanged.
|
||||
- Identify the LinuxCNC source files that own the behavior being tested.
|
||||
- Add native runner coverage that calls vendored LinuxCNC code.
|
||||
- Add WASM Node coverage through the exported C ABI and SDK filesystem bridge.
|
||||
- Add browser coverage if the behavior crosses SDK, OPFS, or UI boundaries.
|
||||
- Compare against upstream LinuxCNC output where practical.
|
||||
- Update `docs/source-reuse-map.md`.
|
||||
- Update `docs/compatibility-validation.md`.
|
||||
- Add any blocked dependency to the blocked-test table below.
|
||||
|
||||
## Blocked Test Table
|
||||
|
||||
| LinuxCNC test path | Status | Blocking dependency | Next action |
|
||||
| --- | --- | --- | --- |
|
||||
| `tests/remap/introspect` | Blocked | Python remap modules and Python interpreter introspection. | Port or expose the required LinuxCNC Python remap runtime boundary before executing. |
|
||||
| `tests/remap/fail/body-py` | Blocked | Python remap body error path. | Port the LinuxCNC Python remap body boundary before executing. |
|
||||
| `tests/remap/fail/canon_error` | Blocked | Python prolog plus `emccanon.CANON_ERROR`. | Port LinuxCNC Python prolog and canonical-error boundary before executing. |
|
||||
| `tests/remap/fail/epilog` | Blocked | Python epilog failure path. | Port LinuxCNC Python epilog boundary before executing. |
|
||||
| `tests/remap/fail/prolog` | Blocked | Python prolog failure path. | Port LinuxCNC Python prolog boundary before executing. |
|
||||
| `tests/remap/oword-pycall` | Blocked | Python O-word callable modules plus tool-change path. | Port the LinuxCNC Python O-word call boundary and required tool-change runtime edges. |
|
||||
| `tests/remap/predefined-named-params` | Blocked | Python predefined named parameters. | Port the LinuxCNC Python named-parameter registration boundary. |
|
||||
| `tests/remap/remap-io` full process/UI branch | Blocked | Full LinuxCNC process, HAL pins, motion I/O status propagation, and Python UI/test driver. | Keep the full process test upstream-only until those runtime boundaries exist; the NGC-only `test-ngc.ini` subpath is covered separately above. |
|
||||
| `tests/remap/remap-reentry` | Blocked | Python generator remaps, HAL/motion runtime, and remap reentry. | Port LinuxCNC Python generator remap boundary and motion/HAL synchronization first. |
|
||||
| `tests/remap/spindle` | Blocked | Python remap body and spindle runtime state. | Port the LinuxCNC Python remap boundary and spindle status adapter. |
|
||||
| `tests/remap/variable-injection` | Blocked | Python prolog/epilog variable injection. | Port LinuxCNC Python prolog/epilog boundary before executing. |
|
||||
| `tests/abort/*` | Blocked | Full LinuxCNC task/motion process, abort/stop handling, HAL files, and machine state after interruption. | Keep as upstream process reference until task/motion abort boundaries are available; do not reduce to standalone interpreter execution. |
|
||||
| `tests/ccomp/early-exit` | Blocked | Full LinuxCNC process and motion-position validation after cutter-compensation early exit. | Use interpreter-only `tests/ccomp/*` cases first; revisit after motion state comparison is available. |
|
||||
| `tests/classicladder/estop` | Blocked | ClassicLadder component, full LinuxCNC process, HAL files, and UI driver. | Keep as upstream-only reference until ClassicLadder/HAL process boundaries are represented. |
|
||||
| `tests/halui/*` | Blocked | Full LinuxCNC process with `halui`, postgui HAL files, and UI/test driver interaction. | Establish HALUI/task runtime boundaries before porting. |
|
||||
| `tests/hard-limits` | Blocked | Full LinuxCNC machine process, HAL limit wiring, and motion limit behavior. | Keep as upstream process reference until motion/HAL limit boundaries exist. |
|
||||
| `tests/inifile/python_bindings` | Blocked | LinuxCNC Python INI bindings, not just vendored C++ `inifile.cc`. | Add only after a Python binding boundary is intentionally exposed, or keep covered by upstream. |
|
||||
| `tests/io-startup/*` | Blocked | Full LinuxCNC `io` startup, task process, HAL files, and postgui setup. | Revisit after IO/task startup runtime boundaries are represented. |
|
||||
| `tests/linuxcncrsh` | Blocked | Full LinuxCNC process plus `linuxcncrsh` socket protocol server. | Keep as upstream integration reference until linuxcncrsh/server boundaries are intentionally ported. |
|
||||
| `tests/linuxcncrsh-tcp` | Blocked | Full LinuxCNC process plus TCP socket service and network timing. | Keep as upstream integration reference until linuxcncrsh/server boundaries are intentionally ported. |
|
||||
| `tests/mdi-queue/*` | Blocked | Full LinuxCNC task/MDI queue behavior through linuxcncrsh, tool changes, and queued command synchronization. | Port only after task queue and linuxcncrsh boundaries are available. |
|
||||
| `tests/motion/*` | Blocked | Full LinuxCNC sim process, HAL pins, linuxcncrsh, halsampler, and realtime motion behavior. | Keep as upstream motion integration reference; prefer standalone TP/kinematics probes for now. |
|
||||
| `tests/motion-logger/*` | Blocked | Full LinuxCNC process plus motion-logger userspace program and mock-motion HAL setup. | Revisit after motion logging/runtime process boundaries are represented. |
|
||||
| `tests/halcompile/*` | Blocked | LinuxCNC HAL component build/install flow, often including userspace or realtime component loading. | Keep as build-system/HAL integration reference; do not treat as interpreter semantics. |
|
||||
| `tests/module-loading/*` | Blocked | HAL realtime module loading and RTAPI lifecycle through `halrun`/`loadrt`. | Covered only by narrow source/native probes today; full HAL module loading remains out of scope. |
|
||||
| `tests/mb2hal/*` | Blocked | External `mb2hal` userspace component, Modbus I/O behavior, and HAL process wiring. | Keep as external-component integration reference until a host I/O boundary exists. |
|
||||
| `tests/t0/*` | Blocked | Full LinuxCNC process, linuxcncrsh display, tool table startup, random/nonrandom toolchanger behavior, and HAL files. | Continue validating tool tables through vendored `tooldata_common.cc`; revisit full T0 startup through task/IO boundaries later. |
|
||||
| `tests/tool-info/*` | Blocked | Full LinuxCNC task/IO startup with HALUI, startup tool state, and random/nonrandom toolchanger process behavior. | Keep tool parsing/formatting in standalone probes; revisit process startup behavior later. |
|
||||
| `tests/toolchanger/*` | Blocked | Full LinuxCNC tool-change process, MDI/task behavior, IO state, and subroutine/user-M paths. | Continue standalone interpreter/tooldata coverage first; revisit after task/IO tool-change boundaries exist. |
|
||||
| `tests/trajectory-planner/circular-arcs` | Blocked | Full LinuxCNC sim configs with task, HAL/Tcl files, GUI/display settings, and motion execution logs. | Keep using standalone TP API probes for planner code; full circular-arc machine tests require task/HAL/motion boundaries. |
|
||||
| `tests/lowlevel/emcmot-error-mpsc` | Blocked | RIP-only build against LinuxCNC motion sources and low-level motion error driver. | Revisit only if low-level motion process test drivers are intentionally ported. |
|
||||
| `tests/uspace/spawnv-root` | Blocked | Sudo-installed userspace HAL component and `spawnv` root behavior. | Keep upstream-only unless HAL component install/runtime support is added. |
|
||||
|
||||
## Next Work Batch
|
||||
|
||||
1. Continue inventorying `linuxcnc/tests/interp/*` for additional pure
|
||||
interpreter cases that can run through vendored file execution without full
|
||||
task/HAL/motion process state.
|
||||
2. Keep adding skipped upstream families to the blocked-test table with a
|
||||
concrete dependency reason before attempting implementation.
|
||||
3. Run `wasm-port/tests/browser/verify_interp_browser.sh` and then
|
||||
`wasm-port/tests/host/verify_host_smokes.sh` after each stable batch.
|
||||
@@ -809,24 +809,33 @@ Current five-axis switchkins status:
|
||||
bridge-mill kinematics, loads vendored machine tool tables through
|
||||
LinuxCNC `tooldata_load()`, and runs vendored `xyzac_switchkins.ngc`,
|
||||
`xyzbc_switchkins.ngc`,
|
||||
`xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_3.ngc`,
|
||||
`boat-xyzac.ngc`, `boat-xyzbc.ngc`, `impeller-7bl-xyzac.ngc`, and
|
||||
`xyzab-tdr-demo.ngc`, plus bridge-mill `5axisgui.ngc` through LinuxCNC
|
||||
remap/file execution paths.
|
||||
`xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_2.ngc`,
|
||||
`xyzac_switchkins_test_3.ngc`, `boat-xyzac.ngc`, `boat-xyzbc.ngc`,
|
||||
`impeller-7bl-xyzac.ngc`, and `xyzab-tdr-demo.ngc`, plus bridge-mill
|
||||
`5axisgui.ngc` through LinuxCNC remap/file execution paths.
|
||||
7. The WASM interpreter core now links vendored `interp_remap.cc` plus the
|
||||
Python-only runtime edge stub, and the Node WASM smoke runs vendored
|
||||
`xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`, `boat-xyzac.ngc`, and
|
||||
`boat-xyzbc.ngc`, `impeller-7bl-xyzac.ngc`, `xyzab-tdr-demo.ngc`, and
|
||||
`5axisgui.ngc` through the SDK C ABI without JavaScript M-code or
|
||||
kinematics semantics.
|
||||
`xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`,
|
||||
`xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_2.ngc`,
|
||||
`xyzac_switchkins_test_3.ngc`, `boat-xyzac.ngc`, `boat-xyzbc.ngc`,
|
||||
`impeller-7bl-xyzac.ngc`, `xyzab-tdr-demo.ngc`, and `5axisgui.ngc`
|
||||
through the SDK C ABI without JavaScript M-code or kinematics semantics.
|
||||
8. Browser smoke and the INI panel UI now expose the same validated 5-axis
|
||||
remap execution path by copying vendored LinuxCNC sample-machine files into
|
||||
the interpreter WASM filesystem and calling the SDK C ABI.
|
||||
9. LinuxCNC upstream `tests/remap/duplicate-o-word` and
|
||||
`tests/remap/m30-interaction` are now vendored unchanged and validated
|
||||
through the generic remap file execution path. Native, Node WASM, and
|
||||
browser interpreter smokes load the vendored INI, program, and remap
|
||||
subroutines, then call vendored `Interp::parse_remap()`, `open()`,
|
||||
`read()`, and `execute()`; standalone code only supplies the INI/file path
|
||||
boundary.
|
||||
|
||||
Next work:
|
||||
|
||||
1. Continue broadening five-axis fixture coverage through the same
|
||||
source-backed execution boundary.
|
||||
1. Continue broadening source-backed remap coverage through LinuxCNC upstream
|
||||
tests that can run through NGC REMAP/O-word/file execution without Python
|
||||
semantics.
|
||||
2. Evaluate additional vendored LinuxCNC five-axis sample machines and demos
|
||||
after the TRT boat/impeller, TDR demo, and bridge-mill demo paths are
|
||||
stable in native, Node WASM, browser, and UI remap paths.
|
||||
|
||||
486
wasm-port/docs/sim-configs-completion-plan.md
Normal file
486
wasm-port/docs/sim-configs-completion-plan.md
Normal file
@@ -0,0 +1,486 @@
|
||||
# LinuxCNC Sim Config Completion Plan
|
||||
|
||||
This plan tracks the work needed to run the LinuxCNC programs under
|
||||
`linuxcnc/configs/sim` through the standalone native/WASM simulation runtime.
|
||||
LinuxCNC source remains the semantic source of truth. Port code must live under
|
||||
`wasm-port/`; do not edit `linuxcnc/` in place.
|
||||
|
||||
## Current Baseline
|
||||
|
||||
The latest strict harness run used `linuxcnc/configs/sim` as the program source,
|
||||
selected the nearest INI/tool table for each `.ngc` unless an explicit sim
|
||||
mapping is required, and ran `rs274` from the INI directory so relative
|
||||
`SUBROUTINE_PATH` and `REMAP` entries resolve like a real sim config.
|
||||
|
||||
Result file:
|
||||
|
||||
```text
|
||||
wasm-port/build/native/sim-configs/summary.tsv
|
||||
```
|
||||
|
||||
Baseline:
|
||||
|
||||
```text
|
||||
total: 159
|
||||
pass: 151
|
||||
fail: 8
|
||||
timeout: 0
|
||||
expected_fail: 8
|
||||
unexpected_fail: 0
|
||||
|
||||
main: PASS 40, FAIL 8
|
||||
macro_load: PASS 46, FAIL 0
|
||||
remap_subroutine: PASS 65, FAIL 0
|
||||
```
|
||||
|
||||
Remaining failures are explicit LinuxCNC-native baseline edges:
|
||||
|
||||
- `axis/external_offsets/*`: 4 failures from sim-only user M-codes `M111`.
|
||||
- `axis/geometry/xyzc.ngc`: 1 failure from sim-only user M-code `M110`.
|
||||
- `axis/foam/foam.ngc`: 1 failure from missing `U/V` axis support in the
|
||||
LinuxCNC `bin/rs274` entry point.
|
||||
- `axis/vismach/5axis/bridgemill/5axisgui.ngc`: 1 failure from missing `W`
|
||||
axis support in the LinuxCNC `bin/rs274` entry point.
|
||||
- `axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_g533.ngc`:
|
||||
1 failure from an upstream demo line that uses bare `X/Y/Z` words after
|
||||
`G53.6` without an explicit motion G-code.
|
||||
|
||||
## Target
|
||||
|
||||
The first target is not a browser UI feature. It is a repeatable native and
|
||||
WASM simulation harness that can load and execute all `linuxcnc/configs/sim`
|
||||
programs that are meaningful in a standalone non-hardware simulation context.
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
- The native sim-config harness reports all executable sim programs as `PASS`.
|
||||
- Macro/remap files are validated by the correct entry point: direct execution
|
||||
only for real programs, load/parse or remap-call validation for subroutines.
|
||||
- WASM tests cover the same representative classes after the native harness is
|
||||
green.
|
||||
- Any remaining unsupported files are explicitly classified as native GUI or
|
||||
hardware-only and excluded by rule, not by accident.
|
||||
|
||||
## Phase 1: Make The Harness A First-Class Test
|
||||
|
||||
Status: complete. The tracked script exists and is wired into the native
|
||||
validation entry point.
|
||||
|
||||
1. Add a tracked script:
|
||||
|
||||
```text
|
||||
wasm-port/tests/native/verify_sim_configs.sh
|
||||
```
|
||||
|
||||
2. Move the ad hoc test logic into the script:
|
||||
|
||||
- scan only `linuxcnc/configs/sim`;
|
||||
- identify `.ngc`, nearest `.ini`, nearest `.tbl`;
|
||||
- run from the INI directory;
|
||||
- write `summary.tsv`, stdout, stderr, and interpreter output under
|
||||
`wasm-port/build/native/sim-configs/`;
|
||||
- classify programs as `main`, `macro_load`, `remap_subroutine`, or
|
||||
`unsupported_runtime_edge`;
|
||||
- fail the script only on unexpected failures.
|
||||
|
||||
3. Add deterministic classification rules:
|
||||
|
||||
- files under `remap_subs/` and `nc_subroutines/` are not standalone main
|
||||
programs;
|
||||
- files with no `M2`, `M30`, or `%` are load/parse fixtures unless the INI
|
||||
references them through `REMAP`;
|
||||
- user M-code files are tested through `USER_M_PATH` resolution, not by
|
||||
pretending LinuxCNC native process services exist.
|
||||
|
||||
4. Wire the script into existing validation:
|
||||
|
||||
```text
|
||||
wasm-port/tests/native/verify_native_probes.sh
|
||||
```
|
||||
|
||||
5. Completion check:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/native/verify_sim_configs.sh
|
||||
```
|
||||
|
||||
Latest result:
|
||||
|
||||
```text
|
||||
total: 159
|
||||
pass: 151
|
||||
fail: 8
|
||||
timeout: 0
|
||||
expected_fail: 8
|
||||
unexpected_fail: 0
|
||||
skipped: 0
|
||||
```
|
||||
|
||||
## Phase 2: Load Machine Axes From INI
|
||||
|
||||
Status: partially complete for the port runtime. The standalone native/WASM
|
||||
runtime now parses `[TRAJ] COORDINATES`, updates the standalone external axis
|
||||
mask used by LinuxCNC `GET_EXTERNAL_AXIS_MASK()`, and applies the same
|
||||
`Interp::_readers` filtering that upstream `rs274ngc_pre.cc` uses. Native
|
||||
regression coverage verifies that `axis_foam.ini` enables `U/V` readers and
|
||||
`bridgemill/5axis.ini` enables the `W` reader.
|
||||
|
||||
The `verify_sim_configs.sh` baseline still records the LinuxCNC `bin/rs274`
|
||||
entry-point failures as expected failures. That harness is intentionally kept
|
||||
as a LinuxCNC-native baseline while the port runtime coverage tracks this
|
||||
phase's standalone behavior.
|
||||
|
||||
Current failures:
|
||||
|
||||
- `axis/foam/foam.ngc`: `Bad character 'u' used`
|
||||
- `axis/vismach/5axis/bridgemill/5axisgui.ngc`: `Bad character 'w' used`
|
||||
|
||||
Root cause:
|
||||
|
||||
The current standalone interpreter initialization does not configure the active
|
||||
axis mask from `[TRAJ] COORDINATES` / `[KINS] KINEMATICS`. Native LinuxCNC
|
||||
accepts `U/V/W` only when the machine config declares those axes.
|
||||
|
||||
Implementation steps:
|
||||
|
||||
1. Add a machine-config loader in `runtime/core/linuxcnc_wrap/`, for example:
|
||||
|
||||
```text
|
||||
linuxcnc_machine_config.hh
|
||||
linuxcnc_machine_config.cpp
|
||||
```
|
||||
|
||||
2. Reuse vendored `inifile.cc` to parse:
|
||||
|
||||
- `[TRAJ] COORDINATES`
|
||||
- `[KINS] KINEMATICS`
|
||||
- `[DISPLAY] GEOMETRY`
|
||||
- `[RS274NGC] PARAMETER_FILE`
|
||||
- `[RS274NGC] SUBROUTINE_PATH`
|
||||
- `[RS274NGC] USER_M_PATH`
|
||||
- `[EMCIO] TOOL_TABLE`
|
||||
|
||||
3. Extend `initialize_minimal_interp()` / the runtime equivalent to set the
|
||||
interpreter setup fields from the parsed machine config instead of hardcoded
|
||||
`XYZ`.
|
||||
|
||||
4. Add focused native fixtures:
|
||||
|
||||
- `axis_foam.ini` + `foam.ngc` accepts `U/V`.
|
||||
- `bridgemill/5axis.ini` + `5axisgui.ngc` accepts `W`.
|
||||
|
||||
5. Add the same coverage to the WASM SDK once native is green.
|
||||
|
||||
Completion check:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/native/verify_sim_configs.sh --only axis/foam/foam.ngc
|
||||
wasm-port/tests/native/verify_sim_configs.sh --only axis/vismach/5axis/bridgemill/5axisgui.ngc
|
||||
```
|
||||
|
||||
## Phase 3: Implement Standalone User M-Code Dispatch
|
||||
|
||||
Status: complete for the standalone native/WASM runtime boundary. The port now
|
||||
reads `[DISPLAY] PROGRAM_PREFIX` and `[RS274NGC] USER_M_PATH`, searches
|
||||
executable `M100` through `M199` files using the same order as LinuxCNC task
|
||||
initialization, registers them in LinuxCNC's `USER_DEFINED_FUNCTION` table, and
|
||||
records `USER_M_COMMAND` canonical boundary events instead of spawning host
|
||||
processes. Native probes cover `axis/geometry` `M110` and
|
||||
`axis/external_offsets` `M111`; Node WASM covers minimal `M110` and `M111`
|
||||
fixtures through the Emscripten filesystem.
|
||||
|
||||
The `verify_sim_configs.sh` baseline still records these files as expected
|
||||
failures because it intentionally runs LinuxCNC `bin/rs274`, not the standalone
|
||||
task/runtime adapter.
|
||||
|
||||
Current failures:
|
||||
|
||||
- `axis/external_offsets/*.ngc`: unknown `M111`
|
||||
- `axis/geometry/xyzc.ngc`: unknown `M110`
|
||||
|
||||
Root cause:
|
||||
|
||||
Native LinuxCNC resolves user M-codes through `[DISPLAY] PROGRAM_PREFIX` and
|
||||
`[RS274NGC] USER_M_PATH` during task initialization, registers matching
|
||||
executable `M100..M199` handlers with the interpreter, and later runs external
|
||||
scripts through the task process boundary. The standalone runtime must register
|
||||
the same interpreter boundary without running host processes in WASM/browser.
|
||||
|
||||
Implementation steps:
|
||||
|
||||
1. Locate the upstream M-code dispatch path in LinuxCNC and vendor the minimum
|
||||
source needed to preserve semantics, or add a narrow runtime-edge adapter if
|
||||
the upstream path is process-bound. Done: the adapter mirrors
|
||||
`src/emc/task/emctask.cc` search/registration behavior and keeps process
|
||||
execution outside CNC semantics.
|
||||
|
||||
2. Add `USER_M_PATH` parsing to the machine-config loader. Done.
|
||||
|
||||
3. For native standalone tests. Done:
|
||||
|
||||
- resolve `M100` through `M199` against configured search paths;
|
||||
- register only executable files;
|
||||
- emit deterministic `USER_M_COMMAND` boundary events.
|
||||
|
||||
4. For WASM/browser. Done for Node WASM:
|
||||
|
||||
- do not spawn host processes;
|
||||
- use a host-boundary user-M adapter that registers deterministic
|
||||
message-emitting handlers for sim-only notification M-codes;
|
||||
- document this as a runtime edge, not CNC semantics.
|
||||
|
||||
5. Add tests. Done:
|
||||
|
||||
- `M110` from `axis/geometry`;
|
||||
- `M111` from `axis/external_offsets`;
|
||||
- minimal WASM `M110` and `M111` fixtures.
|
||||
|
||||
Completion check:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/native/verify_sim_configs.sh --only axis/external_offsets
|
||||
wasm-port/tests/native/verify_sim_configs.sh --only axis/geometry/xyzc.ngc
|
||||
```
|
||||
|
||||
Standalone runtime checks:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/native/verify_native_probes.sh
|
||||
wasm-port/tests/wasm/node/verify_interp_wasm.sh
|
||||
```
|
||||
|
||||
## Phase 4: Bring Up Python Remap Runtime Edges
|
||||
|
||||
Status: complete for the native sim-config harness. Current checks:
|
||||
|
||||
```text
|
||||
gmoccapy: total 38, pass 38, fail 0
|
||||
axis/laser: total 3, pass 3, fail 0
|
||||
```
|
||||
|
||||
Root cause:
|
||||
|
||||
The configs use LinuxCNC Python remap modules. Earlier harness runs failed while
|
||||
initializing `python/toplevel.py`; current native runs now resolve and execute
|
||||
these configs under the LinuxCNC `rs274` baseline.
|
||||
|
||||
Implementation steps:
|
||||
|
||||
1. Preserve upstream behavior where possible:
|
||||
|
||||
- inspect vendored LinuxCNC Python plugin interfaces;
|
||||
- identify exact APIs used by:
|
||||
- `configs/sim/gmoccapy/python/toplevel.py`
|
||||
- `configs/sim/gmoccapy/python/remap.py`
|
||||
- `configs/sim/gmoccapy/python/stdglue.py`
|
||||
- `configs/sim/axis/laser/python/toplevel.py`
|
||||
- `configs/sim/axis/laser/python/remap.py`
|
||||
|
||||
2. Split the implementation into two layers:
|
||||
|
||||
- native harness support using the host Python runtime, if available;
|
||||
- WASM support using a documented adapter boundary or a Python-free
|
||||
equivalent only for runtime edges, not G-code semantics.
|
||||
|
||||
3. Add runtime state adapters required by Python remap:
|
||||
|
||||
- selected tool and pocket;
|
||||
- tool table access;
|
||||
- interpreter status object fields used by stdglue;
|
||||
- message/error reporting;
|
||||
- canonical tool-change side effects needed by `M6`, `M61`, and laser
|
||||
remaps.
|
||||
|
||||
4. Make Python module path resolution match LinuxCNC:
|
||||
|
||||
- INI directory is the base directory;
|
||||
- `PYTHONPATH` includes config `python/` directories;
|
||||
- remap modules load relative to the sim config.
|
||||
|
||||
5. Add narrowly-scoped tests before running all 38 gmoccapy programs. Done:
|
||||
|
||||
- one gmoccapy tool-change macro;
|
||||
- one gmoccapy lathe macro;
|
||||
- one gmoccapy 5-axis example;
|
||||
- one laser raster/vector program.
|
||||
|
||||
Completion check:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/native/verify_sim_configs.sh --only gmoccapy
|
||||
wasm-port/tests/native/verify_sim_configs.sh --only axis/laser
|
||||
```
|
||||
|
||||
## Phase 5: Support TWP Remaps Including G69
|
||||
|
||||
Status: mapping complete. The harness now maps
|
||||
`axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/*` through the
|
||||
explicit `xyzacb-trsrn_twp/xyzacb-trsrn.ini` machine config instead of falling
|
||||
back to `axis/axis.ini`. That loads the TWP `G69` remap declarations correctly,
|
||||
and 14 of the 15 TWP demo/remap programs now pass.
|
||||
|
||||
Current failures:
|
||||
|
||||
- `axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_g533.ngc`
|
||||
fails in the LinuxCNC `rs274` baseline because line 10 uses bare
|
||||
`x50y50z150` after `G53.6`; same-directory demos use explicit `G0` motion
|
||||
words at this point.
|
||||
|
||||
Root cause:
|
||||
|
||||
The demo programs rely on table/spindle rotary TWP remaps. The original test
|
||||
mapping fell back to `axis/axis.ini` for these demo files because the actual
|
||||
INI is in a child directory:
|
||||
|
||||
```text
|
||||
axis/vismach/5axis/table-rotary_spindle-rotary-nutating/
|
||||
xyzacb-trsrn_twp/xyzacb-trsrn.ini
|
||||
xyzbca-trsrn_twp/xyzbca-trsrn.ini
|
||||
```
|
||||
|
||||
Implementation steps:
|
||||
|
||||
1. Improve sim-config mapping. Done:
|
||||
|
||||
- if a `.ngc` is under a `demos/` sibling of machine-specific INI
|
||||
directories, map it to the appropriate TWP INI instead of walking upward
|
||||
to `axis/axis.ini`;
|
||||
- encode this as explicit metadata in the harness, not a fragile heuristic.
|
||||
|
||||
2. Ensure `SUBROUTINE_PATH` includes `../remap_subs:../demos` as declared by
|
||||
the TWP INIs.
|
||||
|
||||
3. Verify remap subroutines:
|
||||
|
||||
- `g69remap.ngc`
|
||||
- `g531remap.ngc`
|
||||
- `g533remap.ngc`
|
||||
- `g536remap.ngc`
|
||||
|
||||
4. Add a native test for each failing demo.
|
||||
|
||||
Latest result:
|
||||
|
||||
```text
|
||||
total: 15
|
||||
pass: 14
|
||||
fail: 1
|
||||
timeout: 0
|
||||
expected_fail: 1
|
||||
unexpected_fail: 0
|
||||
skipped: 0
|
||||
```
|
||||
|
||||
Completion check:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/native/verify_sim_configs.sh --only table-rotary_spindle-rotary-nutating
|
||||
```
|
||||
|
||||
## Phase 6: Promote Native Coverage To WASM
|
||||
|
||||
Status: complete for representative Node and browser WASM coverage. Dedicated
|
||||
Node and browser smokes now pass a representative vendored `configs/sim` subset
|
||||
through the SDK `runSimConfigProgram()` host boundary, which copies files into
|
||||
the Emscripten filesystem and forwards execution to existing LinuxCNC-backed C
|
||||
ABI paths. They cover:
|
||||
|
||||
- `axis/foam/foam.ngc` with `axis_foam.ini`, verifying INI-driven `U/V` axis
|
||||
mask handling in WASM.
|
||||
- `axis/vismach/5axis/bridgemill/5axisgui.ngc` with `5axis.ini`, verifying
|
||||
INI-driven `W` axis mask handling and bridge-mill NGC remap execution in
|
||||
WASM.
|
||||
- `axis/geometry/xyzc.ngc` with `xyzc.ini` and real executable `M110`, verifying
|
||||
`USER_M_PATH` registration in WASM.
|
||||
- `axis/external_offsets/dyn_demo.ngc` with `dynamic_offsets.ini` and real
|
||||
executable `M111`, verifying the same user-M boundary against an upstream sim
|
||||
program.
|
||||
|
||||
Completion checks:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
|
||||
wasm-port/tests/browser/verify_interp_browser.sh
|
||||
```
|
||||
|
||||
Remaining work:
|
||||
|
||||
1. Extend `runtime/core/linuxcnc_wrap/linuxcnc_interp_wasm.cpp` with the same
|
||||
machine-config entry point used by native tests. Done for the existing
|
||||
`runFileWithIni()` file-execution path.
|
||||
|
||||
2. Extend `runtime/sdk/src/linuxcnc-interp.js` with a host-boundary method such
|
||||
as:
|
||||
|
||||
```js
|
||||
runSimConfigProgram({ iniPath, programPath, files })
|
||||
```
|
||||
|
||||
Done. The method only writes caller-provided text files into the
|
||||
Emscripten filesystem, applies executable bits for user M-code files, and
|
||||
forwards execution to the existing LinuxCNC-backed C ABI path. It does not
|
||||
implement CNC semantics in JavaScript.
|
||||
|
||||
3. Copy required sim config files into the Emscripten FS:
|
||||
|
||||
- INI;
|
||||
- tool table;
|
||||
- parameter file;
|
||||
- `.ngc` program;
|
||||
- `SUBROUTINE_PATH` files;
|
||||
- `USER_M_PATH` handler files or registered adapter handlers.
|
||||
|
||||
Done for the representative Node and browser subsets.
|
||||
|
||||
4. Add Node WASM coverage. Done:
|
||||
|
||||
```text
|
||||
wasm-port/tests/wasm/node/verify_sim_configs_wasm.mjs
|
||||
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
|
||||
```
|
||||
|
||||
5. Add representative browser coverage. Done in
|
||||
`wasm-port/tests/browser/interp_smoke.html` through the existing browser
|
||||
interpreter smoke and the same `runSimConfigProgram()` SDK boundary as Node.
|
||||
|
||||
## Phase 7: Documentation And Drift Control
|
||||
|
||||
Status: complete for the current representative sim-config WASM/browser
|
||||
coverage. The documentation and manifest now record the native, Node WASM,
|
||||
browser, source reuse, and vendor-sync state for the selected sim-config
|
||||
programs.
|
||||
|
||||
1. Update `docs/compatibility-validation.md` with the sim-config matrix. Done.
|
||||
|
||||
2. Update `docs/source-reuse-map.md` for newly vendored source files. Done.
|
||||
|
||||
3. Update `tools/source-manifest.txt` and `tools/verify_vendor_sync.sh` if new
|
||||
LinuxCNC files are copied into `wasm-port/vendor/linuxcnc`. Done for the
|
||||
representative `axis/foam`, `axis/geometry`, and `axis/external_offsets`
|
||||
sim-config files; no `verify_vendor_sync.sh` logic change was needed.
|
||||
|
||||
4. Preserve the latest result summary as a machine-readable artifact, but do
|
||||
not commit generated logs unless they are intentionally used as fixtures.
|
||||
Done: generated logs remain under build/test output directories, while the
|
||||
tracked documentation records only the current summary values and validation
|
||||
commands.
|
||||
|
||||
## Recommended Work Order
|
||||
|
||||
1. Harness first: make `verify_sim_configs.sh` reproducible.
|
||||
2. Axis config next: unblock `U/V/W` failures.
|
||||
3. TWP mapping: complete; remaining TWP demo failures are Python/HAL remap
|
||||
runtime edges.
|
||||
4. User M-code dispatch: small runtime-edge feature, unblocks five files.
|
||||
5. Python remap runtime: largest block; do it after the harness and smaller
|
||||
runtime edges are stable.
|
||||
6. WASM promotion after native parity.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not implement a new JavaScript or project-authored G-code interpreter.
|
||||
- Do not edit `linuxcnc/configs/sim` or any upstream `linuxcnc/` file to make
|
||||
tests pass.
|
||||
- Do not fake path, modal, kinematic, tool, or parameter semantics in the SDK.
|
||||
- Do not treat gmoccapy native GUI code as browser UI implementation. Only its
|
||||
simulation/remap behavior is relevant to this runtime.
|
||||
@@ -40,13 +40,18 @@ Current validation is intentionally mechanical:
|
||||
| Identity/trivial kinematics | `src/emc/kinematics/kinematics.h`, `cubic.h`, `kins_util.c`, `trivkins.c` | Copy unchanged | HAL component lifecycle and RTAPI module metadata are replaced by standalone shims; forward/inverse mapping behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_kinematics_probe` |
|
||||
| Switchable 5-axis bridge kinematics | `src/emc/kinematics/5axiskins.c`, `switchkins.c`, `switchkins.h`, `userkfuncs.c`, plus `src/rtapi/rtapi_ctype.h` | Copy unchanged | HAL pin allocation, HAL component lifecycle, and RTAPI module metadata are standalone runtime edges; switchable 5-axis forward/inverse behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_5axis_kinematics_probe` |
|
||||
| TRT table-rotary kinematics | `src/emc/kinematics/trtfuncs.c`, `xyzac-trt-kins.c`, `xyzbc-trt-kins.c` | Copy unchanged | HAL pin allocation and switchkins lifecycle stay runtime boundaries; XYZAC/XYZBC TRT forward/inverse behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_xyzac_trt_kinematics_probe`, `linuxcnc_xyzbc_trt_kinematics_probe` |
|
||||
| Five-axis switchkins machine configs and M428/M429/M430 remaps | `configs/sim/axis/vismach/5axis/bridgemill/*`, `table-dual-rotary/*`, and `table-rotary-tilting/*` selected INI, HAL, tool-table, XML, demo, and `remap_subs/*.ngc` files plus `src/emc/rs274ngc/interp_remap.cc` | Copy unchanged | `M428`, `M429`, and `M430` remain LinuxCNC `REMAP` entries that call LinuxCNC NGC subroutines using `M68`, `M66`, `_hal[motion.switchkins-type]`, and the INI/HAL `motion.analog-out-03 => motion.switchkins-type` link; standalone remap descriptor parsing routes through vendored `Interp::parse_remap()` and `find_ngc_file()`, and NGC remap/file execution routes through vendored LinuxCNC O-word and `open()`/`read()`/`execute()` paths while HAL synchronization stays a runtime adapter boundary | Vendor byte sync, `linuxcnc_5axis_remap_asset_probe`, `linuxcnc_remap_parse_harness`, `linuxcnc_remap_hal_sync_harness`, `linuxcnc_5axis_remap_execute_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/browser/verify_interp_browser.sh`, `tests/browser/verify_ini_panel_browser.sh` |
|
||||
| Five-axis switchkins machine configs and M428/M429/M430 remaps | `configs/sim/axis/vismach/5axis/bridgemill/*`, `table-dual-rotary/*`, and `table-rotary-tilting/*` selected INI, HAL, tool-table, XML, demo, and `remap_subs/*.ngc` files plus `src/emc/rs274ngc/interp_remap.cc` | Copy unchanged | `M428`, `M429`, and `M430` remain LinuxCNC `REMAP` entries that call LinuxCNC NGC subroutines using `M68`, `M66`, `_hal[motion.switchkins-type]`, and the INI/HAL `motion.analog-out-03 => motion.switchkins-type` link; standalone remap descriptor parsing routes through vendored `Interp::parse_remap()` and `find_ngc_file()`, and NGC remap/file execution routes through vendored LinuxCNC O-word and `open()`/`read()`/`execute()` paths while HAL synchronization stays a runtime adapter boundary | Vendor byte sync, `linuxcnc_5axis_remap_asset_probe`, `linuxcnc_remap_parse_harness`, `linuxcnc_remap_hal_sync_harness`, `linuxcnc_5axis_remap_execute_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/wasm/node/verify_sim_configs_wasm.sh`, `tests/browser/verify_interp_browser.sh`, `tests/browser/verify_ini_panel_browser.sh` |
|
||||
| Representative sim-config machine programs | `configs/sim/axis/foam/*`, `configs/sim/axis/geometry/M110`, `xyzc.ini`, `xyzc.ngc`, `configs/sim/axis/external_offsets/M111`, `dyn_demo.ngc`, `dynamic_offsets.ini`, `eoffset.tbl`, and `configs/sim/axis/sim.tbl` | Copy unchanged | The `foam`, `xyzc`, and dynamic external-offset sample programs remain LinuxCNC sim-config assets. The standalone boundary only copies INI, tool table, G-code, and executable user-M files into the native or WASM filesystem, then calls vendored LinuxCNC INI parsing and `Interp::open()`/`read()`/`execute()` through the existing machine-config adapter. The JS SDK `runSimConfigProgram()` is only the host file-staging helper for this boundary: it writes caller-provided text files to the Emscripten filesystem, applies executable bits, and forwards to LinuxCNC-backed C ABI entry points. `M110`/`M111` process execution stays a runtime boundary represented by deterministic `USER_M_COMMAND` canonical events | Vendor byte sync, `tests/native/verify_sim_configs.sh`, `tests/wasm/node/verify_sim_configs_wasm.sh`, `tests/browser/verify_interp_browser.sh` |
|
||||
| Representative `nc_files` examples | `nc_files/arcspiral.ngc`, `nc_files/factorial.ngc`, `nc_files/hole-circle.ngc`, `nc_files/m6demo.ngc` | Copy unchanged | These upstream `linuxcnc/nc_files` examples are copied byte-for-byte into the WASM vendor tree after the native `nc_files` harness classifies the broader directory. Node and browser tests only stage the original `.ngc` text in the Emscripten filesystem and call the LinuxCNC-backed `Interp::open()`, `read()`, and `execute()` path through the existing SDK; no G-code, O-word, tool-change, or M-code behavior is implemented in JavaScript | Vendor byte sync, `tests/native/verify_nc_files.sh`, `tests/wasm/node/verify_nc_files_wasm.sh`, `tests/browser/verify_interp_browser.sh`, `tests/host/verify_host_smokes.sh` |
|
||||
| LinuxCNC remap regression fixtures | `tests/remap/duplicate-o-word/*`, `tests/remap/fail/args.0/*`, `tests/remap/fail/args.1/*`, `tests/remap/fail/args.2/*`, `tests/remap/fail/body-ngc/*`, `tests/remap/m30-interaction/*`, `tests/remap/nested-remaps-oword/*`, `tests/remap/posargs.0/*`, `tests/remap/sequencing/*`, selected NGC-only `tests/remap/remap-io/test-ngc.ini` plus `io_*.ngc`, and `src/emc/rs274ngc/interp_remap.cc` plus `interp_o_word.cc` | Copy unchanged | The upstream duplicate O-word, NGC-only remap failure, M30/remap-level interaction, nested O-word remap, positional-argument remap, G/M remap sequencing, and remap-IO NGC subroutine regressions remain LinuxCNC REMAP/O-word/file or MDI execution tests. The standalone boundary only copies the upstream test files into native or WASM filesystems, reads LinuxCNC INI `SUBROUTINE_PATH`, `REMAP`, and `OWORD_NARGS` entries, and calls vendored `Interp::parse_remap()`, `open()`, `read()`, and `execute()` or feeds the upstream remap-IO MDI sequence into vendored `Interp::execute()`; the continue-on-error runner path only mirrors LinuxCNC `rs274 -n 0` test execution and does not implement duplicate-label, O-word, nested remap, M30, positional-argument, failure, sequencing, M62-M68, M66 input, or remap semantics | Vendor byte sync, `linuxcnc_duplicate_oword_remap_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/browser/verify_interp_browser.sh` |
|
||||
| LinuxCNC interpreter regression fixtures | `tests/interp/do-while-break/*`, `tests/interp/oword-bug315/*`, `tests/interp/oword-bug315-p2/*`, `tests/interp/exists/*`, `tests/interp/return-value/*`, `tests/interp/subs-follow-main/*`, `tests/interp/fractional-linenumbers/*`, `tests/interp/namedparam-bug424/*`, selected `tests/interp/rotation/*` pure interpreter cases, `tests/interp/iniparam/*`, `tests/interp/iniparam-failassign/*`, `tests/interp/m19/*`, `tests/interp/magic_comments/param_format_printing/*`, selected `tests/interp/m98m99/*` pure interpreter cases, `tests/interp/sub-call-from-sub/*`, `tests/interp/sequence-number/*`, `tests/interp/nested-sub-error/*`, `tests/interp/nested-sub-in-file-error/*`, `tests/interp/abort-hot-comment/*`, plus vendored interpreter/O-word sources including `interp_o_word.cc`, `interp_read.cc`, `interp_execute.cc`, `interp_find.cc`, `interp_namedparams.cc`, and `rs274ngc_pre.cc` | Copy unchanged | The upstream do/while/break, O-word bug315, `EXISTS[]`, subroutine return-value, subs-after-main, fractional line-number, named-parameter, selected rotation/G53/G28 absolute-position and endpoint, INI named-parameter lookup/read-only protection, M19 spindle-orient offset/timeout handling, magic-comment parameter formatting, selected Fanuc `M98/M99` and O-expression call regressions, external-subroutine-call, external-subroutine line-number, nested-subroutine-definition rejection, blocked forward-seek-to-later-numbered-sub, and `(ABORT,...)` hot-comment parameter-expansion regressions remain LinuxCNC interpreter file-execution tests. The standalone boundary only vendors the original upstream assets, copies `*.ngc`, `test.ini`, `test.tbl`, `subs/*.ngc`, and referenced external subroutine `.ngc` files into native or WASM filesystems where applicable, sets the LinuxCNC `INI_FILE_NAME` runtime edge for `_ini[...]`, applies LinuxCNC INI machine settings such as `[RS274NGC]ORIENT_OFFSET`, reads LinuxCNC INI `SUBROUTINE_PATH`, captures LinuxCNC `(PRINT,...)` output through the existing stdout/Emscripten `print` boundary, and calls vendored `Interp::open()`, `read()`, and `execute()`; it does not implement O-word loop, break, subroutine, dynamic call, `M98/M99`, `EXISTS[]`, named-parameter, absolute-position named-parameter, G28/G53 endpoint, INI-variable, read-only parameter, line-number, spindle-speed, spindle-orient, magic-comment formatting, subroutine lookup, ABORT hot-comment, error, or branch semantics | Vendor byte sync, `linuxcnc_interp_minimal_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/browser/verify_interp_browser.sh` |
|
||||
| Additional non-switchable kinematics | `src/emc/kinematics/corexykins.c`, `rotatekins.c`, `rosekins.c`, `maxkins.c`, `lineardeltakins.c`, `lineardeltakins-common.h`, `rotarydeltakins.c`, `rotarydeltakins-common.h`, `scorbot-kins.c`, `tripodkins.c`, `scarakins.c`, `pumakins.c`, `pumakins.h`, `genhexkins.c`, `genhexkins.h`, `genserfuncs.c`, `genserkins.c`, `genserkins.h`, `ugenserkins.c`, `pentakins.c`, `pentakins.h`, `cubic.c` | Copy unchanged | HAL pin allocation, HAL parameter allocation, HAL component lifecycle, RTAPI module metadata, Go math C/C++ linkage, switchkins iterative-forward warmup, and userspace test-program process entry remain standalone runtime edges; forward/inverse behavior remains LinuxCNC source where the module exposes it | Vendor byte sync, per-file source probes, `linuxcnc_corexy_kinematics_probe`, `linuxcnc_rotate_kinematics_probe`, `linuxcnc_rose_kinematics_probe`, `linuxcnc_max_kinematics_probe`, `linuxcnc_lineardelta_kinematics_probe`, `linuxcnc_rotarydelta_kinematics_probe`, `linuxcnc_scorbot_kinematics_probe`, `linuxcnc_tripod_kinematics_probe`, `linuxcnc_scara_kinematics_probe`, `linuxcnc_puma_kinematics_probe`, `linuxcnc_genser_kinematics_probe`, `linuxcnc_genhex_kinematics_probe`, `linuxcnc_pentakins_kinematics_probe` |
|
||||
| Trajectory planner | `src/emc/tp/tp.c`, `tc.c`, `tcq.c`, `spherical_arc.c`, `blendmath.c`, `sp_scurve.c`, `ruckig_wrapper.c`, plus matching `*.h` files | Copy unchanged | Native realtime scheduling and motion process state are replaced by standalone probe setup; the WASM TP probe uses the same deterministic status/config boundary and calls vendored TP APIs through a narrow C ABI | Vendor byte sync, per-file source probes, `linuxcnc_tp_api_probe`, `tests/wasm/node/verify_tp_wasm.sh` |
|
||||
| Ruckig C planner support | Selected `src/emc/tp/cruckig/*.c` and `*.h` files in the manifest | Copy unchanged | Used as LinuxCNC planner support code through vendored TP sources | Vendor byte sync, per-file source probes, `tests/wasm/node/verify_tp_wasm.sh` |
|
||||
| Posemath | `src/libnml/posemath/posemath.cc`, `_posemath.c`, `gomath.c`, `sincos.c`, and matching headers | Copy unchanged | `gomath.c` is compiled as C; `rtapi.h` shim is C/C++ compatible for this boundary | Vendor byte sync, per-file source probes, TP native and WASM probes |
|
||||
| RS274 interpreter state and parser | `src/emc/rs274ngc/modal_state.*`, `interp_internal.*`, `interp_read.cc`, `interp_check.cc`, `interp_execute.cc`, `interp_find.cc`, `interp_array.cc`, `interp_queue.*`, `rs274ngc*`, `units.h` | Copy unchanged | Python/remap/runtime edges are isolated in standalone wrappers and shims; parser and execution logic remain LinuxCNC source | Vendor byte sync, per-file source probes, interpreter harness fixtures |
|
||||
| RS274 conversion semantics | `src/emc/rs274ngc/interp_convert.cc`, `interp_arc.cc`, `interp_inverse.cc`, `interp_cycles.cc`, `interp_g7x.cc`, `interp_o_word.cc`, `interp_write.cc` | Copy unchanged | Canonical calls are captured by standalone event sink functions; conversion behavior stays in vendored LinuxCNC files; feed-rate state is read back through the canonical runtime boundary during length-unit conversion; single-axis rotary indexer lock/unlock dispatch remains vendored LinuxCNC `issue_straight_index()` behavior | Vendor byte sync, per-file source probes, canonical fixture suite, no standalone `Interp::convert_g()` guard, `linuxcnc_indexer_harness`, `tests/wasm/node/verify_interp_wasm.sh` and `tests/browser/verify_interp_browser.sh` rotary-indexer assertions |
|
||||
| User M-code registration boundary | `src/emc/task/emctask.cc`, `src/emc/rs274ngc/interp_convert.cc`, `src/emc/rs274ngc/interp_queue.cc` | Runtime-edge adapter | Vendored interpreter conversion still checks LinuxCNC `USER_DEFINED_FUNCTION` before accepting `M100..M199` and queues through vendored `enqueue_M_USER_COMMAND()`. The standalone machine-config adapter mirrors LinuxCNC task search order for `[DISPLAY]PROGRAM_PREFIX` and `[RS274NGC]USER_M_PATH`, registers executable M-code files in `USER_DEFINED_FUNCTION`, calls the canonical `FINISH()` boundary, and records deterministic `USER_M_COMMAND` events instead of spawning host processes in WASM/browser. | `linuxcnc_interp_minimal_harness` sim `M110`/`M111` probes, `tests/wasm/node/verify_interp_wasm.sh` minimal `M110`/`M111` fixtures |
|
||||
| Named parameters and tool slot status | `src/emc/rs274ngc/interp_namedparams.cc`, related interpreter headers | Copy unchanged | `_ini[...]` and `_hal[...]` resolve through standalone INI/HAL adapters while lookup order stays LinuxCNC-derived; current/selected tool slot reads for vendored `Interp::synch()` come from the standalone tool adapter | Vendor byte sync, source probe, `linuxcnc_namedparam_harness`, `linuxcnc_interp_init_harness`, `tests/wasm/node/verify_interp_wasm.sh` and `tests/browser/verify_interp_browser.sh` `Interp::synch()` tool-slot assertions plus `Interp::init_named_parameters()`/`find_named_param()` named-parameter lookup assertions |
|
||||
| Tool table parsing and formatting | `src/emc/tooldata/tooldata_common.cc` | Copy unchanged plus standalone storage callbacks | Native file parsing/formatting stays in vendored LinuxCNC source; the standalone tool adapter supplies `tooldata_get()`/`tooldata_put()` storage and index lookup, the WASM boundary only selects the LinuxCNC non-random or random-toolchanger branch via `tooldata_init()`, and OPFS remains a host-side persistence boundary | Vendor byte sync, `linuxcnc_tooldata_common_source_probe`, `tests/wasm/node/verify_interp_wasm.sh` non-random/random load/save tool-table assertions |
|
||||
| Dynamic interpreter base | `src/emc/rs274ngc/interp_base.*` | Copy unchanged | `interp_base.cc` source probe uses standalone `EMC2_HOME` compile-time path boundary for LinuxCNC dynamic interpreter lookup | Vendor byte sync, `linuxcnc_interp_base_source_probe` |
|
||||
@@ -59,8 +64,9 @@ Current validation is intentionally mechanical:
|
||||
| RTAPI | `rtapi_*.h`, TP, posemath, motion headers | Minimal standalone shim in `runtime/core/shims/rtapi.h` |
|
||||
| NML transport | `emc.hh`, motion/NML type headers | Transport is not ported; only the status/type edges needed by vendored compute code are exposed through standalone shims and probes |
|
||||
| HAL runtime | named parameter lookup, kinematics component lifecycle, and runtime status edges | Standalone HAL adapter under `runtime/core/linuxcnc_wrap/` |
|
||||
| Python/remap | `rs274ngc_pre.cc`, `interp_o_word.cc`, `interp_remap.cc`, remap hooks, selected LinuxCNC `configs/sim/axis/vismach/5axis/*/remap_subs/*.ngc` files | Python calls remain stubbed at the runtime boundary today; five-axis M428/M429/M430 source assets are vendored unchanged, the NGC remap descriptor path parses through vendored LinuxCNC code, and native validation now executes the switchkins NGC remap files plus selected demo programs through vendored LinuxCNC O-word and file execution paths while `_hal[...]` synchronization is supplied by the standalone HAL adapter |
|
||||
| Canonical machine actions | `interp_convert.cc`, `interp_execute.cc`, `interp_queue.cc` | Captured by standalone canonical event sink functions for regression fixtures |
|
||||
| User M-code process execution | `emctask.cc`, `interp_convert.cc`, `interp_queue.cc` | Search and registration are mirrored at the standalone machine-config boundary; native/WASM tests record deterministic `USER_M_COMMAND` events and do not spawn host processes |
|
||||
| Python/remap | `rs274ngc_pre.cc`, `interp_o_word.cc`, `interp_remap.cc`, remap hooks, selected LinuxCNC `configs/sim/axis/vismach/5axis/*/remap_subs/*.ngc` files, `tests/remap/duplicate-o-word/*`, `tests/remap/fail/args.0/*`, `tests/remap/fail/args.1/*`, `tests/remap/fail/args.2/*`, `tests/remap/fail/body-ngc/*`, `tests/remap/m30-interaction/*`, `tests/remap/nested-remaps-oword/*`, `tests/remap/posargs.0/*`, `tests/remap/sequencing/*`, and NGC-only `tests/remap/remap-io/test-ngc.ini` plus `io_*.ngc` | Python calls remain stubbed at the runtime boundary today; five-axis M428/M429/M430 source assets and the upstream NGC remap regression files are vendored unchanged. NGC remap descriptor paths parse through vendored LinuxCNC code, native/WASM/browser validation executes the NGC remap files through vendored LinuxCNC O-word and file execution paths, and the remap-IO NGC-only branch feeds the upstream MDI sequence into vendored LinuxCNC `Interp::execute()` while external M66 input values and `_hal[...]` synchronization remain standalone runtime adapter boundaries |
|
||||
| Canonical machine actions | `interp_convert.cc`, `interp_execute.cc`, `interp_queue.cc`, selected `tests/interp/*` regression assets | Captured by standalone canonical event sink functions for regression fixtures; vendored upstream interpreter test assets remain unchanged and are executed through LinuxCNC file execution |
|
||||
| Realtime scheduling | TP and motion headers | Not ported; native TP probes seed deterministic status/config state |
|
||||
| GUI | None used as implementation | Native LinuxCNC GUI remains reference-only |
|
||||
|
||||
|
||||
@@ -362,6 +362,12 @@ int main()
|
||||
"xyzac_switchkins_test_1.ngc",
|
||||
0.0,
|
||||
},
|
||||
{
|
||||
"xyzac_switchkins_test_2",
|
||||
"configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/"
|
||||
"xyzac_switchkins_test_2.ngc",
|
||||
0.0,
|
||||
},
|
||||
{
|
||||
"xyzac_switchkins_test_3",
|
||||
"configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/"
|
||||
@@ -404,10 +410,11 @@ int main()
|
||||
ok &= execute_demo_file(cases[0], demos[2]);
|
||||
ok &= execute_demo_file(cases[0], demos[3]);
|
||||
ok &= execute_demo_file(cases[0], demos[4]);
|
||||
ok &= execute_demo_file(cases[1], demos[5]);
|
||||
ok &= execute_demo_file(cases[0], demos[6]);
|
||||
ok &= execute_demo_file(cases[2], demos[7]);
|
||||
ok &= execute_demo_file(cases[3], demos[8]);
|
||||
ok &= execute_demo_file(cases[0], demos[5]);
|
||||
ok &= execute_demo_file(cases[1], demos[6]);
|
||||
ok &= execute_demo_file(cases[0], demos[7]);
|
||||
ok &= execute_demo_file(cases[2], demos[8]);
|
||||
ok &= execute_demo_file(cases[3], demos[9]);
|
||||
|
||||
print_bool("fiveaxis_linuxcnc_remap_execute_path", ok);
|
||||
return ok ? 0 : 1;
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
#define private public
|
||||
#include "emc/rs274ngc/rs274ngc_interp.hh"
|
||||
#undef private
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "canon_event_sink.hh"
|
||||
#include "emc/ini/inifile.hh"
|
||||
#include "emc/rs274ngc/interp_internal.hh"
|
||||
#include "linuxcnc_hal_adapter.hh"
|
||||
#include "linuxcnc_tool_adapter.hh"
|
||||
|
||||
#ifndef LINUXCNC_VENDOR_DIR
|
||||
#error "LINUXCNC_VENDOR_DIR must point at wasm-port/vendor/linuxcnc"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
std::filesystem::path vendor_path(const std::string &rel)
|
||||
{
|
||||
return std::filesystem::path(LINUXCNC_VENDOR_DIR) / rel;
|
||||
}
|
||||
|
||||
void print_bool(const std::string &name, bool value)
|
||||
{
|
||||
std::cout << name << "=" << (value ? 1 : 0) << "\n";
|
||||
}
|
||||
|
||||
void print_error_text(Interp &interp, const std::string &name, int rc)
|
||||
{
|
||||
char error_buf[LINELEN] = {0};
|
||||
interp.error_text(rc, error_buf, sizeof(error_buf));
|
||||
std::cout << name << error_buf << "\n";
|
||||
}
|
||||
|
||||
void initialize_interp(Interp &interp)
|
||||
{
|
||||
standalone::reset_hal_adapter();
|
||||
standalone::reset_tool_adapter();
|
||||
standalone::reset_canon_events();
|
||||
|
||||
interp._setup.length_units = CANON_UNITS_MM;
|
||||
interp._setup.distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
interp._setup.ijk_distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
interp._setup.feed_mode = FEED_MODE::UNITS_PER_MINUTE;
|
||||
interp._setup.plane = CANON_PLANE::XY;
|
||||
interp._setup.motion_mode = G_0;
|
||||
interp._setup.percent_flag = false;
|
||||
interp._setup.sequence_number = 0;
|
||||
interp._setup.parameter_occurrence = 0;
|
||||
interp._setup.num_spindles = 1;
|
||||
interp._setup.feature_set = FEATURE_INI_VARS | FEATURE_HAL_PIN_VARS;
|
||||
interp._setup.parameter_g73_peck_clearance = 1.0;
|
||||
interp._setup.parameter_g83_peck_clearance = 1.0;
|
||||
interp._setup.parameters[5599] = 1.0;
|
||||
std::memcpy(interp._readers, Interp::default_readers, sizeof(Interp::default_readers));
|
||||
interp.init_named_parameters();
|
||||
}
|
||||
|
||||
std::filesystem::path subroutine_path(const std::filesystem::path &machine_dir,
|
||||
const std::string &entry)
|
||||
{
|
||||
const std::filesystem::path path(entry);
|
||||
if (path.is_absolute()) {
|
||||
return path;
|
||||
}
|
||||
return machine_dir / path;
|
||||
}
|
||||
|
||||
bool configure_remaps(Interp &interp,
|
||||
const std::filesystem::path &ini_path,
|
||||
const char *label,
|
||||
int expected_remaps)
|
||||
{
|
||||
linuxcnc::IniFile ini(ini_path.string());
|
||||
const bool opened = static_cast<bool>(ini);
|
||||
print_bool(std::string(label) + "_ini_open", opened);
|
||||
if (!opened) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto machine_dir = ini_path.parent_path();
|
||||
std::snprintf(interp._setup.program_prefix, sizeof(interp._setup.program_prefix), "%s",
|
||||
machine_dir.c_str());
|
||||
|
||||
int subroutine_count = 0;
|
||||
if (auto subroutine_path_text = ini.findString("SUBROUTINE_PATH", "RS274NGC")) {
|
||||
std::stringstream paths(*subroutine_path_text);
|
||||
std::string entry;
|
||||
while (std::getline(paths, entry, ':') && subroutine_count < MAX_SUB_DIRS) {
|
||||
const auto resolved = subroutine_path(machine_dir, entry);
|
||||
interp._setup.subroutines[subroutine_count++] = strstore(resolved.c_str());
|
||||
}
|
||||
}
|
||||
std::cout << label << "_subroutine_path_count=" << subroutine_count << "\n";
|
||||
|
||||
if (ini.findBoolV("OWORD_NARGS", "RS274NGC", false)) {
|
||||
interp._setup.feature_set |= FEATURE_OWORD_N_ARGS;
|
||||
}
|
||||
|
||||
bool ok = subroutine_count > 0;
|
||||
int remap_count = 0;
|
||||
while (auto remap = ini.findString(++remap_count, "REMAP", "RS274NGC")) {
|
||||
const int line_number = ini.lineOf(remap_count, "REMAP", "RS274NGC").second;
|
||||
const int rc = interp.parse_remap(remap->c_str(), line_number);
|
||||
std::cout << label << "_parse_remap_" << remap_count << "=" << rc << "\n";
|
||||
ok &= rc == INTERP_OK;
|
||||
}
|
||||
remap_count -= 1;
|
||||
std::cout << label << "_parsed_remap_count=" << remap_count << "\n";
|
||||
ok &= remap_count == expected_remaps;
|
||||
|
||||
print_bool(std::string(label) + "_remaps_ready", ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool execute_file(Interp &interp,
|
||||
const std::filesystem::path &program_path,
|
||||
const char *label,
|
||||
bool continue_on_error,
|
||||
bool expect_error)
|
||||
{
|
||||
bool ok = true;
|
||||
const int open_rc = interp.open(program_path.c_str());
|
||||
std::cout << label << "_file_open=" << open_rc << "\n";
|
||||
if (open_rc != INTERP_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr int max_file_steps = 20000;
|
||||
int read_count = 0;
|
||||
int execute_count = 0;
|
||||
int finish_count = 0;
|
||||
int final_rc = INTERP_OK;
|
||||
bool reached_exit = false;
|
||||
bool reached_endfile = false;
|
||||
bool saw_error = false;
|
||||
|
||||
while (read_count < max_file_steps && execute_count < max_file_steps) {
|
||||
const int read_rc = interp.read();
|
||||
if (read_rc == INTERP_ENDFILE) {
|
||||
final_rc = read_rc;
|
||||
reached_endfile = true;
|
||||
break;
|
||||
}
|
||||
|
||||
++read_count;
|
||||
if ((read_rc != INTERP_OK) && (read_rc != INTERP_EXECUTE_FINISH)) {
|
||||
std::cout << label << "_file_read_" << read_count << "=" << read_rc << "\n";
|
||||
print_error_text(interp, std::string(label) + "_file_error_text=", read_rc);
|
||||
final_rc = read_rc;
|
||||
saw_error = true;
|
||||
if (!expect_error) {
|
||||
ok = false;
|
||||
}
|
||||
if (!continue_on_error) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const int execute_rc = interp.execute();
|
||||
++execute_count;
|
||||
final_rc = execute_rc;
|
||||
if (execute_rc == INTERP_EXECUTE_FINISH) {
|
||||
++finish_count;
|
||||
}
|
||||
if ((execute_rc != INTERP_OK) &&
|
||||
(execute_rc != INTERP_EXECUTE_FINISH) &&
|
||||
(execute_rc != INTERP_EXIT)) {
|
||||
std::cout << label << "_file_execute_" << execute_count << "=" << execute_rc << "\n";
|
||||
print_error_text(interp, std::string(label) + "_file_error_text=", execute_rc);
|
||||
saw_error = true;
|
||||
if (!expect_error) {
|
||||
ok = false;
|
||||
}
|
||||
if (!continue_on_error) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (execute_rc == INTERP_EXIT) {
|
||||
reached_exit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << label << "_file_read_count=" << read_count << "\n";
|
||||
std::cout << label << "_file_execute_count=" << execute_count << "\n";
|
||||
std::cout << label << "_file_finish_count=" << finish_count << "\n";
|
||||
std::cout << label << "_file_final_rc=" << final_rc << "\n";
|
||||
print_bool(std::string(label) + "_file_reached_exit", reached_exit);
|
||||
print_bool(std::string(label) + "_file_reached_endfile", reached_endfile);
|
||||
print_bool(std::string(label) + "_file_saw_error", saw_error);
|
||||
std::cout << label << "_canon_event_count=" << standalone::canon_events().size() << "\n";
|
||||
for (const auto &event : standalone::canon_events()) {
|
||||
std::cout << label << "_canon_event=" << event << "\n";
|
||||
}
|
||||
|
||||
ok &= read_count > 0;
|
||||
ok &= execute_count > 0;
|
||||
ok &= read_count < max_file_steps;
|
||||
ok &= execute_count < max_file_steps;
|
||||
ok &= reached_exit || reached_endfile;
|
||||
ok &= expect_error ? saw_error : !saw_error;
|
||||
print_bool(std::string(label) + "_linuxcnc_remap_file_execute", ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
std::string command_label(const char *command)
|
||||
{
|
||||
std::string value = command ? command : "";
|
||||
while (!value.empty() && (value.back() == '\n' || value.back() == '\r')) {
|
||||
value.pop_back();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool execute_mdi(Interp &interp, const char *label, const char *command)
|
||||
{
|
||||
int rc = interp.execute(command);
|
||||
std::cout << label << "_mdi_" << command_label(command) << "_execute_0=" << rc << "\n";
|
||||
|
||||
int finish_count = 0;
|
||||
while (rc == INTERP_EXECUTE_FINISH && finish_count < 16) {
|
||||
++finish_count;
|
||||
rc = interp.execute();
|
||||
std::cout << label << "_mdi_" << command_label(command)
|
||||
<< "_execute_" << finish_count << "=" << rc << "\n";
|
||||
}
|
||||
|
||||
std::cout << label << "_mdi_" << command_label(command)
|
||||
<< "_execute_finish_count=" << finish_count << "\n";
|
||||
return rc == INTERP_OK;
|
||||
}
|
||||
|
||||
bool execute_remap_io_mdi_case()
|
||||
{
|
||||
const auto test_dir = vendor_path("tests/remap/remap-io");
|
||||
const auto ini_path = test_dir / "test-ngc.ini";
|
||||
setenv("INI_FILE_NAME", ini_path.c_str(), 1);
|
||||
|
||||
Interp interp;
|
||||
initialize_interp(interp);
|
||||
|
||||
bool ok = configure_remaps(interp, ini_path, "remap_io_ngc", 7);
|
||||
|
||||
const struct MdiStep {
|
||||
const char *command;
|
||||
bool digital_input;
|
||||
int digital_value;
|
||||
bool analog_input;
|
||||
double analog_value;
|
||||
} steps[] = {
|
||||
{"M62 P1\n", false, 0, false, 0.0},
|
||||
{"G0 X1.0\n", false, 0, false, 0.0},
|
||||
{"M63 P1\n", false, 0, false, 0.0},
|
||||
{"G0 X2.0\n", false, 0, false, 0.0},
|
||||
{"M62 P1\n", false, 0, false, 0.0},
|
||||
{"G0 X3.0\n", false, 0, false, 0.0},
|
||||
{"M63 P1\n", false, 0, false, 0.0},
|
||||
{"G0 X4.0\n", false, 0, false, 0.0},
|
||||
{"M64 P1\n", false, 0, false, 0.0},
|
||||
{"M65 P1\n", false, 0, false, 0.0},
|
||||
{"M64 P1\n", false, 0, false, 0.0},
|
||||
{"M65 P1\n", false, 0, false, 0.0},
|
||||
{"M66 P1\n", true, 1, false, 0.0},
|
||||
{"M66 P1\n", true, 0, false, 0.0},
|
||||
{"M66 E1 L0\n", false, 0, true, 42.13},
|
||||
{"M66 E1 L0\n", false, 0, true, -13.42},
|
||||
{"M67 E1 Q42.13\n", false, 0, false, 0.0},
|
||||
{"G0 X-1.0\n", false, 0, false, 0.0},
|
||||
{"M67 E1 Q-13.42\n", false, 0, false, 0.0},
|
||||
{"G0 X-2.0\n", false, 0, false, 0.0},
|
||||
{"M67 E1 Q0.0\n", false, 0, false, 0.0},
|
||||
{"G0 X-3.0\n", false, 0, false, 0.0},
|
||||
{"M68 E1 Q42.13\n", false, 0, false, 0.0},
|
||||
{"M68 E1 Q-13.42\n", false, 0, false, 0.0},
|
||||
{"M68 E1 Q0.0\n", false, 0, false, 0.0},
|
||||
};
|
||||
|
||||
for (const auto &step : steps) {
|
||||
if (step.digital_input) {
|
||||
standalone::set_external_digital_input(0, step.digital_value);
|
||||
}
|
||||
if (step.analog_input) {
|
||||
standalone::set_external_analog_input(0, step.analog_value);
|
||||
}
|
||||
ok &= execute_mdi(interp, "remap_io_ngc", step.command);
|
||||
std::cout << "remap_io_ngc_parameter_5399=" << interp._setup.parameters[5399] << "\n";
|
||||
std::cout << "remap_io_ngc_parameter_100=" << interp._setup.parameters[100] << "\n";
|
||||
}
|
||||
|
||||
std::cout << "remap_io_ngc_canon_event_count=" << standalone::canon_events().size() << "\n";
|
||||
for (const auto &event : standalone::canon_events()) {
|
||||
std::cout << "remap_io_ngc_canon_event=" << event << "\n";
|
||||
}
|
||||
|
||||
ok &= std::fabs(interp._setup.parameters[5399] - -13.42) < 1e-9;
|
||||
ok &= std::fabs(interp._setup.parameters[100] - -13.42) < 1e-9;
|
||||
print_bool("remap_io_ngc_linuxcnc_mdi_sequence", ok);
|
||||
unsetenv("INI_FILE_NAME");
|
||||
return ok;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
struct RegressionCase {
|
||||
const char *label;
|
||||
const char *rel;
|
||||
int expected_remaps;
|
||||
bool continue_on_error;
|
||||
bool expect_error;
|
||||
};
|
||||
|
||||
const RegressionCase cases[] = {
|
||||
{"duplicate_oword", "tests/remap/duplicate-o-word", 2, false, false},
|
||||
{"fail_args_0", "tests/remap/fail/args.0", 1, false, false},
|
||||
{"fail_args_1", "tests/remap/fail/args.1", 1, true, true},
|
||||
{"fail_args_2", "tests/remap/fail/args.2", 1, true, true},
|
||||
{"fail_body_ngc", "tests/remap/fail/body-ngc", 1, true, true},
|
||||
{"m30_interaction", "tests/remap/m30-interaction", 1, false, false},
|
||||
{"nested_remaps_oword", "tests/remap/nested-remaps-oword", 4, false, false},
|
||||
{"posargs_0", "tests/remap/posargs.0", 1, false, false},
|
||||
{"sequencing", "tests/remap/sequencing", 7, false, false},
|
||||
};
|
||||
|
||||
bool all_ok = true;
|
||||
for (const auto &test : cases) {
|
||||
const auto test_dir = vendor_path(test.rel);
|
||||
const auto ini_path = test_dir / "test.ini";
|
||||
const auto program_path = test_dir / "test.ngc";
|
||||
|
||||
setenv("INI_FILE_NAME", ini_path.c_str(), 1);
|
||||
|
||||
Interp interp;
|
||||
initialize_interp(interp);
|
||||
|
||||
bool ok = configure_remaps(interp, ini_path, test.label, test.expected_remaps);
|
||||
ok &= execute_file(interp,
|
||||
program_path,
|
||||
test.label,
|
||||
test.continue_on_error,
|
||||
test.expect_error);
|
||||
print_bool(std::string(test.label) + "_linuxcnc_regression_path", ok);
|
||||
all_ok &= ok;
|
||||
|
||||
unsetenv("INI_FILE_NAME");
|
||||
}
|
||||
|
||||
all_ok &= execute_remap_io_mdi_case();
|
||||
|
||||
print_bool("linuxcnc_upstream_remap_regression_path", all_ok);
|
||||
return all_ok ? 0 : 1;
|
||||
}
|
||||
@@ -59,6 +59,18 @@ std::unordered_map<std::string, std::vector<std::string>> &pin_aliases()
|
||||
return values;
|
||||
}
|
||||
|
||||
std::unordered_map<int, int> &digital_inputs()
|
||||
{
|
||||
static std::unordered_map<int, int> values;
|
||||
return values;
|
||||
}
|
||||
|
||||
std::unordered_map<int, double> &analog_inputs()
|
||||
{
|
||||
static std::unordered_map<int, double> values;
|
||||
return values;
|
||||
}
|
||||
|
||||
int lookup_hal_value(const char *name, std::unordered_map<std::string, HalEntry> &values,
|
||||
hal_type_t *type, hal_data_u **ptr, bool *connected)
|
||||
{
|
||||
@@ -89,6 +101,8 @@ void reset_hal_adapter()
|
||||
signals().clear();
|
||||
params().clear();
|
||||
pin_aliases().clear();
|
||||
digital_inputs().clear();
|
||||
analog_inputs().clear();
|
||||
}
|
||||
|
||||
void set_hal_value(HalValueKind kind, const char *name, hal_type_t type, hal_data_u value,
|
||||
@@ -130,6 +144,28 @@ void sync_motion_analog_output(int index, double value)
|
||||
}
|
||||
}
|
||||
|
||||
void set_external_digital_input(int index, int value)
|
||||
{
|
||||
digital_inputs()[index] = value ? 1 : 0;
|
||||
}
|
||||
|
||||
void set_external_analog_input(int index, double value)
|
||||
{
|
||||
analog_inputs()[index] = value;
|
||||
}
|
||||
|
||||
int external_digital_input(int index, int def)
|
||||
{
|
||||
auto it = digital_inputs().find(index);
|
||||
return it == digital_inputs().end() ? def : it->second;
|
||||
}
|
||||
|
||||
double external_analog_input(int index, double def)
|
||||
{
|
||||
auto it = analog_inputs().find(index);
|
||||
return it == analog_inputs().end() ? def : it->second;
|
||||
}
|
||||
|
||||
} // namespace standalone
|
||||
|
||||
int hal_init(const char *)
|
||||
|
||||
@@ -15,5 +15,9 @@ void set_hal_value(HalValueKind kind, const char *name, hal_type_t type, hal_dat
|
||||
bool connected = true);
|
||||
void link_hal_pin_alias(const char *source, const char *alias);
|
||||
void sync_motion_analog_output(int index, double value);
|
||||
void set_external_digital_input(int index, int value);
|
||||
void set_external_analog_input(int index, double value);
|
||||
int external_digital_input(int index, int def);
|
||||
double external_analog_input(int index, double def);
|
||||
|
||||
} // namespace standalone
|
||||
|
||||
@@ -3,13 +3,19 @@
|
||||
#undef private
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "canon_event_sink.hh"
|
||||
#include "emc/ini/inifile.hh"
|
||||
#include "linuxcnc_hal_adapter.hh"
|
||||
#include "linuxcnc_machine_config.hh"
|
||||
#include "linuxcnc_runtime_state.hh"
|
||||
#include "linuxcnc_tool_adapter.hh"
|
||||
|
||||
namespace {
|
||||
@@ -70,6 +76,7 @@ void initialize_minimal_interp(Interp &interp)
|
||||
{
|
||||
seed_hal_values();
|
||||
seed_tool_values();
|
||||
standalone::reset_external_axis_mask();
|
||||
interp._setup.length_units = CANON_UNITS_MM;
|
||||
interp._setup.distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
interp._setup.ijk_distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
@@ -85,7 +92,45 @@ void initialize_minimal_interp(Interp &interp)
|
||||
interp._setup.parameter_g83_peck_clearance = 1.0;
|
||||
interp._setup.parameters[5599] = 1.0;
|
||||
interp.load_tool_table();
|
||||
std::memcpy(interp._readers, Interp::default_readers, sizeof(Interp::default_readers));
|
||||
standalone::apply_axis_mask_to_interp(interp, standalone::axis_mask_from_coordinates("XYZABCUVW"));
|
||||
standalone::reset_user_m_code_registry();
|
||||
}
|
||||
|
||||
void apply_ini_search_paths(Interp &interp, const char *ini_path)
|
||||
{
|
||||
if (!ini_path || ini_path[0] == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
linuxcnc::IniFile ini(ini_path);
|
||||
if (!ini) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto machine_dir = std::filesystem::path(ini_path).parent_path();
|
||||
standalone::apply_machine_axis_config(interp, ini);
|
||||
standalone::load_tool_table_from_ini(interp, ini, machine_dir.c_str());
|
||||
standalone::register_user_m_codes_from_ini(ini, machine_dir.c_str());
|
||||
|
||||
std::snprintf(interp._setup.program_prefix, sizeof(interp._setup.program_prefix), "%s",
|
||||
machine_dir.c_str());
|
||||
|
||||
int subroutine_count = 0;
|
||||
if (auto subroutine_path_text = ini.findString("SUBROUTINE_PATH", "RS274NGC")) {
|
||||
std::stringstream paths(*subroutine_path_text);
|
||||
std::string entry;
|
||||
while (std::getline(paths, entry, ':') && subroutine_count < MAX_SUB_DIRS) {
|
||||
std::filesystem::path resolved(entry);
|
||||
if (resolved.is_relative()) {
|
||||
resolved = machine_dir / resolved;
|
||||
}
|
||||
interp._setup.subroutines[subroutine_count++] = strstore(resolved.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (ini.findBoolV("OWORD_NARGS", "RS274NGC", false)) {
|
||||
interp._setup.feature_set |= FEATURE_OWORD_N_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> load_program(int argc, char **argv)
|
||||
@@ -117,11 +162,25 @@ std::vector<std::string> load_program(int argc, char **argv)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
bool continue_on_error = false;
|
||||
int arg_offset = 1;
|
||||
if (argc > 1 && std::strcmp(argv[1], "--continue-on-error") == 0) {
|
||||
continue_on_error = true;
|
||||
arg_offset = 2;
|
||||
}
|
||||
|
||||
Interp interp;
|
||||
standalone::reset_canon_events();
|
||||
const char *ini_path = argc > arg_offset + 1 ? argv[arg_offset + 1] : nullptr;
|
||||
if (ini_path && ini_path[0] != '\0') {
|
||||
setenv("INI_FILE_NAME", ini_path, 1);
|
||||
} else {
|
||||
unsetenv("INI_FILE_NAME");
|
||||
}
|
||||
initialize_minimal_interp(interp);
|
||||
apply_ini_search_paths(interp, ini_path);
|
||||
|
||||
const std::vector<std::string> program = load_program(argc, argv);
|
||||
const std::vector<std::string> program = load_program(argc - arg_offset + 1, argv + arg_offset - 1);
|
||||
if (program.empty()) {
|
||||
std::cerr << "empty fixture\n";
|
||||
return 2;
|
||||
@@ -138,6 +197,7 @@ int main(int argc, char **argv)
|
||||
const int read_rc = interp.read(program.front().c_str());
|
||||
|
||||
initialize_minimal_interp(interp);
|
||||
apply_ini_search_paths(interp, ini_path);
|
||||
for (std::size_t idx = 0; idx < program.size(); ++idx) {
|
||||
interp._setup.sequence_number = static_cast<int>(idx + 1);
|
||||
const int execute_rc = interp.execute(program[idx].c_str());
|
||||
@@ -152,10 +212,13 @@ int main(int argc, char **argv)
|
||||
int file_open_rc = INTERP_FILE_NOT_OPEN;
|
||||
int file_read_count = 0;
|
||||
int file_execute_count = 0;
|
||||
if (argc > 1) {
|
||||
bool file_saw_error = false;
|
||||
if (argc > arg_offset) {
|
||||
Interp file_interp;
|
||||
standalone::reset_canon_events();
|
||||
initialize_minimal_interp(file_interp);
|
||||
file_open_rc = file_interp.open(argv[1]);
|
||||
apply_ini_search_paths(file_interp, ini_path);
|
||||
file_open_rc = file_interp.open(argv[arg_offset]);
|
||||
if (file_open_rc == INTERP_OK) {
|
||||
while (true) {
|
||||
const int file_read_rc = file_interp.read();
|
||||
@@ -166,8 +229,17 @@ int main(int argc, char **argv)
|
||||
++file_read_count;
|
||||
std::cout << "file_read_" << file_read_count << "=" << file_read_rc << "\n";
|
||||
if ((file_read_rc != INTERP_OK) && (file_read_rc != INTERP_EXECUTE_FINISH)) {
|
||||
if (file_read_rc > INTERP_MIN_ERROR) {
|
||||
char error_buf[LINELEN] = {0};
|
||||
file_interp.error_text(file_read_rc, error_buf, sizeof(error_buf));
|
||||
std::cout << "file_error_text=" << error_buf << "\n";
|
||||
}
|
||||
file_saw_error = true;
|
||||
if (!continue_on_error) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const int file_execute_rc = file_interp.execute();
|
||||
++file_execute_count;
|
||||
@@ -180,6 +252,7 @@ int main(int argc, char **argv)
|
||||
if ((file_execute_rc != INTERP_OK) &&
|
||||
(file_execute_rc != INTERP_EXECUTE_FINISH) &&
|
||||
(file_execute_rc != INTERP_EXIT)) {
|
||||
file_saw_error = true;
|
||||
break;
|
||||
}
|
||||
if (file_execute_rc == INTERP_EXIT) {
|
||||
@@ -200,6 +273,7 @@ int main(int argc, char **argv)
|
||||
std::cout << "file_open=" << file_open_rc << "\n";
|
||||
std::cout << "file_read_count=" << file_read_count << "\n";
|
||||
std::cout << "file_execute_count=" << file_execute_count << "\n";
|
||||
std::cout << "file_saw_error=" << (file_saw_error ? 1 : 0) << "\n";
|
||||
std::cout << "raw_line=" << raw_line << "\n";
|
||||
std::cout << "cooked_line=" << cooked_line << "\n";
|
||||
std::cout << "line_length=" << length << "\n";
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "emc/rs274ngc/rs274ngc_return.hh"
|
||||
#include "canon_event_sink.hh"
|
||||
#include "linuxcnc_hal_adapter.hh"
|
||||
#include "linuxcnc_runtime_state.hh"
|
||||
#include "linuxcnc_tool_adapter.hh"
|
||||
#include "nml_intf/emc.hh"
|
||||
|
||||
@@ -20,6 +21,7 @@ namespace standalone {
|
||||
|
||||
static std::vector<std::string> g_canon_events;
|
||||
static double g_external_feed_rate = 0.0;
|
||||
static int g_external_axis_mask = Interp::AXIS_MASK_X | Interp::AXIS_MASK_Y | Interp::AXIS_MASK_Z;
|
||||
|
||||
void reset_canon_events()
|
||||
{
|
||||
@@ -36,6 +38,23 @@ const std::vector<std::string> &canon_events()
|
||||
return g_canon_events;
|
||||
}
|
||||
|
||||
void reset_external_axis_mask()
|
||||
{
|
||||
g_external_axis_mask = Interp::AXIS_MASK_X | Interp::AXIS_MASK_Y | Interp::AXIS_MASK_Z;
|
||||
}
|
||||
|
||||
void set_external_axis_mask(int axis_mask)
|
||||
{
|
||||
g_external_axis_mask = axis_mask == 0
|
||||
? (Interp::AXIS_MASK_X | Interp::AXIS_MASK_Y | Interp::AXIS_MASK_Z)
|
||||
: axis_mask;
|
||||
}
|
||||
|
||||
int external_axis_mask()
|
||||
{
|
||||
return g_external_axis_mask;
|
||||
}
|
||||
|
||||
} // namespace standalone
|
||||
|
||||
bool GET_BLOCK_DELETE(void) { return false; }
|
||||
@@ -523,9 +542,15 @@ int GET_EXTERNAL_FEED_OVERRIDE_ENABLE() { return 1; }
|
||||
int GET_EXTERNAL_SPINDLE_OVERRIDE_ENABLE(int) { return 1; }
|
||||
int GET_EXTERNAL_ADAPTIVE_FEED_ENABLE() { return 1; }
|
||||
int GET_EXTERNAL_FEED_HOLD_ENABLE() { return 1; }
|
||||
int GET_EXTERNAL_DIGITAL_INPUT(int, int def) { return def; }
|
||||
double GET_EXTERNAL_ANALOG_INPUT(int, double def) { return def; }
|
||||
int GET_EXTERNAL_AXIS_MASK() { return 7; }
|
||||
int GET_EXTERNAL_DIGITAL_INPUT(int index, int def)
|
||||
{
|
||||
return standalone::external_digital_input(index, def);
|
||||
}
|
||||
double GET_EXTERNAL_ANALOG_INPUT(int index, double def)
|
||||
{
|
||||
return standalone::external_analog_input(index, def);
|
||||
}
|
||||
int GET_EXTERNAL_AXIS_MASK() { return standalone::external_axis_mask(); }
|
||||
int GET_EXTERNAL_OFFSET_APPLIED() { return 0; }
|
||||
EmcPose GET_EXTERNAL_OFFSETS() { return {{0, 0, 0}, 0, 0, 0, 0, 0, 0}; }
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "emc/rs274ngc/rs274ngc_interp.hh"
|
||||
#undef private
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
@@ -13,6 +14,8 @@
|
||||
#include "canon_event_sink.hh"
|
||||
#include "emc/ini/inifile.hh"
|
||||
#include "linuxcnc_hal_adapter.hh"
|
||||
#include "linuxcnc_machine_config.hh"
|
||||
#include "linuxcnc_runtime_state.hh"
|
||||
#include "linuxcnc_tool_adapter.hh"
|
||||
#include "nml_intf/emc.hh"
|
||||
#include "tooldata.hh"
|
||||
@@ -105,6 +108,7 @@ void initialize_minimal_interp(Interp &interp)
|
||||
{
|
||||
seed_hal_values();
|
||||
seed_tool_values();
|
||||
standalone::reset_external_axis_mask();
|
||||
interp._setup.length_units = CANON_UNITS_MM;
|
||||
interp._setup.distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
interp._setup.ijk_distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
@@ -120,13 +124,15 @@ void initialize_minimal_interp(Interp &interp)
|
||||
interp._setup.parameter_g83_peck_clearance = 1.0;
|
||||
interp._setup.parameters[5599] = 1.0;
|
||||
interp.load_tool_table();
|
||||
std::memcpy(interp._readers, Interp::default_readers, sizeof(Interp::default_readers));
|
||||
standalone::apply_axis_mask_to_interp(interp, standalone::axis_mask_from_coordinates("XYZABCUVW"));
|
||||
standalone::reset_user_m_code_registry();
|
||||
}
|
||||
|
||||
void initialize_fiveaxis_remap_interp(Interp &interp)
|
||||
{
|
||||
seed_switchkins_hal();
|
||||
seed_tool_values();
|
||||
standalone::reset_external_axis_mask();
|
||||
interp._setup.length_units = CANON_UNITS_MM;
|
||||
interp._setup.distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
interp._setup.ijk_distance_mode = DISTANCE_MODE::INCREMENTAL;
|
||||
@@ -142,7 +148,8 @@ void initialize_fiveaxis_remap_interp(Interp &interp)
|
||||
interp._setup.parameter_g83_peck_clearance = 1.0;
|
||||
interp._setup.parameters[5599] = 1.0;
|
||||
interp.load_tool_table();
|
||||
std::memcpy(interp._readers, Interp::default_readers, sizeof(Interp::default_readers));
|
||||
standalone::apply_axis_mask_to_interp(interp, standalone::axis_mask_from_coordinates("XYZABCUVW"));
|
||||
standalone::reset_user_m_code_registry();
|
||||
interp.init_named_parameters();
|
||||
}
|
||||
|
||||
@@ -274,6 +281,15 @@ void append_named_value(std::ostringstream &output, Interp &interp, const char *
|
||||
output << name << ": rc=" << rc << " found=" << status << " value=" << value << "\n";
|
||||
}
|
||||
|
||||
std::string command_label(const char *command)
|
||||
{
|
||||
std::string value = command ? command : "";
|
||||
while (!value.empty() && (value.back() == '\n' || value.back() == '\r')) {
|
||||
value.pop_back();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string parent_path(const char *path)
|
||||
{
|
||||
std::string value = path ? path : "";
|
||||
@@ -329,6 +345,88 @@ bool parse_machine_remaps(Interp &interp, std::ostringstream &output, const char
|
||||
return ok;
|
||||
}
|
||||
|
||||
std::string remap_subroutine_path(const std::string &machine_dir, const std::string &entry)
|
||||
{
|
||||
if (!entry.empty() && entry[0] == '/') {
|
||||
return entry;
|
||||
}
|
||||
if (machine_dir == "/") {
|
||||
return machine_dir + entry;
|
||||
}
|
||||
return machine_dir + "/" + entry;
|
||||
}
|
||||
|
||||
int apply_ini_search_paths(Interp &interp, const linuxcnc::IniFile &ini, const std::string &machine_dir)
|
||||
{
|
||||
standalone::apply_machine_axis_config(interp, ini);
|
||||
standalone::load_tool_table_from_ini(interp, ini, machine_dir.c_str());
|
||||
standalone::register_user_m_codes_from_ini(ini, machine_dir.c_str());
|
||||
|
||||
std::snprintf(interp._setup.program_prefix, sizeof(interp._setup.program_prefix), "%s",
|
||||
machine_dir.c_str());
|
||||
|
||||
int subroutine_count = 0;
|
||||
if (auto subroutine_path_text = ini.findString("SUBROUTINE_PATH", "RS274NGC")) {
|
||||
std::istringstream paths(*subroutine_path_text);
|
||||
std::string entry;
|
||||
while (std::getline(paths, entry, ':') && subroutine_count < MAX_SUB_DIRS) {
|
||||
const std::string resolved = remap_subroutine_path(machine_dir, entry);
|
||||
interp._setup.subroutines[subroutine_count++] = strstore(resolved.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (ini.findBoolV("OWORD_NARGS", "RS274NGC", false)) {
|
||||
interp._setup.feature_set |= FEATURE_OWORD_N_ARGS;
|
||||
}
|
||||
|
||||
return subroutine_count;
|
||||
}
|
||||
|
||||
bool apply_ini_search_paths(Interp &interp, const char *ini_path)
|
||||
{
|
||||
if (!ini_path || ini_path[0] == '\0') {
|
||||
return true;
|
||||
}
|
||||
|
||||
linuxcnc::IniFile ini(ini_path);
|
||||
if (!ini) {
|
||||
return false;
|
||||
}
|
||||
|
||||
apply_ini_search_paths(interp, ini, parent_path(ini_path));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_remaps_from_ini(Interp &interp, std::ostringstream &output, const char *ini_path)
|
||||
{
|
||||
const std::string machine_dir = parent_path(ini_path);
|
||||
|
||||
linuxcnc::IniFile ini(ini_path ? ini_path : "");
|
||||
const bool opened = static_cast<bool>(ini);
|
||||
output << "remap_ini_open=" << (opened ? 1 : 0) << "\n";
|
||||
if (!opened) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int subroutine_count = apply_ini_search_paths(interp, ini, machine_dir);
|
||||
output << "remap_subroutine_path_count=" << subroutine_count << "\n";
|
||||
|
||||
bool ok = subroutine_count > 0;
|
||||
int remap_count = 0;
|
||||
while (auto remap = ini.findString(++remap_count, "REMAP", "RS274NGC")) {
|
||||
const int line_number = ini.lineOf(remap_count, "REMAP", "RS274NGC").second;
|
||||
const int rc = interp.parse_remap(remap->c_str(), line_number);
|
||||
output << "remap_parse_remap_" << remap_count << "=" << rc << "\n";
|
||||
ok &= rc == INTERP_OK;
|
||||
}
|
||||
|
||||
remap_count -= 1;
|
||||
output << "remap_parsed_remap_count=" << remap_count << "\n";
|
||||
ok &= remap_count > 0;
|
||||
output << "remap_remaps_ready=" << (ok ? 1 : 0) << "\n";
|
||||
return ok;
|
||||
}
|
||||
|
||||
void apply_parameter_assignments(Interp &interp, const char *assignments)
|
||||
{
|
||||
std::istringstream input(assignments ? assignments : "");
|
||||
@@ -371,6 +469,7 @@ char *lcinterp_run_program_with_ini(const char *program_text, const char *ini_pa
|
||||
Interp interp;
|
||||
standalone::reset_canon_events();
|
||||
initialize_minimal_interp(interp);
|
||||
apply_ini_search_paths(interp, ini_path);
|
||||
|
||||
const std::vector<std::string> program = split_program_lines(program_text);
|
||||
std::ostringstream output;
|
||||
@@ -401,8 +500,7 @@ char *lcinterp_run_program(const char *program_text)
|
||||
return lcinterp_run_program_with_ini(program_text, nullptr);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
char *lcinterp_run_file_with_ini(const char *path, const char *ini_path)
|
||||
char *run_file_with_ini_internal(const char *path, const char *ini_path, bool continue_on_error)
|
||||
{
|
||||
if (ini_path && ini_path[0] != '\0') {
|
||||
setenv("INI_FILE_NAME", ini_path, 1);
|
||||
@@ -415,6 +513,8 @@ char *lcinterp_run_file_with_ini(const char *path, const char *ini_path)
|
||||
initialize_minimal_interp(interp);
|
||||
|
||||
std::ostringstream output;
|
||||
apply_ini_search_paths(interp, ini_path);
|
||||
|
||||
const int open_rc = interp.open(path);
|
||||
output << "file_open=" << open_rc << "\n";
|
||||
if (open_rc != INTERP_OK) {
|
||||
@@ -429,6 +529,7 @@ char *lcinterp_run_file_with_ini(const char *path, const char *ini_path)
|
||||
|
||||
int file_read_count = 0;
|
||||
int file_execute_count = 0;
|
||||
bool saw_error = false;
|
||||
while (true) {
|
||||
const int read_rc = interp.read();
|
||||
if (read_rc == INTERP_ENDFILE) {
|
||||
@@ -444,8 +545,12 @@ char *lcinterp_run_file_with_ini(const char *path, const char *ini_path)
|
||||
interp.error_text(read_rc, error_buf, sizeof(error_buf));
|
||||
output << "file_error_text=" << error_buf << "\n";
|
||||
}
|
||||
saw_error = true;
|
||||
if (!continue_on_error) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const int execute_rc = interp.execute();
|
||||
++file_execute_count;
|
||||
@@ -458,6 +563,7 @@ char *lcinterp_run_file_with_ini(const char *path, const char *ini_path)
|
||||
if ((execute_rc != INTERP_OK) &&
|
||||
(execute_rc != INTERP_EXECUTE_FINISH) &&
|
||||
(execute_rc != INTERP_EXIT)) {
|
||||
saw_error = true;
|
||||
break;
|
||||
}
|
||||
if (execute_rc == INTERP_EXIT) {
|
||||
@@ -467,10 +573,23 @@ char *lcinterp_run_file_with_ini(const char *path, const char *ini_path)
|
||||
|
||||
output << "file_read_count=" << file_read_count << "\n";
|
||||
output << "file_execute_count=" << file_execute_count << "\n";
|
||||
output << "file_saw_error=" << (saw_error ? 1 : 0) << "\n";
|
||||
append_events_and_state(output, interp);
|
||||
return copy_result(output.str());
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
char *lcinterp_run_file_with_ini(const char *path, const char *ini_path)
|
||||
{
|
||||
return run_file_with_ini_internal(path, ini_path, false);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
char *lcinterp_run_file_with_ini_continue_on_error(const char *path, const char *ini_path)
|
||||
{
|
||||
return run_file_with_ini_internal(path, ini_path, true);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
char *lcinterp_run_file(const char *path)
|
||||
{
|
||||
@@ -573,6 +692,230 @@ char *lcinterp_run_fiveaxis_remap_file(const char *path, const char *ini_path)
|
||||
return copy_result(output.str());
|
||||
}
|
||||
|
||||
char *run_remap_file_internal(const char *path,
|
||||
const char *ini_path,
|
||||
bool continue_on_error,
|
||||
bool expect_error)
|
||||
{
|
||||
if (ini_path && ini_path[0] != '\0') {
|
||||
setenv("INI_FILE_NAME", ini_path, 1);
|
||||
} else {
|
||||
unsetenv("INI_FILE_NAME");
|
||||
}
|
||||
|
||||
Interp interp;
|
||||
standalone::reset_canon_events();
|
||||
initialize_minimal_interp(interp);
|
||||
interp.init_named_parameters();
|
||||
|
||||
std::ostringstream output;
|
||||
bool ok = parse_remaps_from_ini(interp, output, ini_path);
|
||||
|
||||
const int open_rc = interp.open(path);
|
||||
output << "remap_file_open=" << open_rc << "\n";
|
||||
if (open_rc != INTERP_OK) {
|
||||
append_error_text(output, interp, "remap_file_error_text=", open_rc);
|
||||
output << "remap_linuxcnc_file_execute=0\n";
|
||||
unsetenv("INI_FILE_NAME");
|
||||
return copy_result(output.str());
|
||||
}
|
||||
|
||||
constexpr int max_file_steps = 20000;
|
||||
int file_read_count = 0;
|
||||
int file_execute_count = 0;
|
||||
int file_finish_count = 0;
|
||||
int final_rc = INTERP_OK;
|
||||
bool reached_exit = false;
|
||||
bool reached_endfile = false;
|
||||
bool saw_error = false;
|
||||
|
||||
while ((file_read_count < max_file_steps) && (file_execute_count < max_file_steps)) {
|
||||
const int read_rc = interp.read();
|
||||
if (read_rc == INTERP_ENDFILE) {
|
||||
output << "remap_file_read_eof=" << read_rc << "\n";
|
||||
final_rc = read_rc;
|
||||
reached_endfile = true;
|
||||
break;
|
||||
}
|
||||
|
||||
++file_read_count;
|
||||
if ((read_rc != INTERP_OK) && (read_rc != INTERP_EXECUTE_FINISH)) {
|
||||
output << "remap_file_read_" << file_read_count << "=" << read_rc << "\n";
|
||||
append_error_text(output, interp, "remap_file_error_text=", read_rc);
|
||||
final_rc = read_rc;
|
||||
saw_error = true;
|
||||
if (!expect_error) {
|
||||
ok = false;
|
||||
}
|
||||
if (!continue_on_error) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const int execute_rc = interp.execute();
|
||||
++file_execute_count;
|
||||
final_rc = execute_rc;
|
||||
if (execute_rc == INTERP_EXECUTE_FINISH) {
|
||||
++file_finish_count;
|
||||
}
|
||||
if ((execute_rc != INTERP_OK) && (execute_rc != INTERP_EXIT) &&
|
||||
(execute_rc != INTERP_EXECUTE_FINISH)) {
|
||||
output << "remap_file_execute_" << file_execute_count << "=" << execute_rc << "\n";
|
||||
append_error_text(output, interp, "remap_file_error_text=", execute_rc);
|
||||
saw_error = true;
|
||||
if (!expect_error) {
|
||||
ok = false;
|
||||
}
|
||||
if (!continue_on_error) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (execute_rc == INTERP_EXIT) {
|
||||
reached_exit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
output << "remap_file_read_count=" << file_read_count << "\n";
|
||||
output << "remap_file_execute_count=" << file_execute_count << "\n";
|
||||
output << "remap_file_finish_count=" << file_finish_count << "\n";
|
||||
output << "remap_file_final_rc=" << final_rc << "\n";
|
||||
output << "remap_file_reached_exit=" << (reached_exit ? 1 : 0) << "\n";
|
||||
output << "remap_file_reached_endfile=" << (reached_endfile ? 1 : 0) << "\n";
|
||||
output << "remap_file_saw_error=" << (saw_error ? 1 : 0) << "\n";
|
||||
for (const auto &event : standalone::canon_events()) {
|
||||
output << "remap_canon_event=" << event << "\n";
|
||||
}
|
||||
|
||||
ok &= file_read_count > 0;
|
||||
ok &= file_execute_count > 0;
|
||||
ok &= file_read_count < max_file_steps;
|
||||
ok &= file_execute_count < max_file_steps;
|
||||
ok &= reached_exit || reached_endfile;
|
||||
ok &= expect_error ? saw_error : !saw_error;
|
||||
|
||||
output << "remap_linuxcnc_file_execute=" << (ok ? 1 : 0) << "\n";
|
||||
unsetenv("INI_FILE_NAME");
|
||||
return copy_result(output.str());
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
bool execute_remap_mdi_command(Interp &interp, std::ostringstream &output, const char *command)
|
||||
{
|
||||
const std::string label = command_label(command);
|
||||
int rc = interp.execute(command);
|
||||
output << "remap_mdi_" << label << "_execute_0=" << rc << "\n";
|
||||
|
||||
int finish_count = 0;
|
||||
while (rc == INTERP_EXECUTE_FINISH && finish_count < 16) {
|
||||
++finish_count;
|
||||
rc = interp.execute();
|
||||
output << "remap_mdi_" << label << "_execute_" << finish_count << "=" << rc << "\n";
|
||||
}
|
||||
|
||||
output << "remap_mdi_" << label << "_execute_finish_count=" << finish_count << "\n";
|
||||
return rc == INTERP_OK;
|
||||
}
|
||||
|
||||
char *run_remap_io_mdi_sequence_internal(const char *ini_path)
|
||||
{
|
||||
if (ini_path && ini_path[0] != '\0') {
|
||||
setenv("INI_FILE_NAME", ini_path, 1);
|
||||
} else {
|
||||
unsetenv("INI_FILE_NAME");
|
||||
}
|
||||
|
||||
Interp interp;
|
||||
standalone::reset_canon_events();
|
||||
initialize_minimal_interp(interp);
|
||||
interp.init_named_parameters();
|
||||
|
||||
std::ostringstream output;
|
||||
bool ok = parse_remaps_from_ini(interp, output, ini_path);
|
||||
ok &= output.str().find("remap_parsed_remap_count=7") != std::string::npos;
|
||||
|
||||
const struct MdiStep {
|
||||
const char *command;
|
||||
bool digital_input;
|
||||
int digital_value;
|
||||
bool analog_input;
|
||||
double analog_value;
|
||||
} steps[] = {
|
||||
{"M62 P1\n", false, 0, false, 0.0},
|
||||
{"G0 X1.0\n", false, 0, false, 0.0},
|
||||
{"M63 P1\n", false, 0, false, 0.0},
|
||||
{"G0 X2.0\n", false, 0, false, 0.0},
|
||||
{"M62 P1\n", false, 0, false, 0.0},
|
||||
{"G0 X3.0\n", false, 0, false, 0.0},
|
||||
{"M63 P1\n", false, 0, false, 0.0},
|
||||
{"G0 X4.0\n", false, 0, false, 0.0},
|
||||
{"M64 P1\n", false, 0, false, 0.0},
|
||||
{"M65 P1\n", false, 0, false, 0.0},
|
||||
{"M64 P1\n", false, 0, false, 0.0},
|
||||
{"M65 P1\n", false, 0, false, 0.0},
|
||||
{"M66 P1\n", true, 1, false, 0.0},
|
||||
{"M66 P1\n", true, 0, false, 0.0},
|
||||
{"M66 E1 L0\n", false, 0, true, 42.13},
|
||||
{"M66 E1 L0\n", false, 0, true, -13.42},
|
||||
{"M67 E1 Q42.13\n", false, 0, false, 0.0},
|
||||
{"G0 X-1.0\n", false, 0, false, 0.0},
|
||||
{"M67 E1 Q-13.42\n", false, 0, false, 0.0},
|
||||
{"G0 X-2.0\n", false, 0, false, 0.0},
|
||||
{"M67 E1 Q0.0\n", false, 0, false, 0.0},
|
||||
{"G0 X-3.0\n", false, 0, false, 0.0},
|
||||
{"M68 E1 Q42.13\n", false, 0, false, 0.0},
|
||||
{"M68 E1 Q-13.42\n", false, 0, false, 0.0},
|
||||
{"M68 E1 Q0.0\n", false, 0, false, 0.0},
|
||||
};
|
||||
|
||||
for (const auto &step : steps) {
|
||||
if (step.digital_input) {
|
||||
standalone::set_external_digital_input(0, step.digital_value);
|
||||
}
|
||||
if (step.analog_input) {
|
||||
standalone::set_external_analog_input(0, step.analog_value);
|
||||
}
|
||||
ok &= execute_remap_mdi_command(interp, output, step.command);
|
||||
output << "remap_mdi_parameter_5399=" << interp._setup.parameters[5399] << "\n";
|
||||
output << "remap_mdi_parameter_100=" << interp._setup.parameters[100] << "\n";
|
||||
}
|
||||
|
||||
output << "remap_mdi_canon_event_count=" << standalone::canon_events().size() << "\n";
|
||||
for (const auto &event : standalone::canon_events()) {
|
||||
output << "remap_mdi_canon_event=" << event << "\n";
|
||||
}
|
||||
|
||||
ok &= std::fabs(interp._setup.parameters[5399] - -13.42) < 1e-9;
|
||||
ok &= std::fabs(interp._setup.parameters[100] - -13.42) < 1e-9;
|
||||
output << "remap_io_ngc_linuxcnc_mdi_sequence=" << (ok ? 1 : 0) << "\n";
|
||||
unsetenv("INI_FILE_NAME");
|
||||
return copy_result(output.str());
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
char *lcinterp_run_remap_file(const char *path, const char *ini_path)
|
||||
{
|
||||
return run_remap_file_internal(path, ini_path, false, false);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
char *lcinterp_run_remap_file_continue_on_error(const char *path, const char *ini_path)
|
||||
{
|
||||
return run_remap_file_internal(path, ini_path, true, true);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
char *lcinterp_run_remap_io_mdi_sequence(const char *ini_path)
|
||||
{
|
||||
return run_remap_io_mdi_sequence_internal(ini_path);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
char *lcinterp_restore_parameters(const char *path)
|
||||
{
|
||||
|
||||
280
wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_machine_config.cpp
Normal file
280
wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_machine_config.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
#define private public
|
||||
#include "emc/rs274ngc/rs274ngc_interp.hh"
|
||||
#undef private
|
||||
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "emc/ini/inifile.hh"
|
||||
#include "canon_event_sink.hh"
|
||||
#include "linuxcnc_machine_config.hh"
|
||||
#include "linuxcnc_runtime_state.hh"
|
||||
#include "tooldata.hh"
|
||||
|
||||
namespace standalone {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kDefaultAxisMask = Interp::AXIS_MASK_X | Interp::AXIS_MASK_Y | Interp::AXIS_MASK_Z;
|
||||
constexpr int kMaxUserMDirs = 6;
|
||||
|
||||
std::string g_user_m_paths[USER_DEFINED_FUNCTION_NUM];
|
||||
|
||||
bool is_executable_file(const std::filesystem::path &path)
|
||||
{
|
||||
struct stat st {};
|
||||
return stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode) && (st.st_mode & S_IXUSR);
|
||||
}
|
||||
|
||||
std::filesystem::path resolve_machine_path(const std::filesystem::path &machine_dir, const std::string &entry)
|
||||
{
|
||||
std::filesystem::path path(entry);
|
||||
if (path.is_relative()) {
|
||||
path = machine_dir / path;
|
||||
}
|
||||
return path.lexically_normal();
|
||||
}
|
||||
|
||||
void standalone_user_m_code(int num, double arg1, double arg2)
|
||||
{
|
||||
FINISH();
|
||||
const int code = num + 100;
|
||||
std::ostringstream event;
|
||||
event << "USER_M_COMMAND code=M" << code
|
||||
<< " path=" << g_user_m_paths[num]
|
||||
<< " p=" << arg1
|
||||
<< " q=" << arg2;
|
||||
push_canon_event(event.str());
|
||||
}
|
||||
|
||||
int axis_mask_for_letter(char letter)
|
||||
{
|
||||
switch (std::toupper(static_cast<unsigned char>(letter))) {
|
||||
case 'X':
|
||||
return Interp::AXIS_MASK_X;
|
||||
case 'Y':
|
||||
return Interp::AXIS_MASK_Y;
|
||||
case 'Z':
|
||||
return Interp::AXIS_MASK_Z;
|
||||
case 'A':
|
||||
return Interp::AXIS_MASK_A;
|
||||
case 'B':
|
||||
return Interp::AXIS_MASK_B;
|
||||
case 'C':
|
||||
return Interp::AXIS_MASK_C;
|
||||
case 'U':
|
||||
return Interp::AXIS_MASK_U;
|
||||
case 'V':
|
||||
return Interp::AXIS_MASK_V;
|
||||
case 'W':
|
||||
return Interp::AXIS_MASK_W;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int axis_mask_from_coordinates(const char *coordinates)
|
||||
{
|
||||
if (!coordinates || coordinates[0] == '\0') {
|
||||
return kDefaultAxisMask;
|
||||
}
|
||||
|
||||
int axis_mask = 0;
|
||||
for (const char *cursor = coordinates; *cursor; ++cursor) {
|
||||
axis_mask |= axis_mask_for_letter(*cursor);
|
||||
}
|
||||
return axis_mask == 0 ? kDefaultAxisMask : axis_mask;
|
||||
}
|
||||
|
||||
int axis_mask_from_ini(const char *ini_path)
|
||||
{
|
||||
if (!ini_path || ini_path[0] == '\0') {
|
||||
return kDefaultAxisMask;
|
||||
}
|
||||
|
||||
linuxcnc::IniFile ini(ini_path);
|
||||
if (!ini) {
|
||||
return kDefaultAxisMask;
|
||||
}
|
||||
|
||||
if (auto coordinates = ini.findString("COORDINATES", "TRAJ")) {
|
||||
return axis_mask_from_coordinates(coordinates->c_str());
|
||||
}
|
||||
return kDefaultAxisMask;
|
||||
}
|
||||
|
||||
void apply_axis_mask_to_interp(Interp &interp, int axis_mask)
|
||||
{
|
||||
if (axis_mask == 0) {
|
||||
axis_mask = kDefaultAxisMask;
|
||||
}
|
||||
|
||||
set_external_axis_mask(axis_mask);
|
||||
std::memcpy(interp._readers, Interp::default_readers, sizeof(Interp::default_readers));
|
||||
if (!(axis_mask & Interp::AXIS_MASK_X)) {
|
||||
interp._readers[static_cast<int>('x')] = nullptr;
|
||||
}
|
||||
if (!(axis_mask & Interp::AXIS_MASK_Y)) {
|
||||
interp._readers[static_cast<int>('y')] = nullptr;
|
||||
}
|
||||
if (!(axis_mask & Interp::AXIS_MASK_Z)) {
|
||||
interp._readers[static_cast<int>('z')] = nullptr;
|
||||
}
|
||||
if (!(axis_mask & Interp::AXIS_MASK_A)) {
|
||||
interp._readers[static_cast<int>('a')] = nullptr;
|
||||
}
|
||||
if (!(axis_mask & Interp::AXIS_MASK_B)) {
|
||||
interp._readers[static_cast<int>('b')] = nullptr;
|
||||
}
|
||||
if (!(axis_mask & Interp::AXIS_MASK_C)) {
|
||||
interp._readers[static_cast<int>('c')] = nullptr;
|
||||
}
|
||||
if (!(axis_mask & Interp::AXIS_MASK_U)) {
|
||||
interp._readers[static_cast<int>('u')] = nullptr;
|
||||
}
|
||||
if (!(axis_mask & Interp::AXIS_MASK_V)) {
|
||||
interp._readers[static_cast<int>('v')] = nullptr;
|
||||
}
|
||||
if (!(axis_mask & Interp::AXIS_MASK_W)) {
|
||||
interp._readers[static_cast<int>('w')] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void apply_machine_axis_config(Interp &interp, const linuxcnc::IniFile &ini)
|
||||
{
|
||||
interp._setup.orient_offset = ini.findRealV("ORIENT_OFFSET", "RS274NGC", 0.0);
|
||||
interp._setup.disable_fanuc_style_sub =
|
||||
ini.findBoolV("DISABLE_FANUC_STYLE_SUB", "RS274NGC", false);
|
||||
|
||||
if (auto coordinates = ini.findString("COORDINATES", "TRAJ")) {
|
||||
apply_axis_mask_to_interp(interp, axis_mask_from_coordinates(coordinates->c_str()));
|
||||
return;
|
||||
}
|
||||
apply_axis_mask_to_interp(interp, kDefaultAxisMask);
|
||||
}
|
||||
|
||||
bool apply_machine_axis_config(Interp &interp, const char *ini_path)
|
||||
{
|
||||
if (!ini_path || ini_path[0] == '\0') {
|
||||
apply_axis_mask_to_interp(interp, kDefaultAxisMask);
|
||||
return true;
|
||||
}
|
||||
|
||||
linuxcnc::IniFile ini(ini_path);
|
||||
if (!ini) {
|
||||
apply_axis_mask_to_interp(interp, kDefaultAxisMask);
|
||||
return false;
|
||||
}
|
||||
apply_machine_axis_config(interp, ini);
|
||||
return true;
|
||||
}
|
||||
|
||||
int load_tool_table_from_ini(Interp &interp, const linuxcnc::IniFile &ini, const char *machine_dir)
|
||||
{
|
||||
if (auto tool_table = ini.findString("TOOL_TABLE", "EMCIO")) {
|
||||
const std::filesystem::path base_dir = (machine_dir && machine_dir[0] != '\0')
|
||||
? std::filesystem::path(machine_dir)
|
||||
: std::filesystem::path();
|
||||
const std::filesystem::path tool_path = resolve_machine_path(base_dir, *tool_table);
|
||||
const bool random_toolchanger = ini.findBoolV("RANDOM_TOOLCHANGER", "EMCIO", false);
|
||||
|
||||
interp._setup.random_toolchanger = random_toolchanger;
|
||||
tooldata_init(random_toolchanger);
|
||||
tooldata_set_db(DB_NOTUSED);
|
||||
const int rc = tooldata_load(tool_path.c_str());
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
return interp.load_tool_table();
|
||||
}
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int load_tool_table_from_ini(Interp &interp, const char *ini_path)
|
||||
{
|
||||
if (!ini_path || ini_path[0] == '\0') {
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
linuxcnc::IniFile ini(ini_path);
|
||||
if (!ini) {
|
||||
return -1;
|
||||
}
|
||||
const std::filesystem::path machine_dir = std::filesystem::path(ini_path).parent_path();
|
||||
return load_tool_table_from_ini(interp, ini, machine_dir.c_str());
|
||||
}
|
||||
|
||||
void reset_user_m_code_registry()
|
||||
{
|
||||
for (int index = 0; index < USER_DEFINED_FUNCTION_NUM; ++index) {
|
||||
USER_DEFINED_FUNCTION[index] = nullptr;
|
||||
g_user_m_paths[index].clear();
|
||||
}
|
||||
}
|
||||
|
||||
int register_user_m_codes_from_ini(const linuxcnc::IniFile &ini, const char *machine_dir)
|
||||
{
|
||||
std::filesystem::path base_dir = (machine_dir && machine_dir[0] != '\0')
|
||||
? std::filesystem::path(machine_dir)
|
||||
: std::filesystem::current_path();
|
||||
|
||||
std::string program_prefix = "nc_files";
|
||||
if (auto prefix = ini.findString("PROGRAM_PREFIX", "DISPLAY")) {
|
||||
program_prefix = *prefix;
|
||||
}
|
||||
|
||||
std::filesystem::path dirs[kMaxUserMDirs];
|
||||
int dir_count = 0;
|
||||
dirs[dir_count++] = resolve_machine_path(base_dir, program_prefix);
|
||||
|
||||
if (auto user_m_path = ini.findString("USER_M_PATH", "RS274NGC")) {
|
||||
std::istringstream entries(*user_m_path);
|
||||
std::string entry;
|
||||
while (std::getline(entries, entry, ':') && dir_count < kMaxUserMDirs) {
|
||||
if (!entry.empty()) {
|
||||
dirs[dir_count++] = resolve_machine_path(base_dir, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int registered = 0;
|
||||
for (int num = 0; num < USER_DEFINED_FUNCTION_NUM; ++num) {
|
||||
for (int dir_index = 0; dir_index < dir_count; ++dir_index) {
|
||||
char file_name[8] = {0};
|
||||
std::snprintf(file_name, sizeof(file_name), "M1%02d", num);
|
||||
std::filesystem::path candidate = dirs[dir_index] / file_name;
|
||||
if (!is_executable_file(candidate)) {
|
||||
continue;
|
||||
}
|
||||
USER_DEFINED_FUNCTION_ADD(standalone_user_m_code, num);
|
||||
g_user_m_paths[num] = candidate.string();
|
||||
++registered;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return registered;
|
||||
}
|
||||
|
||||
int register_user_m_codes_from_ini(const char *ini_path)
|
||||
{
|
||||
if (!ini_path || ini_path[0] == '\0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
linuxcnc::IniFile ini(ini_path);
|
||||
if (!ini) {
|
||||
return 0;
|
||||
}
|
||||
const std::filesystem::path machine_dir = std::filesystem::path(ini_path).parent_path();
|
||||
return register_user_m_codes_from_ini(ini, machine_dir.c_str());
|
||||
}
|
||||
|
||||
} // namespace standalone
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
class Interp;
|
||||
|
||||
namespace linuxcnc {
|
||||
class IniFile;
|
||||
}
|
||||
|
||||
namespace standalone {
|
||||
|
||||
int axis_mask_from_coordinates(const char *coordinates);
|
||||
int axis_mask_from_ini(const char *ini_path);
|
||||
void apply_axis_mask_to_interp(Interp &interp, int axis_mask);
|
||||
void apply_machine_axis_config(Interp &interp, const linuxcnc::IniFile &ini);
|
||||
bool apply_machine_axis_config(Interp &interp, const char *ini_path);
|
||||
int load_tool_table_from_ini(Interp &interp, const linuxcnc::IniFile &ini, const char *machine_dir);
|
||||
int load_tool_table_from_ini(Interp &interp, const char *ini_path);
|
||||
void reset_user_m_code_registry();
|
||||
int register_user_m_codes_from_ini(const linuxcnc::IniFile &ini, const char *machine_dir);
|
||||
int register_user_m_codes_from_ini(const char *ini_path);
|
||||
|
||||
} // namespace standalone
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace standalone {
|
||||
|
||||
void reset_external_axis_mask();
|
||||
void set_external_axis_mask(int axis_mask);
|
||||
int external_axis_mask();
|
||||
|
||||
} // namespace standalone
|
||||
@@ -39,7 +39,11 @@ vendored LinuxCNC RS274NGC sources and exposes:
|
||||
- `runProgramWithIni(programText, iniPath)`
|
||||
- `runFile(path)`
|
||||
- `runFileWithIni(path, iniPath)`
|
||||
- `runFileWithIniContinueOnError(path, iniPath)`
|
||||
- `runSimConfigProgram({ iniPath, programPath, files, executionMode })`
|
||||
- `runFiveAxisRemapFile(path, iniPath)`
|
||||
- `runRemapFile(path, iniPath)`
|
||||
- `runRemapIoMdiSequence(iniPath)`
|
||||
- `restoreParameters(path)`
|
||||
- `saveParameters(path, values)`
|
||||
- `loadToolTable(path, options)`
|
||||
@@ -55,3 +59,33 @@ LinuxCNC random-toolchanger branch before calling vendored
|
||||
sample-machine remap validation. Callers provide INI/remap/demo files in the
|
||||
WASM filesystem; the C ABI runs vendored LinuxCNC `REMAP`, O-word, file
|
||||
execution, and HAL adapter paths.
|
||||
|
||||
`runRemapFile()` is the generic remap-test equivalent for vendored LinuxCNC
|
||||
tests such as `tests/remap/duplicate-o-word`. It reads LinuxCNC INI
|
||||
`SUBROUTINE_PATH` and `REMAP` entries, then calls vendored LinuxCNC
|
||||
`Interp::parse_remap()`, `open()`, `read()`, and `execute()`.
|
||||
|
||||
`runRemapIoMdiSequence()` is a narrow regression boundary for the NGC-only
|
||||
branch of vendored LinuxCNC `tests/remap/remap-io/test-ngc.ini`. The C ABI
|
||||
reads LinuxCNC `REMAP` entries, then feeds the upstream test driver's MDI
|
||||
command sequence into vendored `Interp::execute()`. JavaScript only copies the
|
||||
vendored INI/subroutine files into the WASM filesystem and forwards the INI
|
||||
path; it does not implement M62-M68, M66 input, or remap semantics.
|
||||
|
||||
`runFileWithIni()` is the plain interpreter-file equivalent for upstream tests
|
||||
that need LinuxCNC INI search paths, such as
|
||||
`tests/interp/sub-call-from-sub`. The C ABI reads LinuxCNC
|
||||
`SUBROUTINE_PATH` and then calls vendored `Interp::open()`, `read()`, and
|
||||
`execute()`; the SDK only copies files and forwards paths.
|
||||
|
||||
`runSimConfigProgram()` is a convenience host boundary for representative
|
||||
LinuxCNC `configs/sim` programs. Callers provide `{ path, text, executable }`
|
||||
file entries, an INI path, and a program path. The SDK writes those text files
|
||||
into the Emscripten filesystem, applies executable bits for user M-code files,
|
||||
then forwards to `runFileWithIni()` by default or to `runFiveAxisRemapFile()`
|
||||
when `executionMode: "fiveAxisRemap"` is explicitly requested.
|
||||
|
||||
`runFileWithIniContinueOnError()` uses the same LinuxCNC-backed file execution
|
||||
path but keeps the runner loop going after LinuxCNC reports an error, matching
|
||||
upstream `rs274 -n 0` regression tests such as `tests/interp/oword-unwind`.
|
||||
It does not implement or reinterpret LinuxCNC error semantics.
|
||||
|
||||
@@ -58,6 +58,34 @@ export async function createLinuxCncInterpSdk(moduleOptions = {}) {
|
||||
return mod.FS.readFile(path, { encoding: "utf8" });
|
||||
},
|
||||
|
||||
runSimConfigProgram({
|
||||
iniPath,
|
||||
programPath,
|
||||
files = [],
|
||||
executionMode = "fileWithIni",
|
||||
}) {
|
||||
for (const file of files) {
|
||||
ensureParentPath(mod, file.path);
|
||||
mod.FS.writeFile(file.path, file.text, { encoding: "utf8" });
|
||||
if (file.executable) {
|
||||
mod.FS.chmod(file.path, 0o755);
|
||||
}
|
||||
}
|
||||
|
||||
if (executionMode === "fiveAxisRemap") {
|
||||
return callStringResult(
|
||||
mod,
|
||||
"lcinterp_run_fiveaxis_remap_file",
|
||||
programPath,
|
||||
iniPath,
|
||||
);
|
||||
}
|
||||
if (executionMode === "fileWithIni") {
|
||||
return callStringResult(mod, "lcinterp_run_file_with_ini", programPath, iniPath);
|
||||
}
|
||||
throw new Error(`unsupported sim config execution mode: ${executionMode}`);
|
||||
},
|
||||
|
||||
runProgram(programText) {
|
||||
return callStringResult(mod, "lcinterp_run_program", programText);
|
||||
},
|
||||
@@ -74,10 +102,31 @@ export async function createLinuxCncInterpSdk(moduleOptions = {}) {
|
||||
return callStringResult(mod, "lcinterp_run_file_with_ini", path, iniPath);
|
||||
},
|
||||
|
||||
runFileWithIniContinueOnError(path, iniPath) {
|
||||
return callStringResult(
|
||||
mod,
|
||||
"lcinterp_run_file_with_ini_continue_on_error",
|
||||
path,
|
||||
iniPath,
|
||||
);
|
||||
},
|
||||
|
||||
runFiveAxisRemapFile(path, iniPath) {
|
||||
return callStringResult(mod, "lcinterp_run_fiveaxis_remap_file", path, iniPath);
|
||||
},
|
||||
|
||||
runRemapFile(path, iniPath) {
|
||||
return callStringResult(mod, "lcinterp_run_remap_file", path, iniPath);
|
||||
},
|
||||
|
||||
runRemapFileContinueOnError(path, iniPath) {
|
||||
return callStringResult(mod, "lcinterp_run_remap_file_continue_on_error", path, iniPath);
|
||||
},
|
||||
|
||||
runRemapIoMdiSequence(iniPath) {
|
||||
return callStringResult(mod, "lcinterp_run_remap_io_mdi_sequence", iniPath);
|
||||
},
|
||||
|
||||
restoreParameters(path) {
|
||||
return callStringResult(mod, "lcinterp_restore_parameters", path);
|
||||
},
|
||||
|
||||
@@ -67,6 +67,22 @@ const eventCountNode = document.getElementById("event-count");
|
||||
const wasmBadge = document.getElementById("wasm-badge");
|
||||
const interpBadge = document.getElementById("interp-badge");
|
||||
const opfsBadge = document.getElementById("opfs-badge");
|
||||
const runProgressNode = document.getElementById("run-progress");
|
||||
const runProgressLabelNode = document.getElementById("run-progress-label");
|
||||
const runMotionNode = document.getElementById("run-motion");
|
||||
const runLineNode = document.getElementById("run-line");
|
||||
const runStatementNode = document.getElementById("run-statement");
|
||||
const axisNodes = {
|
||||
x: document.getElementById("axis-x"),
|
||||
y: document.getElementById("axis-y"),
|
||||
z: document.getElementById("axis-z"),
|
||||
a: document.getElementById("axis-a"),
|
||||
b: document.getElementById("axis-b"),
|
||||
c: document.getElementById("axis-c"),
|
||||
u: document.getElementById("axis-u"),
|
||||
v: document.getElementById("axis-v"),
|
||||
w: document.getElementById("axis-w"),
|
||||
};
|
||||
|
||||
const fields = {
|
||||
machine: document.getElementById("field-machine"),
|
||||
@@ -88,6 +104,7 @@ let iniSdk = null;
|
||||
let interpSdk = null;
|
||||
let loadedSession = null;
|
||||
let canonicalEventText = "";
|
||||
let runPlaybackTimer = null;
|
||||
|
||||
function setBadge(node, text, className = "badge") {
|
||||
node.className = className;
|
||||
@@ -119,6 +136,109 @@ function setField(name, value) {
|
||||
fields[name].textContent = value ?? "-";
|
||||
}
|
||||
|
||||
function nextFrame() {
|
||||
return new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
}
|
||||
|
||||
function formatAxisValue(value) {
|
||||
return Number.isFinite(value) ? value.toFixed(3) : "0.000";
|
||||
}
|
||||
|
||||
function clearRunPlayback() {
|
||||
if (runPlaybackTimer) {
|
||||
clearInterval(runPlaybackTimer);
|
||||
runPlaybackTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function setRunMonitor(progress, label, axes = {}, motionText = "idle", lineText = "line -", statement = "-") {
|
||||
runProgressNode.value = Math.max(0, Math.min(100, progress));
|
||||
runProgressLabelNode.textContent = label;
|
||||
runMotionNode.textContent = motionText;
|
||||
runLineNode.textContent = lineText;
|
||||
runStatementNode.textContent = statement;
|
||||
for (const [axis, node] of Object.entries(axisNodes)) {
|
||||
node.textContent = formatAxisValue(axes[axis] ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
function readCanonicalNumber(line, name) {
|
||||
const match = line.match(new RegExp(`(?:^| )${name}=([-+0-9.eE]+)`));
|
||||
return match ? Number(match[1]) : null;
|
||||
}
|
||||
|
||||
function programLineMap(programText) {
|
||||
const lines = new Map();
|
||||
programText.split(/\r?\n/).forEach((line, index) => {
|
||||
lines.set(index + 1, line.trim() || "(blank)");
|
||||
});
|
||||
return lines;
|
||||
}
|
||||
|
||||
function parseRunMotion(resultText, programText) {
|
||||
const axes = { x: 0, y: 0, z: 0, a: 0, b: 0, c: 0, u: 0, v: 0, w: 0 };
|
||||
const snapshots = [];
|
||||
const sourceLines = programLineMap(programText);
|
||||
|
||||
for (const line of resultText.split("\n")) {
|
||||
const motion = line.match(/^canon_event=(STRAIGHT_TRAVERSE|STRAIGHT_FEED|ARC_FEED)\b/);
|
||||
if (!motion) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const axis of Object.keys(axes)) {
|
||||
const value = readCanonicalNumber(line, axis);
|
||||
if (value !== null && Number.isFinite(value)) {
|
||||
axes[axis] = value;
|
||||
}
|
||||
}
|
||||
|
||||
const sourceLine = readCanonicalNumber(line, "line");
|
||||
snapshots.push({
|
||||
type: motion[1],
|
||||
line: sourceLine,
|
||||
statement: Number.isFinite(sourceLine) ? (sourceLines.get(sourceLine) ?? "-") : "-",
|
||||
axes: { ...axes },
|
||||
});
|
||||
}
|
||||
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
function showRunSnapshot(snapshot, index, total) {
|
||||
const progress = total > 0 ? Math.round(((index + 1) / total) * 100) : 0;
|
||||
const lineText = Number.isFinite(snapshot.line) ? `line ${snapshot.line}` : "line -";
|
||||
setRunMonitor(
|
||||
progress,
|
||||
`${progress}%`,
|
||||
snapshot.axes,
|
||||
`${snapshot.type} ${lineText} (${index + 1}/${total})`,
|
||||
lineText,
|
||||
snapshot.statement,
|
||||
);
|
||||
}
|
||||
|
||||
function playRunMotion(resultText, programText) {
|
||||
clearRunPlayback();
|
||||
const snapshots = parseRunMotion(resultText, programText);
|
||||
if (snapshots.length === 0) {
|
||||
setRunMonitor(100, "100%", {}, "complete; no axis motion");
|
||||
return;
|
||||
}
|
||||
|
||||
let index = 0;
|
||||
showRunSnapshot(snapshots[index], index, snapshots.length);
|
||||
runPlaybackTimer = setInterval(() => {
|
||||
index += 1;
|
||||
if (index >= snapshots.length) {
|
||||
clearRunPlayback();
|
||||
showRunSnapshot(snapshots[snapshots.length - 1], snapshots.length - 1, snapshots.length);
|
||||
return;
|
||||
}
|
||||
showRunSnapshot(snapshots[index], index, snapshots.length);
|
||||
}, 220);
|
||||
}
|
||||
|
||||
function requireIniSdk() {
|
||||
if (!iniSdk) {
|
||||
throw new Error("INI WASM module is not ready yet.");
|
||||
@@ -287,10 +407,15 @@ document.getElementById("run-gcode").addEventListener("click", async () => {
|
||||
const interp = requireInterpSdk();
|
||||
const programText = await loadGcodeProgram(GCODE_FILENAME);
|
||||
interp.writeTextFile(GCODE_WASM_FILE, programText);
|
||||
clearRunPlayback();
|
||||
setField("runStatus", "running");
|
||||
setRunMonitor(5, "running", {}, "running");
|
||||
await nextFrame();
|
||||
const result = interp.runFileWithIni(GCODE_WASM_FILE, loadedSession.ini.wasmPath);
|
||||
setField("sessionGcode", GCODE_WASM_FILE);
|
||||
setField("runStatus", "ok");
|
||||
setCanonicalEvents(result.trim());
|
||||
playRunMotion(result.trim(), programText);
|
||||
setLog(
|
||||
[
|
||||
"Ran G-code through LinuxCNC interpreter WASM.",
|
||||
@@ -302,6 +427,8 @@ document.getElementById("run-gcode").addEventListener("click", async () => {
|
||||
} catch (error) {
|
||||
setField("runStatus", "failed");
|
||||
setCanonicalEvents("");
|
||||
clearRunPlayback();
|
||||
setRunMonitor(0, "failed", {}, "failed");
|
||||
setLog(`G-code run failed: ${error.message}`, true);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -123,6 +123,53 @@
|
||||
font: 13px/1.5 "SFMono-Regular", "Consolas", monospace;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.run-monitor {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
background: #fbfdff;
|
||||
padding: 12px;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.progress-row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
progress {
|
||||
width: 100%;
|
||||
height: 14px;
|
||||
accent-color: var(--accent-2);
|
||||
}
|
||||
.run-readout {
|
||||
font: 13px/1.4 "SFMono-Regular", "Consolas", monospace;
|
||||
color: var(--muted);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.axis-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 8px;
|
||||
}
|
||||
.axis-cell {
|
||||
border: 1px solid #edf2f6;
|
||||
border-radius: 6px;
|
||||
padding: 8px;
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
}
|
||||
.axis-cell span:first-child {
|
||||
color: var(--muted);
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
.axis-cell span:last-child {
|
||||
font: 14px/1.2 "SFMono-Regular", "Consolas", monospace;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.events {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
@@ -154,6 +201,11 @@
|
||||
.grid { grid-template-columns: 1fr; }
|
||||
textarea { min-height: 320px; }
|
||||
}
|
||||
@media (max-width: 560px) {
|
||||
.axis-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.progress-row { grid-template-columns: 1fr; }
|
||||
.run-readout { white-space: normal; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -226,6 +278,28 @@
|
||||
<dd id="field-fiveaxis-remap">-</dd>
|
||||
</dl>
|
||||
|
||||
<h2>Run Monitor</h2>
|
||||
<div class="run-monitor">
|
||||
<div class="progress-row">
|
||||
<progress id="run-progress" max="100" value="0"></progress>
|
||||
<span id="run-progress-label" class="run-readout">0%</span>
|
||||
</div>
|
||||
<div id="run-motion" class="run-readout">idle</div>
|
||||
<div id="run-line" class="run-readout">line -</div>
|
||||
<div id="run-statement" class="run-readout">-</div>
|
||||
<div class="axis-grid" id="axis-grid">
|
||||
<div class="axis-cell"><span>X</span><span id="axis-x">0.000</span></div>
|
||||
<div class="axis-cell"><span>Y</span><span id="axis-y">0.000</span></div>
|
||||
<div class="axis-cell"><span>Z</span><span id="axis-z">0.000</span></div>
|
||||
<div class="axis-cell"><span>A</span><span id="axis-a">0.000</span></div>
|
||||
<div class="axis-cell"><span>B</span><span id="axis-b">0.000</span></div>
|
||||
<div class="axis-cell"><span>C</span><span id="axis-c">0.000</span></div>
|
||||
<div class="axis-cell"><span>U</span><span id="axis-u">0.000</span></div>
|
||||
<div class="axis-cell"><span>V</span><span id="axis-v">0.000</span></div>
|
||||
<div class="axis-cell"><span>W</span><span id="axis-w">0.000</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="log" id="log"></div>
|
||||
|
||||
<h2>Canonical Events</h2>
|
||||
|
||||
@@ -344,6 +344,24 @@ TOOL_TABLE = browser-tool.tbl
|
||||
) {
|
||||
throw new Error(`UI canonical event panel missing LinuxCNC events: ${eventText}`);
|
||||
}
|
||||
await waitFor(
|
||||
() => uiDocument.getElementById("run-motion")?.textContent.includes("STRAIGHT_FEED"),
|
||||
"G-code run motion playback",
|
||||
);
|
||||
assertEqual(
|
||||
uiDocument.getElementById("run-progress-label").textContent,
|
||||
"100%",
|
||||
"UI G-code run progress",
|
||||
);
|
||||
assertEqual(uiDocument.getElementById("axis-x").textContent, "3.000", "UI G-code X axis");
|
||||
assertEqual(uiDocument.getElementById("axis-y").textContent, "4.000", "UI G-code Y axis");
|
||||
assertEqual(uiDocument.getElementById("axis-z").textContent, "0.000", "UI G-code Z axis");
|
||||
assertEqual(uiDocument.getElementById("run-line").textContent, "line 2", "UI G-code line");
|
||||
assertEqual(
|
||||
uiDocument.getElementById("run-statement").textContent,
|
||||
"G1 X3.0 Y4.0 F120.0",
|
||||
"UI G-code statement",
|
||||
);
|
||||
const eventFilter = uiDocument.getElementById("event-filter");
|
||||
eventFilter.value = "STRAIGHT_FEED";
|
||||
eventFilter.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
2
wasm-port/tests/fixtures/canon/ini_tool_table.events
vendored
Normal file
2
wasm-port/tests/fixtures/canon/ini_tool_table.events
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
canon_event=USE_TOOL_LENGTH_OFFSET x=0 y=0 z=6.25 a=0 b=0 c=0 u=0 v=0 w=0
|
||||
canon_event=PROGRAM_END
|
||||
4
wasm-port/tests/fixtures/canon/spindle_orient_offset.events
vendored
Normal file
4
wasm-port/tests/fixtures/canon/spindle_orient_offset.events
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
canon_event=SELECT_PLANE plane=1
|
||||
canon_event=STRAIGHT_TRAVERSE line=1 x=0 y=0 z=0 a=0 b=0 c=0 u=0 v=0 w=0
|
||||
canon_event=ORIENT_SPINDLE spindle=0 orientation=57.5 mode=2
|
||||
canon_event=WAIT_SPINDLE_ORIENT_COMPLETE spindle=0 timeout=1.5
|
||||
4
wasm-port/tests/fixtures/gcode/disable_fanuc_style_sub_m98.ngc
vendored
Normal file
4
wasm-port/tests/fixtures/gcode/disable_fanuc_style_sub_m98.ngc
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
M98 P1
|
||||
O1
|
||||
M99
|
||||
M2
|
||||
2
wasm-port/tests/fixtures/gcode/ini_tool_table.ngc
vendored
Normal file
2
wasm-port/tests/fixtures/gcode/ini_tool_table.ngc
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
G43 H2
|
||||
M2
|
||||
2
wasm-port/tests/fixtures/gcode/spindle_orient_offset.ngc
vendored
Normal file
2
wasm-port/tests/fixtures/gcode/spindle_orient_offset.ngc
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
G90 G17 G0 X0 Y0 Z0
|
||||
M19 R45 P2 Q1.5
|
||||
5
wasm-port/tests/fixtures/ini/disable_fanuc_style_sub.ini
vendored
Normal file
5
wasm-port/tests/fixtures/ini/disable_fanuc_style_sub.ini
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
[RS274NGC]
|
||||
DISABLE_FANUC_STYLE_SUB = 1
|
||||
|
||||
[TRAJ]
|
||||
COORDINATES = XYZ
|
||||
6
wasm-port/tests/fixtures/ini/ini_tool_table.ini
vendored
Normal file
6
wasm-port/tests/fixtures/ini/ini_tool_table.ini
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
[TRAJ]
|
||||
LINEAR_UNITS = mm
|
||||
|
||||
[EMCIO]
|
||||
TOOL_TABLE = ini_tool_table.tbl
|
||||
RANDOM_TOOLCHANGER = 0
|
||||
1
wasm-port/tests/fixtures/ini/ini_tool_table.tbl
vendored
Normal file
1
wasm-port/tests/fixtures/ini/ini_tool_table.tbl
vendored
Normal file
@@ -0,0 +1 @@
|
||||
T2 P7 Z6.25 D1.5 ;ini-driven tool table entry
|
||||
5
wasm-port/tests/fixtures/ini/spindle_orient_offset.ini
vendored
Normal file
5
wasm-port/tests/fixtures/ini/spindle_orient_offset.ini
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
[TRAJ]
|
||||
COORDINATES = XYZ
|
||||
|
||||
[RS274NGC]
|
||||
ORIENT_OFFSET = 12.5
|
||||
@@ -71,5 +71,6 @@ export const INTERP_BROWSER_FILE_FIXTURES = INTERP_FILE_FIXTURES;
|
||||
|
||||
export const INTERP_INI_FIXTURE = "namedparam_semantics";
|
||||
export const INTERP_BASELINE_INI_FIXTURE = "namedparam_ini_semantics";
|
||||
export const INTERP_SPINDLE_ORIENT_OFFSET_FIXTURE = "spindle_orient_offset";
|
||||
export const INTERP_COORDINATE_OFFSETS_FILE_FIXTURE = "coordinate_offsets";
|
||||
export const INTERP_POSITION_PARAMS_FILE_FIXTURE = "position_params";
|
||||
|
||||
@@ -8,6 +8,8 @@ ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
"$ROOT_DIR/tools/build_tp_wasm.sh"
|
||||
SKIP_INI_BUILD=1 "$ROOT_DIR/tests/wasm/node/verify_ini_wasm.sh"
|
||||
SKIP_INTERP_BUILD=1 "$ROOT_DIR/tests/wasm/node/verify_interp_wasm.sh"
|
||||
SKIP_INTERP_BUILD=1 "$ROOT_DIR/tests/wasm/node/verify_sim_configs_wasm.sh"
|
||||
SKIP_INTERP_BUILD=1 "$ROOT_DIR/tests/wasm/node/verify_nc_files_wasm.sh"
|
||||
SKIP_TP_BUILD=1 "$ROOT_DIR/tests/wasm/node/verify_tp_wasm.sh"
|
||||
"$ROOT_DIR/tests/opfs/node/verify_file_service.sh"
|
||||
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 "$ROOT_DIR/tests/browser/verify_ini_panel_browser.sh"
|
||||
|
||||
@@ -8,12 +8,59 @@ CANON_FIXTURE_DIR="$ROOT_DIR/tests/fixtures/canon"
|
||||
GCODE_ERROR_FIXTURE_DIR="$ROOT_DIR/tests/fixtures/gcode_errors"
|
||||
CANON_ERROR_FIXTURE_DIR="$ROOT_DIR/tests/fixtures/canon_errors"
|
||||
NAMEDPARAM_INI_FIXTURE="$ROOT_DIR/tests/fixtures/ini/namedparams.ini"
|
||||
SPINDLE_ORIENT_OFFSET_INI_FIXTURE="$ROOT_DIR/tests/fixtures/ini/spindle_orient_offset.ini"
|
||||
DISABLE_FANUC_STYLE_SUB_INI_FIXTURE="$ROOT_DIR/tests/fixtures/ini/disable_fanuc_style_sub.ini"
|
||||
VALIDATION_CACHE_KEY_FILE="$BUILD_DIR/native-probe-validation.input.sha256"
|
||||
VALIDATION_CACHE_OK_FILE="$BUILD_DIR/native-probe-validation.ok"
|
||||
|
||||
"$ROOT_DIR/tools/verify_upstream_baseline.sh"
|
||||
"$ROOT_DIR/tools/verify_vendor_sync.sh"
|
||||
"$ROOT_DIR/tools/verify_no_standalone_cnc_semantics.sh"
|
||||
"$ROOT_DIR/tools/verify_native_linuxcnc_fixture_baseline.sh"
|
||||
"$ROOT_DIR/tools/build_native_probes.sh"
|
||||
"$ROOT_DIR/tests/native/verify_sim_configs.sh"
|
||||
"$ROOT_DIR/tests/native/verify_nc_files.sh"
|
||||
|
||||
hash_tree() {
|
||||
find "$@" -type f -print0 | sort -z | xargs -0 -r sha256sum
|
||||
}
|
||||
|
||||
hash_build_validation_inputs() {
|
||||
find "$BUILD_DIR" -maxdepth 1 -type f \
|
||||
\( \
|
||||
-name '*.exitcode' \
|
||||
-o -name '*.run.stdout.log' \
|
||||
-o -name '*.run.stderr.log' \
|
||||
-o -name 'source-probes.tsv' \
|
||||
-o -name 'native-probes.ok' \
|
||||
-o -name 'linuxcnc_interp_minimal_harness' \
|
||||
\) \
|
||||
! -name 'native-probe-validation.*' \
|
||||
-print0 | sort -z | xargs -0 -r sha256sum
|
||||
}
|
||||
|
||||
native_probe_validation_fingerprint() {
|
||||
{
|
||||
sha256sum \
|
||||
"$ROOT_DIR/tests/native/verify_native_probes.sh" \
|
||||
"$ROOT_DIR/tools/source-manifest.txt"
|
||||
hash_tree \
|
||||
"$GCODE_FIXTURE_DIR" \
|
||||
"$CANON_FIXTURE_DIR" \
|
||||
"$GCODE_ERROR_FIXTURE_DIR" \
|
||||
"$CANON_ERROR_FIXTURE_DIR" \
|
||||
"$ROOT_DIR/tests/fixtures/ini"
|
||||
hash_build_validation_inputs
|
||||
} | sha256sum | awk '{ print $1 }'
|
||||
}
|
||||
|
||||
NATIVE_PROBE_VALIDATION_FINGERPRINT="$(native_probe_validation_fingerprint)"
|
||||
if [[ -f "$VALIDATION_CACHE_KEY_FILE" && -f "$VALIDATION_CACHE_OK_FILE" ]] &&
|
||||
[[ "$(tr -d '[:space:]' < "$VALIDATION_CACHE_KEY_FILE")" == "$NATIVE_PROBE_VALIDATION_FINGERPRINT" ]] &&
|
||||
[[ "$(tr -d '[:space:]' < "$VALIDATION_CACHE_OK_FILE")" == "$NATIVE_PROBE_VALIDATION_FINGERPRINT" ]]; then
|
||||
echo "native probe validation up to date"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
check_source_probe_coverage() {
|
||||
local manifest_sources="$BUILD_DIR/source-manifest-sources.sorted"
|
||||
@@ -155,6 +202,40 @@ check_exitcode linuxcnc_namedparam_harness
|
||||
check_exitcode linuxcnc_namedparam_harness.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness
|
||||
check_exitcode linuxcnc_interp_minimal_harness.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.do_while_break.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.oword_bug315.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.oword_bug315_p2.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.interp_exists.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.return_value.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.subs_follow_main.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.fractional_linenumbers.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.namedparam_bug424.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.g6164.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.rotation_abs_pts.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.rotation_g28.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.rotation_g53.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.iniparam.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.iniparam_failassign.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.sub_call_from_sub.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.sequence_number.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.nested_sub_error.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.nested_sub_in_file_error.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.oword_unwind.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.abort_hot_comment.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.m19.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.magic_comments_param_format.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.m98m99_01_basics.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.m98m99_02_variables.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.m98m99_07_nested_subs.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.m98m99_08_sub_follows_main.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.m98m99_10_m98_p001.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.m98m99_13_named_program_named.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.m98m99_13_named_program_numbered.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.m98m99_14_o_expression_call.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.sim_axis_foam.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.sim_bridgemill.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.sim_geometry_xyzc.run
|
||||
check_exitcode linuxcnc_interp_minimal_harness.sim_external_offsets_dyn.run
|
||||
check_exitcode linuxcnc_parameter_file_harness
|
||||
check_exitcode linuxcnc_parameter_file_harness.run
|
||||
check_exitcode linuxcnc_interp_init_harness
|
||||
@@ -165,6 +246,8 @@ check_exitcode linuxcnc_remap_hal_sync_harness
|
||||
check_exitcode linuxcnc_remap_hal_sync_harness.run
|
||||
check_exitcode linuxcnc_5axis_remap_execute_harness
|
||||
check_exitcode linuxcnc_5axis_remap_execute_harness.run
|
||||
check_exitcode linuxcnc_duplicate_oword_remap_harness
|
||||
check_exitcode linuxcnc_duplicate_oword_remap_harness.run
|
||||
check_exitcode linuxcnc_indexer_harness
|
||||
check_exitcode linuxcnc_indexer_harness.run
|
||||
check_exitcode linuxcnc_rs274_compile_probe
|
||||
@@ -214,6 +297,29 @@ check_exitcode linuxcnc_interp_base_source_probe
|
||||
check_exitcode linuxcnc_gomath_source_probe
|
||||
check_exitcode linuxcnc_tooldata_common_source_probe
|
||||
|
||||
INIPARAM_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.iniparam.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$INIPARAM_STDOUT"
|
||||
grep -Fq "file_read_count=9" "$INIPARAM_STDOUT"
|
||||
grep -Fq "file_execute_count=8" "$INIPARAM_STDOUT"
|
||||
grep -Fq "file_saw_error=1" "$INIPARAM_STDOUT"
|
||||
grep -Fq "file_error_text=Named parameter #<_ini[nosuchsection]nosuchname> not defined" "$INIPARAM_STDOUT"
|
||||
grep -Fq "setup.current_x=10" "$INIPARAM_STDOUT"
|
||||
grep -Fq "setup.current_y=20" "$INIPARAM_STDOUT"
|
||||
grep -Fq "setup.current_z=30" "$INIPARAM_STDOUT"
|
||||
grep -Fq "canon_event=STRAIGHT_TRAVERSE line=1 x=10 y=20 z=30" "$INIPARAM_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: position now: 10.000000 20.000000 30.000000" "$INIPARAM_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: not in INI: ######" "$INIPARAM_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$INIPARAM_STDOUT"
|
||||
|
||||
INIPARAM_FAILASSIGN_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.iniparam_failassign.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$INIPARAM_FAILASSIGN_STDOUT"
|
||||
grep -Fq "file_saw_error=1" "$INIPARAM_FAILASSIGN_STDOUT"
|
||||
grep -Fq "file_error_text=Cannot assign to read-only parameter #<_ini[vars]toolchange_x>" "$INIPARAM_FAILASSIGN_STDOUT"
|
||||
if grep -Fq "canon_event=MESSAGE: notreached" "$INIPARAM_FAILASSIGN_STDOUT"; then
|
||||
echo "iniparam-failassign unexpectedly reached post-assignment message" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
EMC_STATUS_STDOUT="$BUILD_DIR/linuxcnc_emc_status_probe.run.stdout.log"
|
||||
grep -Fq "emc_status_default_linear_units=1" "$EMC_STATUS_STDOUT"
|
||||
grep -Fq "emc_status_default_units_visible=1" "$EMC_STATUS_STDOUT"
|
||||
@@ -248,39 +354,56 @@ grep -Fq "xyzbc_trt_switch_mcodes_from_linuxcnc=1" "$FIVEAXIS_REMAP_ASSET_STDOUT
|
||||
grep -Fq "fiveaxis_remap_assets_from_linuxcnc=1" "$FIVEAXIS_REMAP_ASSET_STDOUT"
|
||||
|
||||
REMAP_PARSE_STDOUT="$BUILD_DIR/linuxcnc_remap_parse_harness.run.stdout.log"
|
||||
|
||||
check_remap_descriptor() {
|
||||
local machine="$1"
|
||||
local mcode="$2"
|
||||
|
||||
grep -Fq "${machine}_${mcode}_name_lookup=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "${machine}_${mcode}_mcode_lookup=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "${machine}_${mcode}_ngc=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "${machine}_${mcode}_modalgroup10=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "${machine}_${mcode}_no_python=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "${machine}_${mcode}_linuxcnc_mcode_remappable=1" "$REMAP_PARSE_STDOUT"
|
||||
}
|
||||
|
||||
grep -Fq "xyzac_trt_ini_open=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzac_trt_parse_remap_1=0" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzac_trt_parse_remap_2=0" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzac_trt_parse_remap_3=0" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzac_trt_parsed_remap_count=3" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzac_trt_M428_ngc=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzac_trt_M429_ngc=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzac_trt_M430_ngc=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzac_trt_m_remapped_count=3" "$REMAP_PARSE_STDOUT"
|
||||
check_remap_descriptor "xyzac_trt" "M428"
|
||||
check_remap_descriptor "xyzac_trt" "M429"
|
||||
check_remap_descriptor "xyzac_trt" "M430"
|
||||
grep -Fq "xyzac_trt_linuxcnc_ngc_remaps_parsed=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzbc_trt_ini_open=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzbc_trt_parse_remap_1=0" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzbc_trt_parse_remap_2=0" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzbc_trt_parse_remap_3=0" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzbc_trt_parsed_remap_count=3" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzbc_trt_M428_ngc=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzbc_trt_M429_ngc=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzbc_trt_M430_ngc=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzbc_trt_m_remapped_count=3" "$REMAP_PARSE_STDOUT"
|
||||
check_remap_descriptor "xyzbc_trt" "M428"
|
||||
check_remap_descriptor "xyzbc_trt" "M429"
|
||||
check_remap_descriptor "xyzbc_trt" "M430"
|
||||
grep -Fq "xyzbc_trt_linuxcnc_ngc_remaps_parsed=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzab_tdr_ini_open=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzab_tdr_parse_remap_1=0" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzab_tdr_parse_remap_2=0" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzab_tdr_parsed_remap_count=2" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzab_tdr_M428_ngc=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzab_tdr_M429_ngc=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzab_tdr_m_remapped_count=2" "$REMAP_PARSE_STDOUT"
|
||||
check_remap_descriptor "xyzab_tdr" "M428"
|
||||
check_remap_descriptor "xyzab_tdr" "M429"
|
||||
grep -Fq "xyzab_tdr_linuxcnc_ngc_remaps_parsed=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "bridgemill_ini_open=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "bridgemill_parse_remap_1=0" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "bridgemill_parse_remap_2=0" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "bridgemill_parse_remap_3=0" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "bridgemill_parsed_remap_count=3" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "bridgemill_M428_ngc=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "bridgemill_M429_ngc=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "bridgemill_M430_ngc=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "bridgemill_m_remapped_count=3" "$REMAP_PARSE_STDOUT"
|
||||
check_remap_descriptor "bridgemill" "M428"
|
||||
check_remap_descriptor "bridgemill" "M429"
|
||||
check_remap_descriptor "bridgemill" "M430"
|
||||
grep -Fq "bridgemill_linuxcnc_ngc_remaps_parsed=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "fiveaxis_linuxcnc_remap_parse_path=1" "$REMAP_PARSE_STDOUT"
|
||||
|
||||
@@ -363,6 +486,14 @@ grep -Fq "xyzac_trt_xyzac_switchkins_test_1_file_final_rc=1" "$FIVEAXIS_REMAP_EX
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_1_file_reached_exit=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_1__hal[motion.switchkins-type]: rc=0 found=1 value=0" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_1_linuxcnc_demo_file_execute=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_2_file_open=0" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_2_file_read_count=120" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_2_file_execute_count=120" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_2_file_finish_count=3" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_2_file_final_rc=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_2_file_reached_exit=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_2__hal[motion.switchkins-type]: rc=0 found=1 value=0" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_2_linuxcnc_demo_file_execute=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_3_file_open=0" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_3_file_read_count=86" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "xyzac_trt_xyzac_switchkins_test_3_file_execute_count=86" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
@@ -413,6 +544,164 @@ grep -Fq "bridgemill_bridgemill_5axisgui__hal[motion.switchkins-type]: rc=0 foun
|
||||
grep -Fq "bridgemill_bridgemill_5axisgui_linuxcnc_demo_file_execute=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
grep -Fq "fiveaxis_linuxcnc_remap_execute_path=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT"
|
||||
|
||||
DUPLICATE_OWORD_REMAP_STDOUT="$BUILD_DIR/linuxcnc_duplicate_oword_remap_harness.run.stdout.log"
|
||||
grep -Fq "duplicate_oword_ini_open=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_subroutine_path_count=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_parse_remap_1=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_parse_remap_2=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_parsed_remap_count=2" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_remaps_ready=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_file_open=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_file_read_count=31" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_file_execute_count=31" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_file_finish_count=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_file_final_rc=3" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_file_reached_endfile=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_canon_event=MESSAGE: executing m207: run remapped m208 before o<problem>" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_canon_event=MESSAGE: rm207 running remapped m208" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_canon_event=MESSAGE: rm208 starting and done" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_canon_event=FINISH" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_linuxcnc_remap_file_execute=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "duplicate_oword_linuxcnc_regression_path=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_0_ini_open=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_0_parse_remap_1=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_0_parsed_remap_count=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_0_file_open=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_0_file_saw_error=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_0_canon_event=MESSAGE: M400 call_level= 1.000000 remap_level=1.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_0_canon_event=MESSAGE: P word set: 47.110000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_0_canon_event=MESSAGE: Q word set: 8.150000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_0_canon_event=PROGRAM_END" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_0_linuxcnc_remap_file_execute=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_1_ini_open=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_1_parse_remap_1=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_1_file_execute_1=5" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_1_file_error_text=user-defined M400: missing: Q" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_1_file_saw_error=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_1_canon_event=PROGRAM_END" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_1_linuxcnc_remap_file_execute=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_2_ini_open=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_2_parse_remap_1=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_2_file_execute_1=5" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_2_file_error_text=user-defined M400: missing: P,Q" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_2_file_saw_error=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_2_canon_event=PROGRAM_END" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_args_2_linuxcnc_remap_file_execute=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_body_ngc_ini_open=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_body_ngc_parse_remap_1=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_body_ngc_file_read_5=5" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_body_ngc_file_error_text=Attempt to divide by zero" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_body_ngc_file_saw_error=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_body_ngc_canon_event=MESSAGE: before M400: call_level= 0.000000 remap_level=0.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_body_ngc_canon_event=MESSAGE: in rm400: call_level= 1.000000 remap_level=1.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_body_ngc_canon_event=MESSAGE: after failed M400: call_level= 0.000000 remap_level=0.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_body_ngc_canon_event=PROGRAM_END" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "fail_body_ngc_linuxcnc_remap_file_execute=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_ini_open=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_subroutine_path_count=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_parse_remap_1=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_parsed_remap_count=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_remaps_ready=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_file_open=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_file_read_count=4" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_file_execute_count=4" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_file_finish_count=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_file_final_rc=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_file_reached_exit=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_canon_event=MESSAGE: m400 call_level=1.000000 remap_level=1.000000 line=2.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_canon_event=PROGRAM_END" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_linuxcnc_remap_file_execute=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "m30_interaction_linuxcnc_regression_path=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_ini_open=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_subroutine_path_count=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_parse_remap_1=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_parse_remap_2=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_parse_remap_3=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_parse_remap_4=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_parsed_remap_count=4" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_remaps_ready=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_file_open=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_file_read_count=21" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_file_execute_count=21" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_file_finish_count=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_file_final_rc=3" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_file_reached_endfile=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_canon_event=MESSAGE: main call_level=0.000000 remap_level=0.000000 line=2.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_canon_event=MESSAGE: m400 handler pre call_level=1.000000 remap_level=1.000000 line=2.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_canon_event=MESSAGE: m401 handler pre call_level=2.000000 remap_level=2.000000 line=2.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_canon_event=MESSAGE: m402 handler pre call_level=3.000000 remap_level=3.000000 line=2.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_canon_event=MESSAGE: m403 handler pre call_level=4.000000 remap_level=4.000000 line=2.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_canon_event=MESSAGE: m400 handler post call_level=1.000000 remap_level=1.000000 line=4.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_canon_event=FINISH" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_linuxcnc_remap_file_execute=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "nested_remaps_oword_linuxcnc_regression_path=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_ini_open=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_subroutine_path_count=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_parse_remap_1=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_parsed_remap_count=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_remaps_ready=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_file_open=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_file_read_count=19" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_file_execute_count=19" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_file_finish_count=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_file_final_rc=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_file_reached_exit=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_canon_event=MESSAGE: in rg881: n_args=3.000000 [1.000000] [2.000000] [3.000000] [0.000000] [0.000000]" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_canon_event=MESSAGE: in rg881: n_args=4.000000 [1.000000] [2.000000] [3.000000] [4.000000] [0.000000]" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_canon_event=MESSAGE: in rg881: n_args=4.000000 [1.000000] [2.000000] [3.000000] [5.000000] [0.000000]" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_canon_event=MESSAGE: in rg881: n_args=5.000000 [1.000000] [2.000000] [3.000000] [4.000000] [5.000000]" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_canon_event=PROGRAM_END" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_linuxcnc_remap_file_execute=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "posargs_0_linuxcnc_regression_path=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_ini_open=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_subroutine_path_count=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_parse_remap_1=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_parse_remap_2=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_parse_remap_3=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_parse_remap_4=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_parse_remap_5=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_parse_remap_6=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_parse_remap_7=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_parsed_remap_count=7" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_remaps_ready=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_file_open=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_file_read_count=10084" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_file_execute_count=10084" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_file_final_rc=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_file_reached_exit=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_canon_event=MESSAGE: seq=1.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_canon_event=MESSAGE: seq=5.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_canon_event=MESSAGE: seq=6.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_canon_event=MESSAGE: seq=7.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_canon_event=MESSAGE: seq=8.000000 - reset to 1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_canon_event=MESSAGE: seq=8.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_canon_event=MESSAGE: seq=9.000000" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_canon_event=MESSAGE: seq=10.000000 - reset to 1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_canon_event=PROGRAM_END" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_linuxcnc_remap_file_execute=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "sequencing_linuxcnc_regression_path=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_ini_open=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_subroutine_path_count=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_parse_remap_1=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_parse_remap_7=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_parsed_remap_count=7" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_mdi_M66 P1_execute_0=2" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_mdi_M66 P1_execute_1=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_mdi_M66 E1 L0_execute_0=2" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_mdi_M66 E1 L0_execute_1=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_parameter_5399=42.13" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_parameter_5399=-13.42" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_canon_event=SET_MOTION_OUTPUT_BIT index=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_canon_event=CLEAR_MOTION_OUTPUT_BIT index=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_canon_event=SET_AUX_OUTPUT_BIT index=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_canon_event=CLEAR_AUX_OUTPUT_BIT index=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_canon_event=WAIT index=0 input_type=1 wait_type=0 timeout=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_canon_event=WAIT index=0 input_type=0 wait_type=0 timeout=0" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_canon_event=SET_MOTION_OUTPUT_VALUE index=0 value=42.13" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_canon_event=SET_AUX_OUTPUT_VALUE index=0 value=-13.42" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "remap_io_ngc_linuxcnc_mdi_sequence=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
grep -Fq "linuxcnc_upstream_remap_regression_path=1" "$DUPLICATE_OWORD_REMAP_STDOUT"
|
||||
|
||||
NAMEDPARAM_STDOUT="$BUILD_DIR/linuxcnc_namedparam_harness.run.stdout.log"
|
||||
grep -Fq "init_named_parameters=0" "$NAMEDPARAM_STDOUT"
|
||||
grep -Fq "global_named_count=57" "$NAMEDPARAM_STDOUT"
|
||||
@@ -720,8 +1009,362 @@ check_fixture_output \
|
||||
"$CANON_FIXTURE_DIR/minimal_linear.events" \
|
||||
"$RUN_STDOUT"
|
||||
|
||||
DO_WHILE_BREAK_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.do_while_break.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$DO_WHILE_BREAK_STDOUT"
|
||||
grep -Fq "file_read_count=30" "$DO_WHILE_BREAK_STDOUT"
|
||||
grep -Fq "file_execute_count=30" "$DO_WHILE_BREAK_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: must-execute-outer" "$DO_WHILE_BREAK_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: must-execute-nested" "$DO_WHILE_BREAK_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: must-execute-inner" "$DO_WHILE_BREAK_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: post-inner-while" "$DO_WHILE_BREAK_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: post-nested-while" "$DO_WHILE_BREAK_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: post-outer-while" "$DO_WHILE_BREAK_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$DO_WHILE_BREAK_STDOUT"
|
||||
if grep -Fq "canon_event=MESSAGE: do-not-execute" "$DO_WHILE_BREAK_STDOUT"; then
|
||||
echo "unexpected do-while-break skipped branch event" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
OWORD_BUG315_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.oword_bug315.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$OWORD_BUG315_STDOUT"
|
||||
grep -Fq "file_read_count=23" "$OWORD_BUG315_STDOUT"
|
||||
grep -Fq "file_execute_count=23" "$OWORD_BUG315_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: running sub" "$OWORD_BUG315_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: breaking out of sub" "$OWORD_BUG315_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: done" "$OWORD_BUG315_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$OWORD_BUG315_STDOUT"
|
||||
|
||||
OWORD_BUG315_P2_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.oword_bug315_p2.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$OWORD_BUG315_P2_STDOUT"
|
||||
grep -Fq "file_read_count=26" "$OWORD_BUG315_P2_STDOUT"
|
||||
grep -Fq "file_execute_count=26" "$OWORD_BUG315_P2_STDOUT"
|
||||
grep -Fq "canon_event=STRAIGHT_TRAVERSE line=7 x=2 y=2 z=2" "$OWORD_BUG315_P2_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: executing this one" "$OWORD_BUG315_P2_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$OWORD_BUG315_P2_STDOUT"
|
||||
if grep -Fq "canon_event=MESSAGE: not executing this one" "$OWORD_BUG315_P2_STDOUT"; then
|
||||
echo "unexpected oword-bug315-p2 skipped subroutine event" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
INTERP_EXISTS_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.interp_exists.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$INTERP_EXISTS_STDOUT"
|
||||
grep -Fq "file_read_count=7" "$INTERP_EXISTS_STDOUT"
|
||||
grep -Fq "file_execute_count=7" "$INTERP_EXISTS_STDOUT"
|
||||
grep -Fq "canon_event=STRAIGHT_TRAVERSE line=2 x=1 y=0 z=1" "$INTERP_EXISTS_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: comment" "$INTERP_EXISTS_STDOUT"
|
||||
grep -Fq "canon_event=STRAIGHT_TRAVERSE line=6 x=1 y=0 z=0" "$INTERP_EXISTS_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$INTERP_EXISTS_STDOUT"
|
||||
|
||||
SIM_AXIS_FOAM_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.sim_axis_foam.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$SIM_AXIS_FOAM_STDOUT"
|
||||
grep -Fq "file_read_count=23" "$SIM_AXIS_FOAM_STDOUT"
|
||||
if grep -Fq "Bad character 'u' used" "$SIM_AXIS_FOAM_STDOUT"; then
|
||||
echo "axis_foam INI did not enable U/V axis readers" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SIM_BRIDGEMILL_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.sim_bridgemill.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$SIM_BRIDGEMILL_STDOUT"
|
||||
if grep -Fq "Bad character 'w' used" "$SIM_BRIDGEMILL_STDOUT"; then
|
||||
echo "bridgemill INI did not enable W axis reader" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SIM_GEOMETRY_XYZC_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.sim_geometry_xyzc.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$SIM_GEOMETRY_XYZC_STDOUT"
|
||||
grep -Fq "canon_event=USER_M_COMMAND code=M110" "$SIM_GEOMETRY_XYZC_STDOUT"
|
||||
if grep -Fq "Unknown m code used: M110" "$SIM_GEOMETRY_XYZC_STDOUT"; then
|
||||
echo "xyzc INI did not register USER_M_PATH M110" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SIM_EXTERNAL_OFFSETS_DYN_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.sim_external_offsets_dyn.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$SIM_EXTERNAL_OFFSETS_DYN_STDOUT"
|
||||
grep -Fq "canon_event=USER_M_COMMAND code=M111" "$SIM_EXTERNAL_OFFSETS_DYN_STDOUT"
|
||||
if grep -Fq "Unknown m code used: M111" "$SIM_EXTERNAL_OFFSETS_DYN_STDOUT"; then
|
||||
echo "external_offsets INI did not register USER_M_PATH M111" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RETURN_VALUE_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.return_value.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$RETURN_VALUE_STDOUT"
|
||||
grep -Fq "file_read_count=75" "$RETURN_VALUE_STDOUT"
|
||||
grep -Fq "file_execute_count=75" "$RETURN_VALUE_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: line 6.000000: _value: - expected 0.000000, got 0.000000" "$RETURN_VALUE_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: line 28.000000: call with arg1=2.000000 expect 246.000000, got 246.000000" "$RETURN_VALUE_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: line 37.000000: call with arg1=-1.000000 expect 0.000000, got 0.000000" "$RETURN_VALUE_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: line 47.000000: call with arg1=0.000000 expect 4712.000000, got 4712.000000" "$RETURN_VALUE_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: line 53.000000: _value=4712.000000 - expected 4712.000000" "$RETURN_VALUE_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$RETURN_VALUE_STDOUT"
|
||||
if grep -Fq "fail:" "$RETURN_VALUE_STDOUT"; then
|
||||
echo "unexpected return-value failure message" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SUBS_FOLLOW_MAIN_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.subs_follow_main.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$SUBS_FOLLOW_MAIN_STDOUT"
|
||||
grep -Fq "file_read_count=9" "$SUBS_FOLLOW_MAIN_STDOUT"
|
||||
grep -Fq "file_execute_count=9" "$SUBS_FOLLOW_MAIN_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: Subs may follow main program " "$SUBS_FOLLOW_MAIN_STDOUT"
|
||||
grep -Fq "canon_event=PALLET_SHUTTLE" "$SUBS_FOLLOW_MAIN_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$SUBS_FOLLOW_MAIN_STDOUT"
|
||||
|
||||
FRACTIONAL_LINENUMBERS_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.fractional_linenumbers.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$FRACTIONAL_LINENUMBERS_STDOUT"
|
||||
grep -Fq "file_read_count=4" "$FRACTIONAL_LINENUMBERS_STDOUT"
|
||||
grep -Fq "file_execute_count=4" "$FRACTIONAL_LINENUMBERS_STDOUT"
|
||||
grep -Fq "canon_event=SET_SPINDLE_SPEED spindle=0 speed=300" "$FRACTIONAL_LINENUMBERS_STDOUT"
|
||||
grep -Fq "canon_event=SET_SPINDLE_SPEED spindle=0 speed=600" "$FRACTIONAL_LINENUMBERS_STDOUT"
|
||||
grep -Fq "canon_event=SET_SPINDLE_SPEED spindle=0 speed=1200" "$FRACTIONAL_LINENUMBERS_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$FRACTIONAL_LINENUMBERS_STDOUT"
|
||||
|
||||
NAMEDPARAM_BUG424_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.namedparam_bug424.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$NAMEDPARAM_BUG424_STDOUT"
|
||||
grep -Fq "file_read_count=6" "$NAMEDPARAM_BUG424_STDOUT"
|
||||
grep -Fq "file_execute_count=6" "$NAMEDPARAM_BUG424_STDOUT"
|
||||
grep -Fq "setup.current_x=2" "$NAMEDPARAM_BUG424_STDOUT"
|
||||
grep -Fq "setup.current_y=3" "$NAMEDPARAM_BUG424_STDOUT"
|
||||
grep -Fq "setup.current_z=4" "$NAMEDPARAM_BUG424_STDOUT"
|
||||
grep -Fq "canon_event=USE_LENGTH_UNITS units=1" "$NAMEDPARAM_BUG424_STDOUT"
|
||||
grep -Fq "canon_event=STRAIGHT_TRAVERSE line=5 x=2 y=3 z=4" "$NAMEDPARAM_BUG424_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$NAMEDPARAM_BUG424_STDOUT"
|
||||
|
||||
G6164_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.g6164.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$G6164_STDOUT"
|
||||
grep -Fq "file_read_count=6" "$G6164_STDOUT"
|
||||
grep -Fq "file_execute_count=6" "$G6164_STDOUT"
|
||||
grep -Fq "canon_event=SET_MOTION_CONTROL_MODE mode=3 tolerance=0" "$G6164_STDOUT"
|
||||
grep -Fq "canon_event=SET_NAIVECAM_TOLERANCE tolerance=0" "$G6164_STDOUT"
|
||||
grep -Fq "canon_event=SET_MOTION_CONTROL_MODE mode=3 tolerance=1" "$G6164_STDOUT"
|
||||
grep -Fq "canon_event=SET_NAIVECAM_TOLERANCE tolerance=1" "$G6164_STDOUT"
|
||||
grep -Fq "canon_event=SET_NAIVECAM_TOLERANCE tolerance=2" "$G6164_STDOUT"
|
||||
grep -Fq "canon_event=SET_MOTION_CONTROL_MODE mode=2 tolerance=0" "$G6164_STDOUT"
|
||||
grep -Fq "canon_event=SET_MOTION_CONTROL_MODE mode=1 tolerance=0" "$G6164_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$G6164_STDOUT"
|
||||
|
||||
ROTATION_ABS_PTS_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.rotation_abs_pts.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$ROTATION_ABS_PTS_STDOUT"
|
||||
grep -Fq "file_read_count=192" "$ROTATION_ABS_PTS_STDOUT"
|
||||
grep -Fq "file_execute_count=192" "$ROTATION_ABS_PTS_STDOUT"
|
||||
grep -Fq "file_saw_error=0" "$ROTATION_ABS_PTS_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$ROTATION_ABS_PTS_STDOUT"
|
||||
if [[ "$(grep -Fc "canon_event=MESSAGE: 0.000000 0.000000 0.000000" "$ROTATION_ABS_PTS_STDOUT")" != "14" ]]; then
|
||||
echo "unexpected rotation/abs-pts zero absolute-position message count" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$(grep -Fc "canon_event=MESSAGE: 1.000000 2.000000 3.000000" "$ROTATION_ABS_PTS_STDOUT")" != "14" ]]; then
|
||||
echo "unexpected rotation/abs-pts target absolute-position message count" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ROTATION_G28_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.rotation_g28.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$ROTATION_G28_STDOUT"
|
||||
grep -Fq "file_read_count=13" "$ROTATION_G28_STDOUT"
|
||||
grep -Fq "file_execute_count=13" "$ROTATION_G28_STDOUT"
|
||||
grep -Fq "file_saw_error=0" "$ROTATION_G28_STDOUT"
|
||||
grep -Fq "canon_event=SET_XY_ROTATION rotation=45" "$ROTATION_G28_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: G55 G28" "$ROTATION_G28_STDOUT"
|
||||
grep -Fq "canon_event=STRAIGHT_TRAVERSE line=9 x=10 y=10 z=0" "$ROTATION_G28_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: G56 G28" "$ROTATION_G28_STDOUT"
|
||||
grep -Fq "canon_event=STRAIGHT_TRAVERSE line=14 x=0 y=14.1421 z=0 a=1" "$ROTATION_G28_STDOUT"
|
||||
grep -Eq "canon_event=STRAIGHT_TRAVERSE line=14 x=(0|[0-9.e-]+) y=14\\.1421 z=0 a=0" "$ROTATION_G28_STDOUT"
|
||||
grep -Fq "canon_event=FINISH" "$ROTATION_G28_STDOUT"
|
||||
|
||||
ROTATION_G53_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.rotation_g53.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$ROTATION_G53_STDOUT"
|
||||
grep -Fq "file_read_count=17" "$ROTATION_G53_STDOUT"
|
||||
grep -Fq "file_execute_count=17" "$ROTATION_G53_STDOUT"
|
||||
grep -Fq "file_saw_error=0" "$ROTATION_G53_STDOUT"
|
||||
grep -Fq "canon_event=SET_XY_ROTATION rotation=45" "$ROTATION_G53_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: g53 + g55 to 1,1" "$ROTATION_G53_STDOUT"
|
||||
grep -Eq "canon_event=STRAIGHT_TRAVERSE line=8 x=1\\.41421 y=([0-9.e-]+) z=0" "$ROTATION_G53_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: g53 + g55 + g92 to 1,1" "$ROTATION_G53_STDOUT"
|
||||
grep -Fq "canon_event=STRAIGHT_TRAVERSE line=13 x=0 y=0 z=0" "$ROTATION_G53_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: g53 + g56 + g92 to 1,1" "$ROTATION_G53_STDOUT"
|
||||
grep -Fq "canon_event=STRAIGHT_TRAVERSE line=18 x=-0.414214 y=1 z=0 a=1" "$ROTATION_G53_STDOUT"
|
||||
grep -Fq "canon_event=FINISH" "$ROTATION_G53_STDOUT"
|
||||
|
||||
SUB_CALL_FROM_SUB_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.sub_call_from_sub.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$SUB_CALL_FROM_SUB_STDOUT"
|
||||
grep -Fq "file_read_count=10" "$SUB_CALL_FROM_SUB_STDOUT"
|
||||
grep -Fq "file_execute_count=10" "$SUB_CALL_FROM_SUB_STDOUT"
|
||||
grep -Fq "X caller: 1.000000 2.000000 3.000000" "$SUB_CALL_FROM_SUB_STDOUT"
|
||||
grep -Fq "X helper: 4.000000 5.000000 6.000000" "$SUB_CALL_FROM_SUB_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: Test: calling a sub from within another sub is valid" "$SUB_CALL_FROM_SUB_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$SUB_CALL_FROM_SUB_STDOUT"
|
||||
|
||||
SEQUENCE_NUMBER_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.sequence_number.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$SEQUENCE_NUMBER_STDOUT"
|
||||
grep -Fq "file_read_count=13" "$SEQUENCE_NUMBER_STDOUT"
|
||||
grep -Fq "file_execute_count=13" "$SEQUENCE_NUMBER_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: main: line=7.000000 - expect 7" "$SEQUENCE_NUMBER_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: in rm400.ngc line=2.000000 - expect 2" "$SEQUENCE_NUMBER_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: main: line=9.000000 - expect 9" "$SEQUENCE_NUMBER_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$SEQUENCE_NUMBER_STDOUT"
|
||||
|
||||
NESTED_SUB_ERROR_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.nested_sub_error.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$NESTED_SUB_ERROR_STDOUT"
|
||||
grep -Fq "file_read_4=5" "$NESTED_SUB_ERROR_STDOUT"
|
||||
grep -Fq "file_read_count=4" "$NESTED_SUB_ERROR_STDOUT"
|
||||
grep -Fq "file_execute_count=3" "$NESTED_SUB_ERROR_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: Test: nested sub definition inside named sub should error" "$NESTED_SUB_ERROR_STDOUT"
|
||||
if grep -Fq "canon_event=PROGRAM_END" "$NESTED_SUB_ERROR_STDOUT"; then
|
||||
echo "unexpected nested-sub-error program end" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NESTED_SUB_IN_FILE_ERROR_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.nested_sub_in_file_error.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$NESTED_SUB_IN_FILE_ERROR_STDOUT"
|
||||
grep -Fq "file_execute_5=5" "$NESTED_SUB_IN_FILE_ERROR_STDOUT"
|
||||
grep -Fq "file_error_text=Subroutine 'O200' not found -- not in offset table and no file '" "$NESTED_SUB_IN_FILE_ERROR_STDOUT"
|
||||
grep -Fq "file_read_count=5" "$NESTED_SUB_IN_FILE_ERROR_STDOUT"
|
||||
grep -Fq "file_execute_count=5" "$NESTED_SUB_IN_FILE_ERROR_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: Test: numbered sub after named endsub in same file should error" "$NESTED_SUB_IN_FILE_ERROR_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: sequential main: 7.000000 8.000000 9.000000" "$NESTED_SUB_IN_FILE_ERROR_STDOUT"
|
||||
if grep -Fq "canon_event=PROGRAM_END" "$NESTED_SUB_IN_FILE_ERROR_STDOUT"; then
|
||||
echo "unexpected nested-sub-in-file-error program end" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
OWORD_UNWIND_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.oword_unwind.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$OWORD_UNWIND_STDOUT"
|
||||
grep -Fq "file_read_5=5" "$OWORD_UNWIND_STDOUT"
|
||||
grep -Fq "file_read_10=5" "$OWORD_UNWIND_STDOUT"
|
||||
grep -Fq "file_read_count=11" "$OWORD_UNWIND_STDOUT"
|
||||
grep -Fq "file_execute_count=9" "$OWORD_UNWIND_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: pre divide-by-zero" "$OWORD_UNWIND_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$OWORD_UNWIND_STDOUT"
|
||||
if grep -Fq "canon_event=MESSAGE: post divide-by-zero" "$OWORD_UNWIND_STDOUT"; then
|
||||
echo "unexpected oword-unwind post-error message" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ABORT_HOT_COMMENT_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.abort_hot_comment.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$ABORT_HOT_COMMENT_STDOUT"
|
||||
grep -Fq "file_read_count=125" "$ABORT_HOT_COMMENT_STDOUT"
|
||||
grep -Fq "file_execute_count=125" "$ABORT_HOT_COMMENT_STDOUT"
|
||||
grep -Fq "file_saw_error=1" "$ABORT_HOT_COMMENT_STDOUT"
|
||||
grep -Fq "file_error_text= MixedCase param42=20.000000 named=4711.000000 INI=3.140000" "$ABORT_HOT_COMMENT_STDOUT"
|
||||
if grep -Fq "canon_event=PROGRAM_END" "$ABORT_HOT_COMMENT_STDOUT"; then
|
||||
echo "abort-hot-comment unexpectedly reached program end" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
M19_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.m19.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$M19_STDOUT"
|
||||
grep -Fq "file_read_count=8" "$M19_STDOUT"
|
||||
grep -Fq "file_execute_count=8" "$M19_STDOUT"
|
||||
grep -Fq "file_saw_error=0" "$M19_STDOUT"
|
||||
grep -Fq "canon_event=ORIENT_SPINDLE spindle=0 orientation=87 mode=0" "$M19_STDOUT"
|
||||
grep -Fq "canon_event=WAIT_SPINDLE_ORIENT_COMPLETE spindle=0 timeout=2" "$M19_STDOUT"
|
||||
grep -Fq "canon_event=ORIENT_SPINDLE spindle=0 orientation=42 mode=1" "$M19_STDOUT"
|
||||
grep -Fq "canon_event=ORIENT_SPINDLE spindle=0 orientation=132 mode=0" "$M19_STDOUT"
|
||||
grep -Fq "canon_event=ORIENT_SPINDLE spindle=0 orientation=132 mode=1" "$M19_STDOUT"
|
||||
grep -Fq "canon_event=WAIT_SPINDLE_ORIENT_COMPLETE spindle=0 timeout=1" "$M19_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$M19_STDOUT"
|
||||
|
||||
MAGIC_COMMENTS_PARAM_FORMAT_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.magic_comments_param_format.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$MAGIC_COMMENTS_PARAM_FORMAT_STDOUT"
|
||||
grep -Fq "file_read_count=13" "$MAGIC_COMMENTS_PARAM_FORMAT_STDOUT"
|
||||
grep -Fq "file_execute_count=13" "$MAGIC_COMMENTS_PARAM_FORMAT_STDOUT"
|
||||
grep -Fq "file_saw_error=0" "$MAGIC_COMMENTS_PARAM_FORMAT_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: native value = 1.123457" "$MAGIC_COMMENTS_PARAM_FORMAT_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: Test round to integer: 1" "$MAGIC_COMMENTS_PARAM_FORMAT_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: Test round to 4 decimals: 1.1235" "$MAGIC_COMMENTS_PARAM_FORMAT_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: Test format separate from param: The value is: 1.1235" "$MAGIC_COMMENTS_PARAM_FORMAT_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: Test round to 7 decimals: 1.1234568" "$MAGIC_COMMENTS_PARAM_FORMAT_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: native value2 = 2.345679" "$MAGIC_COMMENTS_PARAM_FORMAT_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: Test2 round all params in line to 4 decimals: The values are: 1.1235, 2.3457" "$MAGIC_COMMENTS_PARAM_FORMAT_STDOUT"
|
||||
grep -Fq "canon_event=MESSAGE: Test2 only round last value to integer: The values are: 1.123457, 2" "$MAGIC_COMMENTS_PARAM_FORMAT_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$MAGIC_COMMENTS_PARAM_FORMAT_STDOUT"
|
||||
|
||||
M98M99_01_BASICS_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.m98m99_01_basics.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$M98M99_01_BASICS_STDOUT"
|
||||
grep -Fq "file_read_count=22" "$M98M99_01_BASICS_STDOUT"
|
||||
grep -Fq "file_execute_count=22" "$M98M99_01_BASICS_STDOUT"
|
||||
grep -Fq "file_saw_error=0" "$M98M99_01_BASICS_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: A simple O sub example " "$M98M99_01_BASICS_STDOUT"
|
||||
grep -Fq "canon_event=STRAIGHT_TRAVERSE line=10 x=3 y=0 z=0.25" "$M98M99_01_BASICS_STDOUT"
|
||||
grep -Fq "canon_event=STRAIGHT_FEED line=11 x=3 y=0 z=-1" "$M98M99_01_BASICS_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$M98M99_01_BASICS_STDOUT"
|
||||
|
||||
M98M99_02_VARIABLES_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.m98m99_02_variables.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$M98M99_02_VARIABLES_STDOUT"
|
||||
grep -Fq "file_read_count=54" "$M98M99_02_VARIABLES_STDOUT"
|
||||
grep -Fq "file_execute_count=54" "$M98M99_02_VARIABLES_STDOUT"
|
||||
grep -Fq "file_saw_error=0" "$M98M99_02_VARIABLES_STDOUT"
|
||||
grep -Fq "Q MAIN/FANUC: POST-M98: 1=13.010000; 30=13.300000; 31=13.310000" "$M98M99_02_VARIABLES_STDOUT"
|
||||
grep -Fq "Q MAIN/RS274NGC: POST-O-CALL: 1=42.010000; 30=42.300000; 31=13.310000" "$M98M99_02_VARIABLES_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$M98M99_02_VARIABLES_STDOUT"
|
||||
|
||||
M98M99_07_NESTED_SUBS_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.m98m99_07_nested_subs.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$M98M99_07_NESTED_SUBS_STDOUT"
|
||||
grep -Fq "file_read_count=163" "$M98M99_07_NESTED_SUBS_STDOUT"
|
||||
grep -Fq "file_execute_count=163" "$M98M99_07_NESTED_SUBS_STDOUT"
|
||||
grep -Fq "file_saw_error=0" "$M98M99_07_NESTED_SUBS_STDOUT"
|
||||
grep -Fq "X >>>> LOOP [O2.O1]: 4.500000" "$M98M99_07_NESTED_SUBS_STDOUT"
|
||||
grep -Fq "X MAIN END: 1=5.000000" "$M98M99_07_NESTED_SUBS_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$M98M99_07_NESTED_SUBS_STDOUT"
|
||||
|
||||
M98M99_08_SUB_FOLLOWS_MAIN_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.m98m99_08_sub_follows_main.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$M98M99_08_SUB_FOLLOWS_MAIN_STDOUT"
|
||||
grep -Fq "file_read_count=9" "$M98M99_08_SUB_FOLLOWS_MAIN_STDOUT"
|
||||
grep -Fq "file_execute_count=9" "$M98M99_08_SUB_FOLLOWS_MAIN_STDOUT"
|
||||
grep -Fq "file_saw_error=0" "$M98M99_08_SUB_FOLLOWS_MAIN_STDOUT"
|
||||
grep -Fq "X IN O1" "$M98M99_08_SUB_FOLLOWS_MAIN_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: Fanuc-style subs may follow main program " "$M98M99_08_SUB_FOLLOWS_MAIN_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$M98M99_08_SUB_FOLLOWS_MAIN_STDOUT"
|
||||
|
||||
M98M99_10_M98_P001_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.m98m99_10_m98_p001.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$M98M99_10_M98_P001_STDOUT"
|
||||
grep -Fq "file_read_count=8" "$M98M99_10_M98_P001_STDOUT"
|
||||
grep -Fq "file_execute_count=8" "$M98M99_10_M98_P001_STDOUT"
|
||||
grep -Fq "file_saw_error=0" "$M98M99_10_M98_P001_STDOUT"
|
||||
grep -Fq "x got here" "$M98M99_10_M98_P001_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: main program" "$M98M99_10_M98_P001_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$M98M99_10_M98_P001_STDOUT"
|
||||
if awk '
|
||||
/^file_read_1=0$/ { in_file = 1 }
|
||||
in_file && /ERROR: should not get here/ { found = 1 }
|
||||
END { exit(found ? 0 : 1) }
|
||||
' "$M98M99_10_M98_P001_STDOUT"; then
|
||||
echo "unexpected m98m99 leading-zero O-word fallback branch" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
M98M99_13_NAMED_PROGRAM_NAMED_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.m98m99_13_named_program_named.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$M98M99_13_NAMED_PROGRAM_NAMED_STDOUT"
|
||||
grep -Fq "file_read_count=4" "$M98M99_13_NAMED_PROGRAM_NAMED_STDOUT"
|
||||
grep -Fq "file_execute_count=4" "$M98M99_13_NAMED_PROGRAM_NAMED_STDOUT"
|
||||
grep -Fq "file_saw_error=0" "$M98M99_13_NAMED_PROGRAM_NAMED_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: test-named.ngc: Test named programs" "$M98M99_13_NAMED_PROGRAM_NAMED_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: ...program body" "$M98M99_13_NAMED_PROGRAM_NAMED_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$M98M99_13_NAMED_PROGRAM_NAMED_STDOUT"
|
||||
|
||||
M98M99_13_NAMED_PROGRAM_NUMBERED_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.m98m99_13_named_program_numbered.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$M98M99_13_NAMED_PROGRAM_NUMBERED_STDOUT"
|
||||
grep -Fq "file_read_count=4" "$M98M99_13_NAMED_PROGRAM_NUMBERED_STDOUT"
|
||||
grep -Fq "file_execute_count=4" "$M98M99_13_NAMED_PROGRAM_NUMBERED_STDOUT"
|
||||
grep -Fq "file_saw_error=0" "$M98M99_13_NAMED_PROGRAM_NUMBERED_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: test-numbered.ngc: Test numbered programs" "$M98M99_13_NAMED_PROGRAM_NUMBERED_STDOUT"
|
||||
grep -Fq "canon_event=COMMENT: ...program body" "$M98M99_13_NAMED_PROGRAM_NUMBERED_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$M98M99_13_NAMED_PROGRAM_NUMBERED_STDOUT"
|
||||
|
||||
M98M99_14_O_EXPRESSION_CALL_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.m98m99_14_o_expression_call.run.stdout.log"
|
||||
grep -Fq "file_open=0" "$M98M99_14_O_EXPRESSION_CALL_STDOUT"
|
||||
grep -Fq "file_read_count=29" "$M98M99_14_O_EXPRESSION_CALL_STDOUT"
|
||||
grep -Fq "file_execute_count=29" "$M98M99_14_O_EXPRESSION_CALL_STDOUT"
|
||||
grep -Fq "file_saw_error=0" "$M98M99_14_O_EXPRESSION_CALL_STDOUT"
|
||||
grep -Fq "In sub 100" "$M98M99_14_O_EXPRESSION_CALL_STDOUT"
|
||||
grep -Fq "In sub 200" "$M98M99_14_O_EXPRESSION_CALL_STDOUT"
|
||||
grep -Fq "canon_event=PROGRAM_END" "$M98M99_14_O_EXPRESSION_CALL_STDOUT"
|
||||
|
||||
for fixture in "$GCODE_FIXTURE_DIR"/*.ngc; do
|
||||
name="$(basename "$fixture" .ngc)"
|
||||
if [[ "$name" == "disable_fanuc_style_sub_m98" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
expected="$CANON_FIXTURE_DIR/$name.events"
|
||||
if [[ ! -f "$expected" ]]; then
|
||||
echo "missing expected canon fixture: $expected" >&2
|
||||
@@ -737,9 +1380,62 @@ for fixture in "$GCODE_FIXTURE_DIR"/*.ngc; do
|
||||
if [[ "$name" == "oword_subroutine" || "$name" == "percent_file_finish" ]]; then
|
||||
require_mdi=0
|
||||
fi
|
||||
if [[ "$name" == "namedparam_semantics" ||
|
||||
"$name" == "namedparam_ini_semantics" ||
|
||||
"$name" == "ini_tool_table" ||
|
||||
"$name" == "spindle_orient_offset" ]]; then
|
||||
continue
|
||||
fi
|
||||
check_fixture_output "$fixture" "$expected" "$stdout_file" "$require_mdi"
|
||||
done
|
||||
|
||||
for name in namedparam_semantics namedparam_ini_semantics; do
|
||||
fixture="$GCODE_FIXTURE_DIR/$name.ngc"
|
||||
expected="$CANON_FIXTURE_DIR/$name.events"
|
||||
stdout_file="$BUILD_DIR/linuxcnc_interp_minimal_harness.$name.with_ini.stdout.log"
|
||||
stderr_file="$BUILD_DIR/linuxcnc_interp_minimal_harness.$name.with_ini.stderr.log"
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" "$fixture" "$NAMEDPARAM_INI_FIXTURE" \
|
||||
>"$stdout_file" \
|
||||
2>"$stderr_file"
|
||||
check_fixture_output "$fixture" "$expected" "$stdout_file"
|
||||
done
|
||||
|
||||
INI_TOOL_TABLE_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.ini_tool_table.with_ini.stdout.log"
|
||||
INI_TOOL_TABLE_STDERR="$BUILD_DIR/linuxcnc_interp_minimal_harness.ini_tool_table.with_ini.stderr.log"
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" \
|
||||
"$GCODE_FIXTURE_DIR/ini_tool_table.ngc" \
|
||||
"$ROOT_DIR/tests/fixtures/ini/ini_tool_table.ini" \
|
||||
>"$INI_TOOL_TABLE_STDOUT" \
|
||||
2>"$INI_TOOL_TABLE_STDERR"
|
||||
check_fixture_output \
|
||||
"$GCODE_FIXTURE_DIR/ini_tool_table.ngc" \
|
||||
"$CANON_FIXTURE_DIR/ini_tool_table.events" \
|
||||
"$INI_TOOL_TABLE_STDOUT"
|
||||
|
||||
SPINDLE_ORIENT_OFFSET_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.spindle_orient_offset.with_ini.stdout.log"
|
||||
SPINDLE_ORIENT_OFFSET_STDERR="$BUILD_DIR/linuxcnc_interp_minimal_harness.spindle_orient_offset.with_ini.stderr.log"
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" \
|
||||
"$GCODE_FIXTURE_DIR/spindle_orient_offset.ngc" \
|
||||
"$SPINDLE_ORIENT_OFFSET_INI_FIXTURE" \
|
||||
>"$SPINDLE_ORIENT_OFFSET_STDOUT" \
|
||||
2>"$SPINDLE_ORIENT_OFFSET_STDERR"
|
||||
check_fixture_output \
|
||||
"$GCODE_FIXTURE_DIR/spindle_orient_offset.ngc" \
|
||||
"$CANON_FIXTURE_DIR/spindle_orient_offset.events" \
|
||||
"$SPINDLE_ORIENT_OFFSET_STDOUT"
|
||||
|
||||
DISABLE_FANUC_STYLE_SUB_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.disable_fanuc_style_sub_m98.with_ini.stdout.log"
|
||||
DISABLE_FANUC_STYLE_SUB_STDERR="$BUILD_DIR/linuxcnc_interp_minimal_harness.disable_fanuc_style_sub_m98.with_ini.stderr.log"
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" \
|
||||
"$GCODE_FIXTURE_DIR/disable_fanuc_style_sub_m98.ngc" \
|
||||
"$DISABLE_FANUC_STYLE_SUB_INI_FIXTURE" \
|
||||
>"$DISABLE_FANUC_STYLE_SUB_STDOUT" \
|
||||
2>"$DISABLE_FANUC_STYLE_SUB_STDERR"
|
||||
grep -Fq "file_open=0" "$DISABLE_FANUC_STYLE_SUB_STDOUT"
|
||||
grep -Fq "file_saw_error=1" "$DISABLE_FANUC_STYLE_SUB_STDOUT"
|
||||
grep -Fq "file_error_text=DISABLE_FANUC_STYLE_SUB set in INI file, but found m98" \
|
||||
"$DISABLE_FANUC_STYLE_SUB_STDOUT"
|
||||
|
||||
for fixture in "$GCODE_ERROR_FIXTURE_DIR"/*.ngc; do
|
||||
name="$(basename "$fixture" .ngc)"
|
||||
expected="$CANON_ERROR_FIXTURE_DIR/$name.expected"
|
||||
@@ -770,4 +1466,6 @@ for fixture in "$GCODE_ERROR_FIXTURE_DIR"/*.ngc; do
|
||||
done < "$expected"
|
||||
done
|
||||
|
||||
printf '%s\n' "$NATIVE_PROBE_VALIDATION_FINGERPRINT" > "$VALIDATION_CACHE_KEY_FILE"
|
||||
printf '%s\n' "$NATIVE_PROBE_VALIDATION_FINGERPRINT" > "$VALIDATION_CACHE_OK_FILE"
|
||||
echo "native probe validation complete"
|
||||
|
||||
313
wasm-port/tests/native/verify_nc_files.sh
Executable file
313
wasm-port/tests/native/verify_nc_files.sh
Executable file
@@ -0,0 +1,313 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
WORKSPACE_ROOT="$(cd "$ROOT_DIR/.." && pwd)"
|
||||
LINUXCNC_DIR="${LINUXCNC_DIR:-$WORKSPACE_ROOT/linuxcnc}"
|
||||
NC_DIR="$LINUXCNC_DIR/nc_files"
|
||||
BUILD_DIR="${NC_FILES_BUILD_DIR:-$ROOT_DIR/build/native/nc-files}"
|
||||
RS274="${RS274:-$LINUXCNC_DIR/bin/rs274}"
|
||||
TIMEOUT_SECONDS="${NC_FILES_TIMEOUT_SECONDS:-30}"
|
||||
ONLY_FILTER=""
|
||||
SCAN_ALL=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--all)
|
||||
SCAN_ALL=1
|
||||
shift
|
||||
;;
|
||||
--only)
|
||||
[[ $# -ge 2 ]] || { echo "missing value for --only" >&2; exit 2; }
|
||||
ONLY_FILTER="$2"
|
||||
shift 2
|
||||
;;
|
||||
--help|-h)
|
||||
cat <<EOF
|
||||
Usage: $0 [--all] [--only PATH_SUBSTRING]
|
||||
|
||||
Runs LinuxCNC nc_files programs through LinuxCNC's rs274 standalone entry point.
|
||||
The default suite covers the basic/example programs and common macro libraries.
|
||||
Use --all to scan every .ngc under linuxcnc/nc_files.
|
||||
|
||||
Results are written under:
|
||||
$BUILD_DIR
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "unknown argument: $1" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ! -x "$RS274" ]]; then
|
||||
echo "missing executable rs274: $RS274" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$NC_DIR" ]]; then
|
||||
echo "missing LinuxCNC nc_files directory: $NC_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export LD_LIBRARY_PATH="$LINUXCNC_DIR/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
||||
export PYTHONPATH="$LINUXCNC_DIR/lib/python${PYTHONPATH:+:$PYTHONPATH}"
|
||||
|
||||
mkdir -p "$BUILD_DIR"/{logs,out,wrapped,params}
|
||||
SUMMARY_FILE="$BUILD_DIR/summary.tsv"
|
||||
INI_FILE="$BUILD_DIR/test-rs274.ini"
|
||||
TOOL_TABLE="$BUILD_DIR/test-tools.tbl"
|
||||
PARAMETER_TEMPLATE="$BUILD_DIR/test.var.template"
|
||||
printf 'path\tclass\tstatus\texpected_failure\texit_code\tseconds\toutput_lines\tstderr_summary\n' > "$SUMMARY_FILE"
|
||||
|
||||
relpath() {
|
||||
local path="$1"
|
||||
printf '%s\n' "${path#"$NC_DIR"/}"
|
||||
}
|
||||
|
||||
safe_name() {
|
||||
local rel="$1"
|
||||
rel="${rel//\//_}"
|
||||
rel="${rel// /_}"
|
||||
rel="${rel//#/_}"
|
||||
rel="${rel//=/}"
|
||||
printf '%s\n' "$rel"
|
||||
}
|
||||
|
||||
write_fixture_config() {
|
||||
{
|
||||
printf '[RS274NGC]\n'
|
||||
printf 'PARAMETER_FILE = test.var\n'
|
||||
printf 'SUBROUTINE_PATH = %s\n' "$(
|
||||
find "$NC_DIR" -type d | sort | paste -sd ':' -
|
||||
)"
|
||||
printf 'OWORD_NARGS = 1\n'
|
||||
printf 'FEATURES = 30\n'
|
||||
printf '\n[DISPLAY]\n'
|
||||
printf 'PROGRAM_PREFIX = %s\n' "$NC_DIR"
|
||||
printf '\n[TRAJ]\n'
|
||||
printf 'COORDINATES = X Y Z A B C U V W\n'
|
||||
printf '\n[EMCIO]\n'
|
||||
printf 'TOOL_TABLE = %s\n' "$TOOL_TABLE"
|
||||
} > "$INI_FILE"
|
||||
|
||||
: > "$TOOL_TABLE"
|
||||
local tool
|
||||
for tool in $(seq 1 200); do
|
||||
printf 'T%s P%s D0.125000 Z+0.000000 ; generated nc_files test tool\n' "$tool" "$tool" >> "$TOOL_TABLE"
|
||||
done
|
||||
|
||||
{
|
||||
printf '5161 0.0\n'
|
||||
printf '5162 0.0\n'
|
||||
printf '5163 0.0\n'
|
||||
printf '5220 1\n'
|
||||
printf '5221 0.0\n'
|
||||
printf '5222 0.0\n'
|
||||
printf '5223 0.0\n'
|
||||
printf '5399 0.0\n'
|
||||
} > "$PARAMETER_TEMPLATE"
|
||||
}
|
||||
|
||||
has_program_end() {
|
||||
local ngc="$1"
|
||||
awk '
|
||||
BEGIN { found = 0 }
|
||||
/^[[:space:]]*%[[:space:]]*$/ { found = 1 }
|
||||
{
|
||||
line = tolower($0)
|
||||
gsub(/\([^)]*\)/, "", line)
|
||||
if (line ~ /(^|[[:space:]])m0*(2|30)([[:space:]]|$)/) {
|
||||
found = 1
|
||||
}
|
||||
}
|
||||
END { exit(found ? 0 : 1) }
|
||||
' "$ngc"
|
||||
}
|
||||
|
||||
is_default_basic_path() {
|
||||
local rel="$1"
|
||||
case "$rel" in
|
||||
*/*)
|
||||
case "$rel" in
|
||||
gladevcp_lib/*.ngc|macros/lathe/*.ngc|macros/mill/*.ngc|ngcgui_lib/*.ngc)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
;;
|
||||
*.ngc)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
classify_program() {
|
||||
local rel="$1"
|
||||
local ngc="$2"
|
||||
case "$rel" in
|
||||
macros/*|ngcgui_lib/*|gladevcp_lib/*|remap-subroutines/*|remap_lib/*|probe/*)
|
||||
printf 'macro_load\n'
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
if has_program_end "$ngc"; then
|
||||
printf 'main\n'
|
||||
else
|
||||
printf 'macro_load\n'
|
||||
fi
|
||||
}
|
||||
|
||||
prepare_input() {
|
||||
local class="$1"
|
||||
local ngc="$2"
|
||||
local wrapped="$3"
|
||||
if [[ "$class" == "main" ]]; then
|
||||
printf '%s\n' "$ngc"
|
||||
return 0
|
||||
fi
|
||||
cp "$ngc" "$wrapped"
|
||||
printf '\nM2\n' >> "$wrapped"
|
||||
printf '%s\n' "$wrapped"
|
||||
}
|
||||
|
||||
known_expected_failure() {
|
||||
local rel="$1"
|
||||
local combined="$2"
|
||||
case "$rel" in
|
||||
cone.ngc)
|
||||
[[ "$combined" == *"Bad character 'w' used"* ]] && { printf 'five-axis-W-machine-context\n'; return 0; }
|
||||
;;
|
||||
g76.ngc|lathe-g76.ngc)
|
||||
[[ "$combined" == *"Length of cutter compensation entry move is not greater than the tool radius"* ]] && { printf 'lathe-cutter-comp-tool-context\n'; return 0; }
|
||||
;;
|
||||
lathe_g70_71_demo.ngc)
|
||||
[[ "$combined" == *"Arc move in concave corner cannot be reached by the tool without gouging"* ]] && { printf 'lathe-profile-tool-context\n'; return 0; }
|
||||
;;
|
||||
nestedcall.ngc)
|
||||
[[ "$combined" == *"Unexpected character after O-word"* ]] && { printf 'upstream-oword-callsub-syntax-edge\n'; return 0; }
|
||||
;;
|
||||
nurbs/G5/Curva_Stella\ #1=1_G5.ngc)
|
||||
[[ "$combined" == *"Unknown g code used"* && "$combined" == *"G2.2"* ]] && { printf 'nurbs-g22-entrypoint-edge\n'; return 0; }
|
||||
;;
|
||||
probe*.ngc|probe/*|smartprobe.ngc|tool-length-probe.ngc|touchoff.ngc)
|
||||
[[ "$combined" == *"probe"* || "$combined" == *"G38"* ]] && { printf 'probe-runtime-context\n'; return 0; }
|
||||
;;
|
||||
plasmac/*|plasmatest.ngc)
|
||||
[[ "$combined" == *"Unknown m code"* || "$combined" == *"Named parameter"* ]] && { printf 'plasmac-runtime-context\n'; return 0; }
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
summarize_text() {
|
||||
local file="$1"
|
||||
if [[ ! -f "$file" ]]; then
|
||||
return 0
|
||||
fi
|
||||
tr '\n\t' ' ' < "$file" | sed -E 's/[[:space:]]+/ /g; s/^ //; s/ $//' | cut -c 1-260
|
||||
}
|
||||
|
||||
write_fixture_config
|
||||
|
||||
total=0
|
||||
pass=0
|
||||
fail=0
|
||||
timeout_count=0
|
||||
expected_fail=0
|
||||
unexpected_fail=0
|
||||
|
||||
while IFS= read -r ngc; do
|
||||
rel="$(relpath "$ngc")"
|
||||
if [[ "$SCAN_ALL" -eq 0 ]] && ! is_default_basic_path "$rel"; then
|
||||
continue
|
||||
fi
|
||||
if [[ -n "$ONLY_FILTER" && "$rel" != *"$ONLY_FILTER"* ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
total=$((total + 1))
|
||||
class="$(classify_program "$rel" "$ngc")"
|
||||
safe="$(safe_name "$rel")"
|
||||
wrapped="$BUILD_DIR/wrapped/$safe"
|
||||
input="$(prepare_input "$class" "$ngc" "$wrapped")"
|
||||
out_file="$BUILD_DIR/out/$safe.out"
|
||||
stdout_file="$BUILD_DIR/logs/$safe.stdout"
|
||||
stderr_file="$BUILD_DIR/logs/$safe.stderr"
|
||||
param_file="$BUILD_DIR/params/$safe.var"
|
||||
cp "$PARAMETER_TEMPLATE" "$param_file"
|
||||
|
||||
start_time="$(date +%s)"
|
||||
set +e
|
||||
(
|
||||
cd "$WORKSPACE_ROOT"
|
||||
INI_FILE_NAME="$INI_FILE" timeout "$TIMEOUT_SECONDS" "$RS274" \
|
||||
-g \
|
||||
-i "$INI_FILE" \
|
||||
-t "$TOOL_TABLE" \
|
||||
-v "$param_file" \
|
||||
"$input" \
|
||||
"$out_file"
|
||||
) >"$stdout_file" 2>"$stderr_file"
|
||||
rc=$?
|
||||
set -e
|
||||
end_time="$(date +%s)"
|
||||
seconds=$((end_time - start_time))
|
||||
|
||||
status="FAIL"
|
||||
if [[ "$rc" -eq 0 ]]; then
|
||||
status="PASS"
|
||||
pass=$((pass + 1))
|
||||
elif [[ "$rc" -eq 124 || "$rc" -eq 137 ]]; then
|
||||
status="TIMEOUT"
|
||||
timeout_count=$((timeout_count + 1))
|
||||
fail=$((fail + 1))
|
||||
else
|
||||
fail=$((fail + 1))
|
||||
fi
|
||||
|
||||
combined="$(cat "$stdout_file" "$stderr_file" 2>/dev/null || true)"
|
||||
expected=""
|
||||
if [[ "$status" != "PASS" ]]; then
|
||||
expected="$(known_expected_failure "$rel" "$combined" || true)"
|
||||
if [[ -n "$expected" ]]; then
|
||||
expected_fail=$((expected_fail + 1))
|
||||
else
|
||||
unexpected_fail=$((unexpected_fail + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
output_lines=0
|
||||
[[ -f "$out_file" ]] && output_lines="$(wc -l < "$out_file" | tr -d '[:space:]')"
|
||||
stderr_summary="$(summarize_text "$stderr_file")"
|
||||
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
|
||||
"$rel" \
|
||||
"$class" \
|
||||
"$status" \
|
||||
"$expected" \
|
||||
"$rc" \
|
||||
"$seconds" \
|
||||
"$output_lines" \
|
||||
"$stderr_summary" >> "$SUMMARY_FILE"
|
||||
done < <(find "$NC_DIR" -type f -name '*.ngc' | sort)
|
||||
|
||||
{
|
||||
printf 'nc_files harness summary\n'
|
||||
printf 'summary: %s\n' "$SUMMARY_FILE"
|
||||
printf 'suite: %s\n' "$([[ "$SCAN_ALL" -eq 1 ]] && printf all || printf basic)"
|
||||
printf 'total: %s\n' "$total"
|
||||
printf 'pass: %s\n' "$pass"
|
||||
printf 'fail: %s\n' "$fail"
|
||||
printf 'timeout: %s\n' "$timeout_count"
|
||||
printf 'expected_fail: %s\n' "$expected_fail"
|
||||
printf 'unexpected_fail: %s\n' "$unexpected_fail"
|
||||
} | tee "$BUILD_DIR/summary.txt"
|
||||
|
||||
if [[ "$unexpected_fail" -ne 0 ]]; then
|
||||
echo "unexpected nc_files failures:" >&2
|
||||
awk -F '\t' 'NR > 1 && $3 != "PASS" && $4 == "" { print $1 "\t" $3 "\t" $8 }' "$SUMMARY_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
387
wasm-port/tests/native/verify_sim_configs.sh
Executable file
387
wasm-port/tests/native/verify_sim_configs.sh
Executable file
@@ -0,0 +1,387 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
WORKSPACE_ROOT="$(cd "$ROOT_DIR/.." && pwd)"
|
||||
LINUXCNC_DIR="${LINUXCNC_DIR:-$WORKSPACE_ROOT/linuxcnc}"
|
||||
SIM_DIR="$LINUXCNC_DIR/configs/sim"
|
||||
BUILD_DIR="${SIM_CONFIG_BUILD_DIR:-$ROOT_DIR/build/native/sim-configs}"
|
||||
RS274="${RS274:-$LINUXCNC_DIR/bin/rs274}"
|
||||
TIMEOUT_SECONDS="${SIM_CONFIG_TIMEOUT_SECONDS:-30}"
|
||||
ONLY_FILTER=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--only)
|
||||
[[ $# -ge 2 ]] || { echo "missing value for --only" >&2; exit 2; }
|
||||
ONLY_FILTER="$2"
|
||||
shift 2
|
||||
;;
|
||||
--help|-h)
|
||||
cat <<EOF
|
||||
Usage: $0 [--only PATH_SUBSTRING]
|
||||
|
||||
Runs LinuxCNC configs/sim .ngc programs through LinuxCNC's rs274 standalone
|
||||
entry point and writes logs plus summary.tsv under:
|
||||
$BUILD_DIR
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "unknown argument: $1" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ! -x "$RS274" ]]; then
|
||||
echo "missing executable rs274: $RS274" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$SIM_DIR" ]]; then
|
||||
echo "missing LinuxCNC sim config directory: $SIM_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$ROOT_DIR/tools/build_native_probes.sh"
|
||||
|
||||
export LD_LIBRARY_PATH="$LINUXCNC_DIR/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
||||
export PYTHONPATH="$LINUXCNC_DIR/lib/python${PYTHONPATH:+:$PYTHONPATH}"
|
||||
|
||||
mkdir -p "$BUILD_DIR"/{logs,out,wrapped,params}
|
||||
: > "$BUILD_DIR/skipped.tsv"
|
||||
SUMMARY_FILE="$BUILD_DIR/summary.tsv"
|
||||
printf 'path\tclass\tstatus\texpected_failure\texit_code\tseconds\tini\ttbl\toutput_lines\tstderr_summary\n' > "$SUMMARY_FILE"
|
||||
|
||||
relpath() {
|
||||
local path="$1"
|
||||
printf '%s\n' "${path#"$SIM_DIR"/}"
|
||||
}
|
||||
|
||||
safe_name() {
|
||||
local rel="$1"
|
||||
rel="${rel//\//_}"
|
||||
rel="${rel// /_}"
|
||||
printf '%s\n' "$rel"
|
||||
}
|
||||
|
||||
find_nearest_ini() {
|
||||
local dir="$1"
|
||||
local candidate
|
||||
while [[ "$dir" == "$SIM_DIR"* ]]; do
|
||||
candidate="$(find "$dir" -maxdepth 1 -type f -name '*.ini' | sort | sed -n '1p')"
|
||||
if [[ -n "$candidate" ]]; then
|
||||
printf '%s\n' "$candidate"
|
||||
return 0
|
||||
fi
|
||||
[[ "$dir" == "$SIM_DIR" ]] && break
|
||||
dir="$(dirname "$dir")"
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
find_sim_ini() {
|
||||
local rel="$1"
|
||||
local ngc_dir="$2"
|
||||
case "$rel" in
|
||||
axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/*)
|
||||
printf '%s\n' "$SIM_DIR/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzacb-trsrn_twp/xyzacb-trsrn.ini"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
find_nearest_ini "$ngc_dir"
|
||||
}
|
||||
|
||||
ini_value() {
|
||||
local ini="$1"
|
||||
local section="$2"
|
||||
local key="$3"
|
||||
awk -v section="$section" -v key="$key" '
|
||||
BEGIN { in_section = 0 }
|
||||
/^[[:space:]]*[#;]/ { next }
|
||||
/^[[:space:]]*\[/ {
|
||||
in_section = (toupper($0) ~ "\\[" toupper(section) "\\]")
|
||||
next
|
||||
}
|
||||
in_section {
|
||||
line = $0
|
||||
sub(/[[:space:]]*[#;].*$/, "", line)
|
||||
split(line, parts, "=")
|
||||
name = parts[1]
|
||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", name)
|
||||
if (toupper(name) == toupper(key)) {
|
||||
value = substr(line, index(line, "=") + 1)
|
||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
|
||||
print value
|
||||
exit
|
||||
}
|
||||
}
|
||||
' "$ini"
|
||||
}
|
||||
|
||||
find_upward_file_by_name() {
|
||||
local start_dir="$1"
|
||||
local basename="$2"
|
||||
local dir="$start_dir"
|
||||
while [[ "$dir" == "$SIM_DIR"* ]]; do
|
||||
if [[ -f "$dir/$basename" ]]; then
|
||||
printf '%s\n' "$dir/$basename"
|
||||
return 0
|
||||
fi
|
||||
[[ "$dir" == "$SIM_DIR" ]] && break
|
||||
dir="$(dirname "$dir")"
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
find_nearest_tbl() {
|
||||
local ngc_dir="$1"
|
||||
local ini="$2"
|
||||
local tool_table
|
||||
tool_table="$(ini_value "$ini" EMCIO TOOL_TABLE || true)"
|
||||
if [[ -n "$tool_table" ]]; then
|
||||
if [[ "$tool_table" = /* && -f "$tool_table" ]]; then
|
||||
printf '%s\n' "$tool_table"
|
||||
return 0
|
||||
fi
|
||||
if [[ -f "$(dirname "$ini")/$tool_table" ]]; then
|
||||
printf '%s\n' "$(dirname "$ini")/$tool_table"
|
||||
return 0
|
||||
fi
|
||||
if find_upward_file_by_name "$ngc_dir" "$(basename "$tool_table")"; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
local dir="$ngc_dir"
|
||||
local candidate
|
||||
while [[ "$dir" == "$SIM_DIR"* ]]; do
|
||||
candidate="$(find "$dir" -maxdepth 1 -type f -name '*.tbl' | sort | sed -n '1p')"
|
||||
if [[ -n "$candidate" ]]; then
|
||||
printf '%s\n' "$candidate"
|
||||
return 0
|
||||
fi
|
||||
[[ "$dir" == "$SIM_DIR" ]] && break
|
||||
dir="$(dirname "$dir")"
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
copy_parameter_file() {
|
||||
local ini="$1"
|
||||
local dst="$2"
|
||||
local parameter_file
|
||||
parameter_file="$(ini_value "$ini" RS274NGC PARAMETER_FILE || true)"
|
||||
rm -f "$dst" "$dst.bak"
|
||||
if [[ -n "$parameter_file" ]]; then
|
||||
if [[ "$parameter_file" = /* && -f "$parameter_file" ]]; then
|
||||
cp "$parameter_file" "$dst"
|
||||
return 0
|
||||
fi
|
||||
if [[ -f "$(dirname "$ini")/$parameter_file" ]]; then
|
||||
cp "$(dirname "$ini")/$parameter_file" "$dst"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
has_program_end() {
|
||||
local ngc="$1"
|
||||
awk '
|
||||
BEGIN { found = 0 }
|
||||
/^[[:space:]]*%[[:space:]]*$/ { found = 1 }
|
||||
{
|
||||
line = tolower($0)
|
||||
gsub(/\([^)]*\)/, "", line)
|
||||
if (line ~ /(^|[[:space:]])m0*(2|30)([[:space:]]|$)/) {
|
||||
found = 1
|
||||
}
|
||||
}
|
||||
END { exit(found ? 0 : 1) }
|
||||
' "$ngc"
|
||||
}
|
||||
|
||||
classify_program() {
|
||||
local rel="$1"
|
||||
local ngc="$2"
|
||||
if [[ "$rel" == */remap_subs/* || "$rel" == */nc_subroutines/* ]]; then
|
||||
printf 'remap_subroutine\n'
|
||||
elif [[ "$rel" == */macros/* || "$rel" == */lathe_configs/* ]]; then
|
||||
printf 'macro_load\n'
|
||||
elif has_program_end "$ngc"; then
|
||||
printf 'main\n'
|
||||
else
|
||||
printf 'macro_load\n'
|
||||
fi
|
||||
}
|
||||
|
||||
prepare_input() {
|
||||
local class="$1"
|
||||
local ngc="$2"
|
||||
local wrapped="$3"
|
||||
if [[ "$class" == "main" ]]; then
|
||||
printf '%s\n' "$ngc"
|
||||
return 0
|
||||
fi
|
||||
cp "$ngc" "$wrapped"
|
||||
printf '\nM2\n' >> "$wrapped"
|
||||
printf '%s\n' "$wrapped"
|
||||
}
|
||||
|
||||
known_expected_failure() {
|
||||
local rel="$1"
|
||||
local combined="$2"
|
||||
case "$rel" in
|
||||
gmoccapy/*)
|
||||
[[ "$combined" == *"python/toplevel.py"* ]] && { printf 'python-remap-runtime-edge\n'; return 0; }
|
||||
;;
|
||||
axis/laser/*)
|
||||
[[ "$combined" == *"python/toplevel.py"* ]] && { printf 'python-remap-runtime-edge\n'; return 0; }
|
||||
;;
|
||||
axis/external_offsets/dyn_demo.ngc|axis/external_offsets/eoffsets.ngc|axis/external_offsets/jwp_z.ngc|axis/external_offsets/opa_demo.ngc)
|
||||
[[ "$combined" == *"Unknown m code used: M111"* ]] && { printf 'user-m-code-M111\n'; return 0; }
|
||||
;;
|
||||
axis/geometry/xyzc.ngc)
|
||||
[[ "$combined" == *"Unknown m code used: M110"* ]] && { printf 'user-m-code-M110\n'; return 0; }
|
||||
;;
|
||||
axis/foam/foam.ngc)
|
||||
[[ "$combined" == *"Bad character 'u' used"* ]] && { printf 'ini-axis-mask-UV\n'; return 0; }
|
||||
;;
|
||||
axis/vismach/5axis/bridgemill/5axisgui.ngc)
|
||||
[[ "$combined" == *"Bad character 'w' used"* ]] && { printf 'ini-axis-mask-W\n'; return 0; }
|
||||
;;
|
||||
axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_g533.ngc)
|
||||
[[ "$combined" == *"Cannot use axis values without a g code that uses them"* ]] && { printf 'upstream-demo-missing-motion-gcode\n'; return 0; }
|
||||
;;
|
||||
axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/*)
|
||||
[[ "$combined" == *"python/toplevel.py"* ]] && { printf 'python-remap-runtime-edge\n'; return 0; }
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
summarize_text() {
|
||||
local file="$1"
|
||||
if [[ ! -f "$file" ]]; then
|
||||
return 0
|
||||
fi
|
||||
tr '\n\t' ' ' < "$file" | sed -E 's/[[:space:]]+/ /g; s/^ //; s/ $//' | cut -c 1-260
|
||||
}
|
||||
|
||||
total=0
|
||||
pass=0
|
||||
fail=0
|
||||
timeout_count=0
|
||||
skip=0
|
||||
expected_fail=0
|
||||
unexpected_fail=0
|
||||
|
||||
while IFS= read -r ngc; do
|
||||
rel="$(relpath "$ngc")"
|
||||
if [[ -n "$ONLY_FILTER" && "$rel" != *"$ONLY_FILTER"* ]]; then
|
||||
continue
|
||||
fi
|
||||
if [[ "$rel" == */python/*.ngc ]]; then
|
||||
printf '%s\tunsupported_runtime_edge\tpython-ngc-helper\n' "$rel" >> "$BUILD_DIR/skipped.tsv"
|
||||
skip=$((skip + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
ini="$(find_sim_ini "$rel" "$(dirname "$ngc")" || true)"
|
||||
if [[ -z "$ini" ]]; then
|
||||
printf '%s\tunsupported_runtime_edge\tmissing-ini\n' "$rel" >> "$BUILD_DIR/skipped.tsv"
|
||||
skip=$((skip + 1))
|
||||
continue
|
||||
fi
|
||||
tbl="$(find_nearest_tbl "$(dirname "$ngc")" "$ini" || true)"
|
||||
if [[ -z "$tbl" ]]; then
|
||||
printf '%s\tunsupported_runtime_edge\tmissing-tool-table\n' "$rel" >> "$BUILD_DIR/skipped.tsv"
|
||||
skip=$((skip + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
total=$((total + 1))
|
||||
class="$(classify_program "$rel" "$ngc")"
|
||||
safe="$(safe_name "$rel")"
|
||||
wrapped="$BUILD_DIR/wrapped/$safe"
|
||||
input="$(prepare_input "$class" "$ngc" "$wrapped")"
|
||||
out_file="$BUILD_DIR/out/$safe.out"
|
||||
stdout_file="$BUILD_DIR/logs/$safe.stdout"
|
||||
stderr_file="$BUILD_DIR/logs/$safe.stderr"
|
||||
param_file="$BUILD_DIR/params/$safe.var"
|
||||
copy_parameter_file "$ini" "$param_file"
|
||||
|
||||
start_time="$(date +%s)"
|
||||
set +e
|
||||
(
|
||||
cd "$(dirname "$ini")"
|
||||
INI_FILE_NAME="$ini" timeout "$TIMEOUT_SECONDS" "$RS274" \
|
||||
-g \
|
||||
-i "$(basename "$ini")" \
|
||||
-t "$tbl" \
|
||||
-v "$param_file" \
|
||||
"$input" \
|
||||
"$out_file"
|
||||
) >"$stdout_file" 2>"$stderr_file"
|
||||
rc=$?
|
||||
set -e
|
||||
end_time="$(date +%s)"
|
||||
seconds=$((end_time - start_time))
|
||||
|
||||
status="FAIL"
|
||||
if [[ "$rc" -eq 0 ]]; then
|
||||
status="PASS"
|
||||
pass=$((pass + 1))
|
||||
elif [[ "$rc" -eq 124 || "$rc" -eq 137 ]]; then
|
||||
status="TIMEOUT"
|
||||
timeout_count=$((timeout_count + 1))
|
||||
else
|
||||
fail=$((fail + 1))
|
||||
fi
|
||||
|
||||
combined="$(cat "$stdout_file" "$stderr_file" 2>/dev/null || true)"
|
||||
expected=""
|
||||
if [[ "$status" != "PASS" ]]; then
|
||||
expected="$(known_expected_failure "$rel" "$combined" || true)"
|
||||
if [[ -n "$expected" ]]; then
|
||||
expected_fail=$((expected_fail + 1))
|
||||
else
|
||||
unexpected_fail=$((unexpected_fail + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
output_lines=0
|
||||
[[ -f "$out_file" ]] && output_lines="$(wc -l < "$out_file" | tr -d '[:space:]')"
|
||||
stderr_summary="$(summarize_text "$stderr_file")"
|
||||
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
|
||||
"$rel" \
|
||||
"$class" \
|
||||
"$status" \
|
||||
"$expected" \
|
||||
"$rc" \
|
||||
"$seconds" \
|
||||
"$(relpath "$ini")" \
|
||||
"$(relpath "$tbl")" \
|
||||
"$output_lines" \
|
||||
"$stderr_summary" >> "$SUMMARY_FILE"
|
||||
done < <(find "$SIM_DIR" -type f -name '*.ngc' | sort)
|
||||
|
||||
{
|
||||
printf 'sim config harness summary\n'
|
||||
printf 'summary: %s\n' "$SUMMARY_FILE"
|
||||
printf 'total: %s\n' "$total"
|
||||
printf 'pass: %s\n' "$pass"
|
||||
printf 'fail: %s\n' "$fail"
|
||||
printf 'timeout: %s\n' "$timeout_count"
|
||||
printf 'expected_fail: %s\n' "$expected_fail"
|
||||
printf 'unexpected_fail: %s\n' "$unexpected_fail"
|
||||
printf 'skipped: %s\n' "$skip"
|
||||
} | tee "$BUILD_DIR/summary.txt"
|
||||
|
||||
if [[ "$unexpected_fail" -ne 0 ]]; then
|
||||
echo "unexpected sim-config failures:" >&2
|
||||
awk -F '\t' 'NR > 1 && $3 != "PASS" && $4 == "" { print $1 "\t" $3 "\t" $10 }' "$SUMMARY_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
File diff suppressed because it is too large
Load Diff
108
wasm-port/tests/wasm/node/verify_nc_files_wasm.mjs
Normal file
108
wasm-port/tests/wasm/node/verify_nc_files_wasm.mjs
Normal file
@@ -0,0 +1,108 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import { createLinuxCncInterpSdk } from "../../../runtime/sdk/src/index.js";
|
||||
|
||||
function verifyExpectedOutput(fixtureName, output, expectedText) {
|
||||
const expectedLines = expectedText.split("\n").filter(Boolean);
|
||||
|
||||
for (const expectedLine of expectedLines) {
|
||||
if (expectedLine.startsWith("absent=")) {
|
||||
const forbidden = expectedLine.slice("absent=".length);
|
||||
assert.equal(
|
||||
output.includes(forbidden),
|
||||
false,
|
||||
`${fixtureName}: unexpected ${forbidden}`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
assert.equal(
|
||||
output.includes(expectedLine),
|
||||
true,
|
||||
`${fixtureName}: ${expectedLine}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const rootDir = resolve(__dirname, "../../..");
|
||||
const wasmPath = resolve(rootDir, "build/wasm/core/linuxcnc_interp.wasm");
|
||||
const ncFilesDir = resolve(rootDir, "vendor/linuxcnc/nc_files");
|
||||
|
||||
const interp = await createLinuxCncInterpSdk({
|
||||
wasmBinary: readFileSync(wasmPath),
|
||||
print() {},
|
||||
printErr(message) {
|
||||
console.error(message);
|
||||
},
|
||||
});
|
||||
|
||||
function runVendorNcFile(filename) {
|
||||
const wasmPath = `/work/nc-files/${filename}`;
|
||||
interp.writeTextFile(wasmPath, readFileSync(resolve(ncFilesDir, filename), "utf8"));
|
||||
return interp.runFile(wasmPath);
|
||||
}
|
||||
|
||||
verifyExpectedOutput(
|
||||
"nc_files_arcspiral_wasm",
|
||||
runVendorNcFile("arcspiral.ngc"),
|
||||
[
|
||||
"file_open=0",
|
||||
"file_read_count=1008",
|
||||
"file_execute_count=1008",
|
||||
"file_saw_error=0",
|
||||
"canon_event=STRAIGHT_TRAVERSE line=3 x=0 y=0 z=1",
|
||||
"canon_event=STRAIGHT_FEED line=6 x=1.72464 y=-1.01273 z=-0.1",
|
||||
"canon_event=PROGRAM_END",
|
||||
"absent=file_error_text=",
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
verifyExpectedOutput(
|
||||
"nc_files_hole_circle_wasm",
|
||||
runVendorNcFile("hole-circle.ngc"),
|
||||
[
|
||||
"file_open=0",
|
||||
"file_read_count=12",
|
||||
"file_execute_count=12",
|
||||
"file_saw_error=0",
|
||||
"canon_event=STRAIGHT_TRAVERSE line=7 x=1.5 y=0 z=0",
|
||||
"canon_event=STRAIGHT_FEED line=10 x=0.75 y=1.29904 z=-0.4",
|
||||
"canon_event=PROGRAM_END",
|
||||
"absent=file_error_text=",
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
verifyExpectedOutput(
|
||||
"nc_files_factorial_wasm",
|
||||
runVendorNcFile("factorial.ngc"),
|
||||
[
|
||||
"file_open=0",
|
||||
"file_read_count=11",
|
||||
"file_execute_count=11",
|
||||
"file_saw_error=0",
|
||||
"canon_event=PROGRAM_END",
|
||||
"absent=file_error_text=",
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
verifyExpectedOutput(
|
||||
"nc_files_m6demo_wasm",
|
||||
runVendorNcFile("m6demo.ngc"),
|
||||
[
|
||||
"file_open=0",
|
||||
"file_read_count=88",
|
||||
"file_execute_count=88",
|
||||
"file_saw_error=0",
|
||||
"canon_event=SET_G5X_OFFSET index=1",
|
||||
"canon_event=STOP_SPINDLE_TURNING spindle=0",
|
||||
"canon_event=PROGRAM_END",
|
||||
"absent=file_error_text=",
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
console.log("nc_files_wasm_node_smoke=ok");
|
||||
10
wasm-port/tests/wasm/node/verify_nc_files_wasm.sh
Executable file
10
wasm-port/tests/wasm/node/verify_nc_files_wasm.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||
|
||||
if [[ "${SKIP_INTERP_BUILD:-0}" != "1" ]]; then
|
||||
"$ROOT_DIR/tools/build_wasm_core.sh"
|
||||
fi
|
||||
|
||||
node "$ROOT_DIR/tests/wasm/node/verify_nc_files_wasm.mjs"
|
||||
161
wasm-port/tests/wasm/node/verify_sim_configs_wasm.mjs
Normal file
161
wasm-port/tests/wasm/node/verify_sim_configs_wasm.mjs
Normal file
@@ -0,0 +1,161 @@
|
||||
import { readFileSync, statSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import { createLinuxCncInterpSdk } from "../../../runtime/sdk/src/index.js";
|
||||
|
||||
function verifyExpectedOutput(fixtureName, output, expectedText) {
|
||||
const expectedLines = expectedText.split("\n").filter(Boolean);
|
||||
|
||||
for (const expectedLine of expectedLines) {
|
||||
if (expectedLine.startsWith("absent=")) {
|
||||
const forbidden = expectedLine.slice("absent=".length);
|
||||
assert.equal(
|
||||
output.includes(forbidden),
|
||||
false,
|
||||
`${fixtureName}: unexpected ${forbidden}`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
assert.equal(
|
||||
output.includes(expectedLine),
|
||||
true,
|
||||
`${fixtureName}: ${expectedLine}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const rootDir = resolve(__dirname, "../../..");
|
||||
const wasmPath = resolve(rootDir, "build/wasm/core/linuxcnc_interp.wasm");
|
||||
const vendorRoot = resolve(rootDir, "vendor/linuxcnc");
|
||||
|
||||
const interp = await createLinuxCncInterpSdk({
|
||||
wasmBinary: readFileSync(wasmPath),
|
||||
print() {},
|
||||
printErr(message) {
|
||||
console.error(message);
|
||||
},
|
||||
});
|
||||
|
||||
function vendorFile(sourceRel, wasmPath) {
|
||||
const sourcePath = resolve(vendorRoot, sourceRel);
|
||||
return {
|
||||
path: wasmPath,
|
||||
text: readFileSync(sourcePath, "utf8"),
|
||||
executable: (statSync(sourcePath).mode & 0o111) !== 0,
|
||||
};
|
||||
}
|
||||
|
||||
function simMachine(machineRel, files) {
|
||||
const wasmDir = `/work/sim/${machineRel}`;
|
||||
return {
|
||||
wasmDir,
|
||||
files: files.map((file) =>
|
||||
vendorFile(`configs/sim/${machineRel}/${file}`, `${wasmDir}/${file}`),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
const foam = simMachine("axis/foam", [
|
||||
"axis_foam.ini",
|
||||
"foam.ngc",
|
||||
]);
|
||||
verifyExpectedOutput(
|
||||
"sim_axis_foam_uv_wasm",
|
||||
interp.runSimConfigProgram({
|
||||
files: foam.files,
|
||||
programPath: `${foam.wasmDir}/foam.ngc`,
|
||||
iniPath: `${foam.wasmDir}/axis_foam.ini`,
|
||||
}),
|
||||
[
|
||||
"file_open=0",
|
||||
"file_saw_error=0",
|
||||
"canon_event=PROGRAM_END",
|
||||
"absent=Bad character 'u' used",
|
||||
"absent=Bad character 'v' used",
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
const bridgeMill = simMachine("axis/vismach/5axis/bridgemill", [
|
||||
"5axis.ini",
|
||||
"5axis.tbl",
|
||||
"5axisgui.ngc",
|
||||
"remap_subs/428remap.ngc",
|
||||
"remap_subs/429remap.ngc",
|
||||
"remap_subs/430remap.ngc",
|
||||
]);
|
||||
verifyExpectedOutput(
|
||||
"sim_axis_bridgemill_w_wasm",
|
||||
interp.runSimConfigProgram({
|
||||
files: bridgeMill.files,
|
||||
programPath: `${bridgeMill.wasmDir}/5axisgui.ngc`,
|
||||
iniPath: `${bridgeMill.wasmDir}/5axis.ini`,
|
||||
executionMode: "fiveAxisRemap",
|
||||
}),
|
||||
[
|
||||
"fiveaxis_ini_open=1",
|
||||
"fiveaxis_tool_table_load=0",
|
||||
"fiveaxis_parse_remap_1=0",
|
||||
"fiveaxis_parse_remap_2=0",
|
||||
"fiveaxis_parse_remap_3=0",
|
||||
"fiveaxis_parsed_remap_count=3",
|
||||
"fiveaxis_remaps_ready=1",
|
||||
"fiveaxis_file_open=0",
|
||||
"fiveaxis_file_read_count=2197",
|
||||
"fiveaxis_file_execute_count=2197",
|
||||
"fiveaxis_file_finish_count=137",
|
||||
"fiveaxis_file_reached_exit=1",
|
||||
"fiveaxis_hal_switchkins: rc=0 found=1 value=0",
|
||||
"fiveaxis_linuxcnc_remap_file_execute=1",
|
||||
"absent=Bad character 'w' used",
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
const geometry = simMachine("axis/geometry", [
|
||||
"M110",
|
||||
"xyzc.ini",
|
||||
"xyzc.ngc",
|
||||
]);
|
||||
verifyExpectedOutput(
|
||||
"sim_axis_geometry_xyzc_user_m110_wasm",
|
||||
interp.runSimConfigProgram({
|
||||
files: geometry.files,
|
||||
programPath: `${geometry.wasmDir}/xyzc.ngc`,
|
||||
iniPath: `${geometry.wasmDir}/xyzc.ini`,
|
||||
}),
|
||||
[
|
||||
"file_open=0",
|
||||
"file_saw_error=0",
|
||||
"canon_event=USER_M_COMMAND code=M110",
|
||||
"canon_event=PROGRAM_END",
|
||||
"absent=Unknown m code used: M110",
|
||||
"absent=Bad character 'c' used",
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
const externalOffsets = simMachine("axis/external_offsets", [
|
||||
"M111",
|
||||
"dyn_demo.ngc",
|
||||
"dynamic_offsets.ini",
|
||||
]);
|
||||
verifyExpectedOutput(
|
||||
"sim_axis_external_offsets_user_m111_wasm",
|
||||
interp.runSimConfigProgram({
|
||||
files: externalOffsets.files,
|
||||
programPath: `${externalOffsets.wasmDir}/dyn_demo.ngc`,
|
||||
iniPath: `${externalOffsets.wasmDir}/dynamic_offsets.ini`,
|
||||
}),
|
||||
[
|
||||
"file_open=0",
|
||||
"file_saw_error=0",
|
||||
"canon_event=USER_M_COMMAND code=M111",
|
||||
"canon_event=PROGRAM_END",
|
||||
"absent=Unknown m code used: M111",
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
console.log("sim_configs_wasm_node_smoke=ok");
|
||||
10
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
Executable file
10
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||
|
||||
if [[ "${SKIP_INTERP_BUILD:-0}" != "1" ]]; then
|
||||
"$ROOT_DIR/tools/build_wasm_core.sh"
|
||||
fi
|
||||
|
||||
node "$ROOT_DIR/tests/wasm/node/verify_sim_configs_wasm.mjs"
|
||||
@@ -9,11 +9,116 @@ SHIM_DIR="$ROOT_DIR/runtime/core/shims"
|
||||
INCLUDE_DIR="$ROOT_DIR/runtime/core/include"
|
||||
SOURCE_PROBE_MAP="$BUILD_DIR/source-probes.tsv"
|
||||
MINIMAL_GCODE_FIXTURE="$ROOT_DIR/tests/fixtures/gcode/minimal_linear.ngc"
|
||||
DO_WHILE_BREAK_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/do-while-break/test.ngc"
|
||||
OWORD_BUG315_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/oword-bug315/test.ngc"
|
||||
OWORD_BUG315_P2_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/oword-bug315-p2/test.ngc"
|
||||
EXISTS_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/exists/test.ngc"
|
||||
RETURN_VALUE_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/return-value/test.ngc"
|
||||
SUBS_FOLLOW_MAIN_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/subs-follow-main/test.ngc"
|
||||
FRACTIONAL_LINENUMBERS_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/fractional-linenumbers/test.ngc"
|
||||
NAMEDPARAM_BUG424_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/namedparam-bug424/test.ngc"
|
||||
G6164_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/g6164/test.ngc"
|
||||
ROTATION_ABS_PTS_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/rotation/abs-pts/test.ngc"
|
||||
ROTATION_G28_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/rotation/g28/g28.ngc"
|
||||
ROTATION_G53_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/rotation/g53/g53.ngc"
|
||||
INIPARAM_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/iniparam/test.ngc"
|
||||
INIPARAM_INI="$ROOT_DIR/vendor/linuxcnc/tests/interp/iniparam/test.ini"
|
||||
INIPARAM_FAILASSIGN_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/iniparam-failassign/test.ngc"
|
||||
INIPARAM_FAILASSIGN_INI="$ROOT_DIR/vendor/linuxcnc/tests/interp/iniparam-failassign/test.ini"
|
||||
SUB_CALL_FROM_SUB_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/sub-call-from-sub/test.ngc"
|
||||
SUB_CALL_FROM_SUB_INI="$ROOT_DIR/vendor/linuxcnc/tests/interp/sub-call-from-sub/test.ini"
|
||||
SEQUENCE_NUMBER_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/sequence-number/test.ngc"
|
||||
SEQUENCE_NUMBER_INI="$ROOT_DIR/vendor/linuxcnc/tests/interp/sequence-number/test.ini"
|
||||
NESTED_SUB_ERROR_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/nested-sub-error/test.ngc"
|
||||
NESTED_SUB_ERROR_INI="$ROOT_DIR/vendor/linuxcnc/tests/interp/nested-sub-error/test.ini"
|
||||
NESTED_SUB_IN_FILE_ERROR_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/test.ngc"
|
||||
NESTED_SUB_IN_FILE_ERROR_INI="$ROOT_DIR/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/test.ini"
|
||||
OWORD_UNWIND_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/oword-unwind/test.ngc"
|
||||
OWORD_UNWIND_INI="$ROOT_DIR/vendor/linuxcnc/tests/interp/oword-unwind/test.ini"
|
||||
ABORT_HOT_COMMENT_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/abort-hot-comment/test.ngc"
|
||||
ABORT_HOT_COMMENT_INI="$ROOT_DIR/vendor/linuxcnc/tests/interp/abort-hot-comment/test.ini"
|
||||
M19_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/m19/test.ngc"
|
||||
M19_INI="$ROOT_DIR/vendor/linuxcnc/tests/interp/m19/test.ini"
|
||||
MAGIC_COMMENTS_PARAM_FORMAT_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/magic_comments/param_format_printing/test.ngc"
|
||||
M98M99_01_BASICS_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/m98m99/01-basics/test.ngc"
|
||||
M98M99_02_VARIABLES_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/m98m99/02-variables/test.ngc"
|
||||
M98M99_07_NESTED_SUBS_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/m98m99/07-nested-subs/test.ngc"
|
||||
M98M99_08_SUB_FOLLOWS_MAIN_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/m98m99/08-sub-follows-main/test.ngc"
|
||||
M98M99_10_M98_P001_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/m98m99/10-M98-P001/test.ngc"
|
||||
M98M99_13_NAMED_PROGRAM_NAMED_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/m98m99/13-named-program/test-named.ngc"
|
||||
M98M99_13_NAMED_PROGRAM_NUMBERED_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/m98m99/13-named-program/test-numbered.ngc"
|
||||
M98M99_14_O_EXPRESSION_CALL_FIXTURE="$ROOT_DIR/vendor/linuxcnc/tests/interp/m98m99/14-o-expression-call/test.ngc"
|
||||
SIM_AXIS_FOAM_FIXTURE="$ROOT_DIR/../linuxcnc/configs/sim/axis/foam/foam.ngc"
|
||||
SIM_AXIS_FOAM_INI="$ROOT_DIR/../linuxcnc/configs/sim/axis/foam/axis_foam.ini"
|
||||
SIM_BRIDGEMILL_FIXTURE="$ROOT_DIR/../linuxcnc/configs/sim/axis/vismach/5axis/bridgemill/5axisgui.ngc"
|
||||
SIM_BRIDGEMILL_INI="$ROOT_DIR/../linuxcnc/configs/sim/axis/vismach/5axis/bridgemill/5axis.ini"
|
||||
SIM_GEOMETRY_XYZC_FIXTURE="$ROOT_DIR/../linuxcnc/configs/sim/axis/geometry/xyzc.ngc"
|
||||
SIM_GEOMETRY_XYZC_INI="$ROOT_DIR/../linuxcnc/configs/sim/axis/geometry/xyzc.ini"
|
||||
SIM_EXTERNAL_OFFSETS_DYN_FIXTURE="$ROOT_DIR/../linuxcnc/configs/sim/axis/external_offsets/dyn_demo.ngc"
|
||||
SIM_EXTERNAL_OFFSETS_DYN_INI="$ROOT_DIR/../linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini"
|
||||
NAMEDPARAM_INI_FIXTURE="$ROOT_DIR/tests/fixtures/ini/namedparams.ini"
|
||||
CXX="${CXX:-g++}"
|
||||
CC="${CC:-gcc}"
|
||||
CACHE_KEY_FILE="$BUILD_DIR/native-probes.input.sha256"
|
||||
CACHE_OK_FILE="$BUILD_DIR/native-probes.ok"
|
||||
CACHE_OUTPUT_MANIFEST="$BUILD_DIR/native-probes.outputs"
|
||||
NATIVE_PROBE_RUN_TIMEOUT_SECONDS="${NATIVE_PROBE_RUN_TIMEOUT_SECONDS:-60}"
|
||||
|
||||
mkdir -p "$BUILD_DIR"
|
||||
|
||||
hash_tree() {
|
||||
find "$@" -type f -print0 | sort -z | xargs -0 -r sha256sum
|
||||
}
|
||||
|
||||
native_input_fingerprint() {
|
||||
{
|
||||
printf 'CXX=%s\n' "$CXX"
|
||||
"$CXX" --version 2>/dev/null | sed -n '1p' || true
|
||||
printf 'CC=%s\n' "$CC"
|
||||
"$CC" --version 2>/dev/null | sed -n '1p' || true
|
||||
sha256sum \
|
||||
"$ROOT_DIR/tools/build_native_probes.sh" \
|
||||
"$ROOT_DIR/tools/source-manifest.txt"
|
||||
hash_tree \
|
||||
"$VENDOR_DIR" \
|
||||
"$WRAP_DIR" \
|
||||
"$SHIM_DIR" \
|
||||
"$INCLUDE_DIR" \
|
||||
"$ROOT_DIR/tests/fixtures"
|
||||
} | sha256sum | awk '{ print $1 }'
|
||||
}
|
||||
|
||||
cached_native_outputs_exist() {
|
||||
[[ -f "$CACHE_OUTPUT_MANIFEST" ]] || return 1
|
||||
[[ -s "$SOURCE_PROBE_MAP" ]] || return 1
|
||||
|
||||
local file
|
||||
while IFS= read -r file; do
|
||||
[[ -z "$file" ]] && continue
|
||||
[[ -f "$file" ]] || return 1
|
||||
done < "$CACHE_OUTPUT_MANIFEST"
|
||||
}
|
||||
|
||||
write_native_cache_stamp() {
|
||||
local key="$1"
|
||||
printf '%s\n' "$key" > "$CACHE_KEY_FILE"
|
||||
find "$BUILD_DIR" -maxdepth 1 -type f \
|
||||
! -name 'native-probes.input.sha256' \
|
||||
! -name 'native-probes.ok' \
|
||||
! -name 'native-probes.outputs' \
|
||||
-print | sort > "$CACHE_OUTPUT_MANIFEST"
|
||||
printf '%s\n' "$key" > "$CACHE_OK_FILE"
|
||||
}
|
||||
|
||||
NATIVE_INPUT_FINGERPRINT="$(native_input_fingerprint)"
|
||||
if [[ -f "$CACHE_KEY_FILE" && -f "$CACHE_OK_FILE" ]] &&
|
||||
[[ "$(tr -d '[:space:]' < "$CACHE_KEY_FILE")" == "$NATIVE_INPUT_FINGERPRINT" ]] &&
|
||||
[[ "$(tr -d '[:space:]' < "$CACHE_OK_FILE")" == "$NATIVE_INPUT_FINGERPRINT" ]] &&
|
||||
cached_native_outputs_exist; then
|
||||
echo "native probes up to date"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
: > "$SOURCE_PROBE_MAP"
|
||||
|
||||
COMMON_FLAGS=(
|
||||
@@ -145,6 +250,21 @@ object_needs_rebuild() {
|
||||
return 1
|
||||
}
|
||||
|
||||
shared_object_path() {
|
||||
local source="$1"
|
||||
shift
|
||||
|
||||
local base key
|
||||
base="$(basename "$source")"
|
||||
key="$(
|
||||
{
|
||||
printf 'source=%q\n' "$source"
|
||||
printf 'arg=%q\n' "$@"
|
||||
} | sha256sum | awk '{ print $1 }'
|
||||
)"
|
||||
printf '%s/obj/shared/%s-%s.o\n' "$BUILD_DIR" "${base%.*}" "$key"
|
||||
}
|
||||
|
||||
compile_object() {
|
||||
local target="$1"
|
||||
local source="$2"
|
||||
@@ -255,15 +375,13 @@ compile_target_objects() {
|
||||
local -n flags="$flags_name"
|
||||
local -n sources="$sources_name"
|
||||
local -n objs="$objs_name"
|
||||
local obj_dir="$BUILD_DIR/obj/$target"
|
||||
local status=0
|
||||
|
||||
objs=()
|
||||
local source
|
||||
for source in "${sources[@]}"; do
|
||||
local base
|
||||
base="$(basename "$source")"
|
||||
local obj="$obj_dir/${base%.*}.o"
|
||||
local obj
|
||||
obj="$(shared_object_path "$source" "${flags[@]}")"
|
||||
objs+=("$obj")
|
||||
if ! compile_object "$target" "$source" "$obj" "${flags[@]}"; then
|
||||
status=1
|
||||
@@ -347,6 +465,65 @@ build_c_object_target() {
|
||||
return "$status"
|
||||
}
|
||||
|
||||
run_command_needs_update() {
|
||||
local exitfile="$1"
|
||||
local stdout_log="$2"
|
||||
local stderr_log="$3"
|
||||
local cmdfile="$4"
|
||||
shift 4
|
||||
|
||||
[[ -f "$exitfile" && -f "$stdout_log" && -f "$stderr_log" ]] || return 0
|
||||
command_matches "$cmdfile" "$@" || return 0
|
||||
|
||||
local arg
|
||||
for arg in "$@"; do
|
||||
if [[ -f "$arg" && "$arg" -nt "$exitfile" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
run_logged_command() {
|
||||
local label="$1"
|
||||
shift
|
||||
|
||||
local exitfile="$BUILD_DIR/$label.run.exitcode"
|
||||
local stdout_log="$BUILD_DIR/$label.run.stdout.log"
|
||||
local stderr_log="$BUILD_DIR/$label.run.stderr.log"
|
||||
local cmdfile="$BUILD_DIR/$label.run.cmd"
|
||||
|
||||
if ! run_command_needs_update "$exitfile" "$stdout_log" "$stderr_log" "$cmdfile" "$@"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
set +e
|
||||
if command -v timeout >/dev/null 2>&1; then
|
||||
timeout "$NATIVE_PROBE_RUN_TIMEOUT_SECONDS" "$@" >"$stdout_log" 2>"$stderr_log"
|
||||
else
|
||||
"$@" >"$stdout_log" 2>"$stderr_log"
|
||||
fi
|
||||
local run_rc=$?
|
||||
set -e
|
||||
|
||||
if [[ "$run_rc" == "124" ]]; then
|
||||
printf 'run timed out after %s seconds\n' "$NATIVE_PROBE_RUN_TIMEOUT_SECONDS" >>"$stderr_log"
|
||||
fi
|
||||
|
||||
write_command_file "$cmdfile" "$@"
|
||||
echo "$run_rc" > "$exitfile"
|
||||
}
|
||||
|
||||
clear_logged_command() {
|
||||
local label="$1"
|
||||
rm -f \
|
||||
"$BUILD_DIR/$label.run.exitcode" \
|
||||
"$BUILD_DIR/$label.run.stdout.log" \
|
||||
"$BUILD_DIR/$label.run.stderr.log" \
|
||||
"$BUILD_DIR/$label.run.cmd"
|
||||
}
|
||||
|
||||
NO_LINK_FLAGS=()
|
||||
|
||||
INI_PROBE_SOURCES=(
|
||||
@@ -636,6 +813,7 @@ INTERP_CORE_SOURCES=(
|
||||
"$WRAP_DIR/linuxcnc_hal_adapter.cpp"
|
||||
"$WRAP_DIR/linuxcnc_emc_status_runtime.cpp"
|
||||
"$WRAP_DIR/linuxcnc_interp_edge_stubs.cpp"
|
||||
"$WRAP_DIR/linuxcnc_machine_config.cpp"
|
||||
"$WRAP_DIR/linuxcnc_runtime_state_stubs.cpp"
|
||||
"$WRAP_DIR/linuxcnc_tool_adapter.cpp"
|
||||
"$WRAP_DIR/linuxcnc_interp_minimal_runtime.cpp"
|
||||
@@ -690,6 +868,7 @@ REMAP_RUNTIME_CORE_SOURCES=(
|
||||
"$WRAP_DIR/linuxcnc_hal_adapter.cpp"
|
||||
"$WRAP_DIR/linuxcnc_emc_status_runtime.cpp"
|
||||
"$WRAP_DIR/linuxcnc_interp_python_edge_stubs.cpp"
|
||||
"$WRAP_DIR/linuxcnc_machine_config.cpp"
|
||||
"$WRAP_DIR/linuxcnc_runtime_state_stubs.cpp"
|
||||
"$WRAP_DIR/linuxcnc_tool_adapter.cpp"
|
||||
"$WRAP_DIR/linuxcnc_interp_minimal_runtime.cpp"
|
||||
@@ -711,6 +890,31 @@ FIVEAXIS_REMAP_EXECUTE_SOURCES=(
|
||||
"$WRAP_DIR/linuxcnc_5axis_remap_execute_harness.cpp"
|
||||
)
|
||||
|
||||
DUPLICATE_OWORD_REMAP_SOURCES=(
|
||||
"${REMAP_RUNTIME_CORE_SOURCES[@]}"
|
||||
"$WRAP_DIR/linuxcnc_duplicate_oword_remap_harness.cpp"
|
||||
)
|
||||
|
||||
if [[ "${NATIVE_PROBE_ONLY:-}" == "linuxcnc_duplicate_oword_remap_harness" ]]; then
|
||||
build_binary_target \
|
||||
linuxcnc_duplicate_oword_remap_harness \
|
||||
"$BUILD_DIR/linuxcnc_duplicate_oword_remap_harness" \
|
||||
REMAP_RUNTIME_FLAGS \
|
||||
DUPLICATE_OWORD_REMAP_SOURCES \
|
||||
MINIMAL_LINK_FLAGS
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_duplicate_oword_remap_harness.exitcode")" == "0" ]]; then
|
||||
run_logged_command \
|
||||
linuxcnc_duplicate_oword_remap_harness \
|
||||
"$BUILD_DIR/linuxcnc_duplicate_oword_remap_harness"
|
||||
else
|
||||
clear_logged_command linuxcnc_duplicate_oword_remap_harness
|
||||
fi
|
||||
|
||||
echo "native probe target complete: linuxcnc_duplicate_oword_remap_harness"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
build_binary_target \
|
||||
linuxcnc_ini_probe \
|
||||
"$BUILD_DIR/linuxcnc_ini_probe" \
|
||||
@@ -1190,18 +1394,11 @@ build_binary_target \
|
||||
-lfmt
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_namedparam_harness.exitcode")" == "0" ]]; then
|
||||
set +e
|
||||
"$BUILD_DIR/linuxcnc_namedparam_harness" "$NAMEDPARAM_INI_FIXTURE" \
|
||||
>"$BUILD_DIR/linuxcnc_namedparam_harness.run.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_namedparam_harness.run.stderr.log"
|
||||
NAMEDPARAM_RUN_RC=$?
|
||||
set -e
|
||||
echo "$NAMEDPARAM_RUN_RC" > "$BUILD_DIR/linuxcnc_namedparam_harness.run.exitcode"
|
||||
run_logged_command \
|
||||
linuxcnc_namedparam_harness \
|
||||
"$BUILD_DIR/linuxcnc_namedparam_harness" "$NAMEDPARAM_INI_FIXTURE"
|
||||
else
|
||||
rm -f \
|
||||
"$BUILD_DIR/linuxcnc_namedparam_harness.run.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_namedparam_harness.run.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_namedparam_harness.run.stderr.log"
|
||||
clear_logged_command linuxcnc_namedparam_harness
|
||||
fi
|
||||
|
||||
build_binary_target \
|
||||
@@ -1213,20 +1410,90 @@ build_binary_target \
|
||||
-lfmt
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_interp_minimal_harness.exitcode")" == "0" ]]; then
|
||||
set +e
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" "$MINIMAL_GCODE_FIXTURE" \
|
||||
>"$BUILD_DIR/linuxcnc_interp_minimal_harness.run.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_interp_minimal_harness.run.stderr.log"
|
||||
INTERP_MIN_RUN_RC=$?
|
||||
set -e
|
||||
echo "$INTERP_MIN_RUN_RC" > "$BUILD_DIR/linuxcnc_interp_minimal_harness.run.exitcode"
|
||||
run_logged_command \
|
||||
linuxcnc_interp_minimal_harness \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" "$MINIMAL_GCODE_FIXTURE"
|
||||
else
|
||||
rm -f \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness.run.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness.run.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness.run.stderr.log"
|
||||
clear_logged_command linuxcnc_interp_minimal_harness
|
||||
fi
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_interp_minimal_harness.exitcode")" == "0" ]]; then
|
||||
run_logged_command \
|
||||
linuxcnc_interp_minimal_harness.do_while_break \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" "$DO_WHILE_BREAK_FIXTURE"
|
||||
else
|
||||
clear_logged_command linuxcnc_interp_minimal_harness.do_while_break
|
||||
fi
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_interp_minimal_harness.exitcode")" == "0" ]]; then
|
||||
run_logged_command \
|
||||
linuxcnc_interp_minimal_harness.oword_bug315 \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" "$OWORD_BUG315_FIXTURE"
|
||||
else
|
||||
clear_logged_command linuxcnc_interp_minimal_harness.oword_bug315
|
||||
fi
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_interp_minimal_harness.exitcode")" == "0" ]]; then
|
||||
run_logged_command \
|
||||
linuxcnc_interp_minimal_harness.oword_bug315_p2 \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" "$OWORD_BUG315_P2_FIXTURE"
|
||||
else
|
||||
clear_logged_command linuxcnc_interp_minimal_harness.oword_bug315_p2
|
||||
fi
|
||||
|
||||
run_interp_minimal_fixture() {
|
||||
local label="$1"
|
||||
local fixture="$2"
|
||||
local ini="${3:-}"
|
||||
local mode="${4:-}"
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_interp_minimal_harness.exitcode")" == "0" ]]; then
|
||||
if [[ "$mode" == "continue_on_error" ]]; then
|
||||
run_logged_command \
|
||||
"linuxcnc_interp_minimal_harness.$label" \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" --continue-on-error "$fixture" "$ini"
|
||||
else
|
||||
run_logged_command \
|
||||
"linuxcnc_interp_minimal_harness.$label" \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" "$fixture" "$ini"
|
||||
fi
|
||||
else
|
||||
clear_logged_command "linuxcnc_interp_minimal_harness.$label"
|
||||
fi
|
||||
}
|
||||
|
||||
run_interp_minimal_fixture interp_exists "$EXISTS_FIXTURE"
|
||||
run_interp_minimal_fixture return_value "$RETURN_VALUE_FIXTURE"
|
||||
run_interp_minimal_fixture subs_follow_main "$SUBS_FOLLOW_MAIN_FIXTURE"
|
||||
run_interp_minimal_fixture fractional_linenumbers "$FRACTIONAL_LINENUMBERS_FIXTURE"
|
||||
run_interp_minimal_fixture namedparam_bug424 "$NAMEDPARAM_BUG424_FIXTURE"
|
||||
run_interp_minimal_fixture g6164 "$G6164_FIXTURE"
|
||||
run_interp_minimal_fixture rotation_abs_pts "$ROTATION_ABS_PTS_FIXTURE"
|
||||
run_interp_minimal_fixture rotation_g28 "$ROTATION_G28_FIXTURE"
|
||||
run_interp_minimal_fixture rotation_g53 "$ROTATION_G53_FIXTURE"
|
||||
run_interp_minimal_fixture iniparam "$INIPARAM_FIXTURE" "$INIPARAM_INI" continue_on_error
|
||||
run_interp_minimal_fixture iniparam_failassign "$INIPARAM_FAILASSIGN_FIXTURE" "$INIPARAM_FAILASSIGN_INI"
|
||||
run_interp_minimal_fixture sub_call_from_sub "$SUB_CALL_FROM_SUB_FIXTURE" "$SUB_CALL_FROM_SUB_INI"
|
||||
run_interp_minimal_fixture sequence_number "$SEQUENCE_NUMBER_FIXTURE" "$SEQUENCE_NUMBER_INI"
|
||||
run_interp_minimal_fixture nested_sub_error "$NESTED_SUB_ERROR_FIXTURE" "$NESTED_SUB_ERROR_INI"
|
||||
run_interp_minimal_fixture nested_sub_in_file_error "$NESTED_SUB_IN_FILE_ERROR_FIXTURE" "$NESTED_SUB_IN_FILE_ERROR_INI"
|
||||
run_interp_minimal_fixture oword_unwind "$OWORD_UNWIND_FIXTURE" "$OWORD_UNWIND_INI" continue_on_error
|
||||
run_interp_minimal_fixture abort_hot_comment "$ABORT_HOT_COMMENT_FIXTURE" "$ABORT_HOT_COMMENT_INI" continue_on_error
|
||||
run_interp_minimal_fixture m19 "$M19_FIXTURE" "$M19_INI"
|
||||
run_interp_minimal_fixture magic_comments_param_format "$MAGIC_COMMENTS_PARAM_FORMAT_FIXTURE"
|
||||
run_interp_minimal_fixture m98m99_01_basics "$M98M99_01_BASICS_FIXTURE"
|
||||
run_interp_minimal_fixture m98m99_02_variables "$M98M99_02_VARIABLES_FIXTURE"
|
||||
run_interp_minimal_fixture m98m99_07_nested_subs "$M98M99_07_NESTED_SUBS_FIXTURE"
|
||||
run_interp_minimal_fixture m98m99_08_sub_follows_main "$M98M99_08_SUB_FOLLOWS_MAIN_FIXTURE"
|
||||
run_interp_minimal_fixture m98m99_10_m98_p001 "$M98M99_10_M98_P001_FIXTURE"
|
||||
run_interp_minimal_fixture m98m99_13_named_program_named "$M98M99_13_NAMED_PROGRAM_NAMED_FIXTURE"
|
||||
run_interp_minimal_fixture m98m99_13_named_program_numbered "$M98M99_13_NAMED_PROGRAM_NUMBERED_FIXTURE"
|
||||
run_interp_minimal_fixture m98m99_14_o_expression_call "$M98M99_14_O_EXPRESSION_CALL_FIXTURE"
|
||||
run_interp_minimal_fixture sim_axis_foam "$SIM_AXIS_FOAM_FIXTURE" "$SIM_AXIS_FOAM_INI" continue_on_error
|
||||
run_interp_minimal_fixture sim_bridgemill "$SIM_BRIDGEMILL_FIXTURE" "$SIM_BRIDGEMILL_INI" continue_on_error
|
||||
run_interp_minimal_fixture sim_geometry_xyzc "$SIM_GEOMETRY_XYZC_FIXTURE" "$SIM_GEOMETRY_XYZC_INI" continue_on_error
|
||||
run_interp_minimal_fixture sim_external_offsets_dyn "$SIM_EXTERNAL_OFFSETS_DYN_FIXTURE" "$SIM_EXTERNAL_OFFSETS_DYN_INI" continue_on_error
|
||||
|
||||
build_binary_target \
|
||||
linuxcnc_parameter_file_harness \
|
||||
"$BUILD_DIR/linuxcnc_parameter_file_harness" \
|
||||
@@ -1236,18 +1503,11 @@ build_binary_target \
|
||||
-lfmt
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_parameter_file_harness.exitcode")" == "0" ]]; then
|
||||
set +e
|
||||
"$BUILD_DIR/linuxcnc_parameter_file_harness" \
|
||||
>"$BUILD_DIR/linuxcnc_parameter_file_harness.run.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_parameter_file_harness.run.stderr.log"
|
||||
PARAMETER_FILE_RUN_RC=$?
|
||||
set -e
|
||||
echo "$PARAMETER_FILE_RUN_RC" > "$BUILD_DIR/linuxcnc_parameter_file_harness.run.exitcode"
|
||||
run_logged_command \
|
||||
linuxcnc_parameter_file_harness \
|
||||
"$BUILD_DIR/linuxcnc_parameter_file_harness"
|
||||
else
|
||||
rm -f \
|
||||
"$BUILD_DIR/linuxcnc_parameter_file_harness.run.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_parameter_file_harness.run.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_parameter_file_harness.run.stderr.log"
|
||||
clear_logged_command linuxcnc_parameter_file_harness
|
||||
fi
|
||||
|
||||
build_binary_target \
|
||||
@@ -1259,18 +1519,11 @@ build_binary_target \
|
||||
-lfmt
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_interp_init_harness.exitcode")" == "0" ]]; then
|
||||
set +e
|
||||
"$BUILD_DIR/linuxcnc_interp_init_harness" \
|
||||
>"$BUILD_DIR/linuxcnc_interp_init_harness.run.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_interp_init_harness.run.stderr.log"
|
||||
INTERP_INIT_RUN_RC=$?
|
||||
set -e
|
||||
echo "$INTERP_INIT_RUN_RC" > "$BUILD_DIR/linuxcnc_interp_init_harness.run.exitcode"
|
||||
run_logged_command \
|
||||
linuxcnc_interp_init_harness \
|
||||
"$BUILD_DIR/linuxcnc_interp_init_harness"
|
||||
else
|
||||
rm -f \
|
||||
"$BUILD_DIR/linuxcnc_interp_init_harness.run.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_interp_init_harness.run.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_interp_init_harness.run.stderr.log"
|
||||
clear_logged_command linuxcnc_interp_init_harness
|
||||
fi
|
||||
|
||||
build_binary_target \
|
||||
@@ -1282,18 +1535,11 @@ build_binary_target \
|
||||
-lfmt
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_remap_parse_harness.exitcode")" == "0" ]]; then
|
||||
set +e
|
||||
"$BUILD_DIR/linuxcnc_remap_parse_harness" \
|
||||
>"$BUILD_DIR/linuxcnc_remap_parse_harness.run.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_remap_parse_harness.run.stderr.log"
|
||||
REMAP_PARSE_RUN_RC=$?
|
||||
set -e
|
||||
echo "$REMAP_PARSE_RUN_RC" > "$BUILD_DIR/linuxcnc_remap_parse_harness.run.exitcode"
|
||||
run_logged_command \
|
||||
linuxcnc_remap_parse_harness \
|
||||
"$BUILD_DIR/linuxcnc_remap_parse_harness"
|
||||
else
|
||||
rm -f \
|
||||
"$BUILD_DIR/linuxcnc_remap_parse_harness.run.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_remap_parse_harness.run.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_remap_parse_harness.run.stderr.log"
|
||||
clear_logged_command linuxcnc_remap_parse_harness
|
||||
fi
|
||||
|
||||
build_binary_target \
|
||||
@@ -1304,18 +1550,11 @@ build_binary_target \
|
||||
MINIMAL_LINK_FLAGS
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_remap_hal_sync_harness.exitcode")" == "0" ]]; then
|
||||
set +e
|
||||
"$BUILD_DIR/linuxcnc_remap_hal_sync_harness" \
|
||||
>"$BUILD_DIR/linuxcnc_remap_hal_sync_harness.run.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_remap_hal_sync_harness.run.stderr.log"
|
||||
REMAP_HAL_SYNC_RUN_RC=$?
|
||||
set -e
|
||||
echo "$REMAP_HAL_SYNC_RUN_RC" > "$BUILD_DIR/linuxcnc_remap_hal_sync_harness.run.exitcode"
|
||||
run_logged_command \
|
||||
linuxcnc_remap_hal_sync_harness \
|
||||
"$BUILD_DIR/linuxcnc_remap_hal_sync_harness"
|
||||
else
|
||||
rm -f \
|
||||
"$BUILD_DIR/linuxcnc_remap_hal_sync_harness.run.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_remap_hal_sync_harness.run.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_remap_hal_sync_harness.run.stderr.log"
|
||||
clear_logged_command linuxcnc_remap_hal_sync_harness
|
||||
fi
|
||||
|
||||
build_binary_target \
|
||||
@@ -1326,18 +1565,26 @@ build_binary_target \
|
||||
MINIMAL_LINK_FLAGS
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_5axis_remap_execute_harness.exitcode")" == "0" ]]; then
|
||||
set +e
|
||||
"$BUILD_DIR/linuxcnc_5axis_remap_execute_harness" \
|
||||
>"$BUILD_DIR/linuxcnc_5axis_remap_execute_harness.run.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_5axis_remap_execute_harness.run.stderr.log"
|
||||
FIVEAXIS_REMAP_EXECUTE_RUN_RC=$?
|
||||
set -e
|
||||
echo "$FIVEAXIS_REMAP_EXECUTE_RUN_RC" > "$BUILD_DIR/linuxcnc_5axis_remap_execute_harness.run.exitcode"
|
||||
run_logged_command \
|
||||
linuxcnc_5axis_remap_execute_harness \
|
||||
"$BUILD_DIR/linuxcnc_5axis_remap_execute_harness"
|
||||
else
|
||||
rm -f \
|
||||
"$BUILD_DIR/linuxcnc_5axis_remap_execute_harness.run.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_5axis_remap_execute_harness.run.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_5axis_remap_execute_harness.run.stderr.log"
|
||||
clear_logged_command linuxcnc_5axis_remap_execute_harness
|
||||
fi
|
||||
|
||||
build_binary_target \
|
||||
linuxcnc_duplicate_oword_remap_harness \
|
||||
"$BUILD_DIR/linuxcnc_duplicate_oword_remap_harness" \
|
||||
REMAP_RUNTIME_FLAGS \
|
||||
DUPLICATE_OWORD_REMAP_SOURCES \
|
||||
MINIMAL_LINK_FLAGS
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_duplicate_oword_remap_harness.exitcode")" == "0" ]]; then
|
||||
run_logged_command \
|
||||
linuxcnc_duplicate_oword_remap_harness \
|
||||
"$BUILD_DIR/linuxcnc_duplicate_oword_remap_harness"
|
||||
else
|
||||
clear_logged_command linuxcnc_duplicate_oword_remap_harness
|
||||
fi
|
||||
|
||||
build_binary_target \
|
||||
@@ -1349,18 +1596,11 @@ build_binary_target \
|
||||
-lfmt
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_indexer_harness.exitcode")" == "0" ]]; then
|
||||
set +e
|
||||
"$BUILD_DIR/linuxcnc_indexer_harness" \
|
||||
>"$BUILD_DIR/linuxcnc_indexer_harness.run.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_indexer_harness.run.stderr.log"
|
||||
INDEXER_RUN_RC=$?
|
||||
set -e
|
||||
echo "$INDEXER_RUN_RC" > "$BUILD_DIR/linuxcnc_indexer_harness.run.exitcode"
|
||||
run_logged_command \
|
||||
linuxcnc_indexer_harness \
|
||||
"$BUILD_DIR/linuxcnc_indexer_harness"
|
||||
else
|
||||
rm -f \
|
||||
"$BUILD_DIR/linuxcnc_indexer_harness.run.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_indexer_harness.run.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_indexer_harness.run.stderr.log"
|
||||
clear_logged_command linuxcnc_indexer_harness
|
||||
fi
|
||||
|
||||
build_object_target \
|
||||
@@ -1639,4 +1879,5 @@ build_object_target \
|
||||
"$VENDOR_DIR/src/emc/tooldata/tooldata_common.cc" \
|
||||
MINIMAL_FLAGS
|
||||
|
||||
write_native_cache_stamp "$NATIVE_INPUT_FINGERPRINT"
|
||||
echo "native probes complete"
|
||||
|
||||
@@ -65,6 +65,7 @@ INTERP_CORE_SOURCES=(
|
||||
"$WRAP_DIR/linuxcnc_hal_adapter.cpp"
|
||||
"$WRAP_DIR/linuxcnc_emc_status_runtime.cpp"
|
||||
"$WRAP_DIR/linuxcnc_interp_python_edge_stubs.cpp"
|
||||
"$WRAP_DIR/linuxcnc_machine_config.cpp"
|
||||
"$WRAP_DIR/linuxcnc_runtime_state_stubs.cpp"
|
||||
"$WRAP_DIR/linuxcnc_tool_adapter.cpp"
|
||||
"$WRAP_DIR/linuxcnc_interp_minimal_runtime.cpp"
|
||||
@@ -97,5 +98,5 @@ link_wasm_module \
|
||||
-s STACK_SIZE=2MB \
|
||||
-s NO_EXIT_RUNTIME=1 \
|
||||
-s FORCE_FILESYSTEM=1 \
|
||||
-s EXPORTED_FUNCTIONS='["_malloc","_free","_lcinterp_run_program","_lcinterp_run_program_with_ini","_lcinterp_run_file","_lcinterp_run_file_with_ini","_lcinterp_run_fiveaxis_remap_file","_lcinterp_restore_parameters","_lcinterp_save_parameters","_lcinterp_load_tool_table","_lcinterp_load_tool_table_random","_lcinterp_save_tool_table","_lcinterp_probe_init_and_synch","_lcinterp_probe_indexer","_lcinterp_probe_named_parameters","_lcinterp_free_string"]' \
|
||||
-s EXPORTED_FUNCTIONS='["_malloc","_free","_lcinterp_run_program","_lcinterp_run_program_with_ini","_lcinterp_run_file","_lcinterp_run_file_with_ini","_lcinterp_run_file_with_ini_continue_on_error","_lcinterp_run_fiveaxis_remap_file","_lcinterp_run_remap_file","_lcinterp_run_remap_file_continue_on_error","_lcinterp_run_remap_io_mdi_sequence","_lcinterp_restore_parameters","_lcinterp_save_parameters","_lcinterp_load_tool_table","_lcinterp_load_tool_table_random","_lcinterp_save_tool_table","_lcinterp_probe_init_and_synch","_lcinterp_probe_indexer","_lcinterp_probe_named_parameters","_lcinterp_free_string"]' \
|
||||
-s EXPORTED_RUNTIME_METHODS='["FS","UTF8ToString","stringToUTF8","lengthBytesUTF8"]'
|
||||
|
||||
@@ -17,7 +17,13 @@ copy_file() {
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$dst")"
|
||||
cp "$src" "$dst"
|
||||
if [[ -f "$dst" ]] && cmp -s "$src" "$dst"; then
|
||||
touch -r "$src" "$dst"
|
||||
echo "unchanged $src_rel"
|
||||
return
|
||||
fi
|
||||
|
||||
cp -p "$src" "$dst"
|
||||
echo "copied $src_rel"
|
||||
}
|
||||
|
||||
|
||||
@@ -150,6 +150,210 @@ src/emc/rs274ngc/interp_remap.cc
|
||||
src/emc/rs274ngc/interp_convert.cc
|
||||
src/emc/rs274ngc/interp_cycles.cc
|
||||
src/emc/rs274ngc/interp_g7x.cc
|
||||
tests/remap/duplicate-o-word/README
|
||||
tests/remap/duplicate-o-word/expected
|
||||
tests/remap/duplicate-o-word/rm207.ngc
|
||||
tests/remap/duplicate-o-word/rm208.ngc
|
||||
tests/remap/duplicate-o-word/test.ini
|
||||
tests/remap/duplicate-o-word/test.ngc
|
||||
tests/remap/duplicate-o-word/test.sh
|
||||
tests/remap/fail/args.0/README
|
||||
tests/remap/fail/args.0/expected
|
||||
tests/remap/fail/args.0/rm400.ngc
|
||||
tests/remap/fail/args.0/test.ini
|
||||
tests/remap/fail/args.0/test.ngc
|
||||
tests/remap/fail/args.0/test.sh
|
||||
tests/remap/fail/args.1/README
|
||||
tests/remap/fail/args.1/expected
|
||||
tests/remap/fail/args.1/rm400.ngc
|
||||
tests/remap/fail/args.1/test.ini
|
||||
tests/remap/fail/args.1/test.ngc
|
||||
tests/remap/fail/args.1/test.sh
|
||||
tests/remap/fail/args.2/README
|
||||
tests/remap/fail/args.2/expected
|
||||
tests/remap/fail/args.2/rm400.ngc
|
||||
tests/remap/fail/args.2/test.ini
|
||||
tests/remap/fail/args.2/test.ngc
|
||||
tests/remap/fail/args.2/test.sh
|
||||
tests/remap/fail/body-ngc/README
|
||||
tests/remap/fail/body-ngc/expected
|
||||
tests/remap/fail/body-ngc/rm400.ngc
|
||||
tests/remap/fail/body-ngc/test.ini
|
||||
tests/remap/fail/body-ngc/test.ngc
|
||||
tests/remap/fail/body-ngc/test.sh
|
||||
tests/remap/m30-interaction/README
|
||||
tests/remap/m30-interaction/expected
|
||||
tests/remap/m30-interaction/rm400.ngc
|
||||
tests/remap/m30-interaction/test.ini
|
||||
tests/remap/m30-interaction/test.ngc
|
||||
tests/remap/m30-interaction/test.sh
|
||||
tests/remap/nested-remaps-oword/README
|
||||
tests/remap/nested-remaps-oword/expected
|
||||
tests/remap/nested-remaps-oword/rm400.ngc
|
||||
tests/remap/nested-remaps-oword/rm401.ngc
|
||||
tests/remap/nested-remaps-oword/rm402.ngc
|
||||
tests/remap/nested-remaps-oword/rm403.ngc
|
||||
tests/remap/nested-remaps-oword/test.ini
|
||||
tests/remap/nested-remaps-oword/test.ngc
|
||||
tests/remap/nested-remaps-oword/test.sh
|
||||
tests/remap/nested-remaps-oword/testsub.ngc
|
||||
tests/remap/posargs.0/README
|
||||
tests/remap/posargs.0/expected
|
||||
tests/remap/posargs.0/rg881.ngc
|
||||
tests/remap/posargs.0/test.ini
|
||||
tests/remap/posargs.0/test.ngc
|
||||
tests/remap/posargs.0/test.sh
|
||||
tests/remap/sequencing/README
|
||||
tests/remap/sequencing/expected
|
||||
tests/remap/sequencing/permute.py
|
||||
tests/remap/sequencing/rg881.ngc
|
||||
tests/remap/sequencing/rm405.ngc
|
||||
tests/remap/sequencing/rm406.ngc
|
||||
tests/remap/sequencing/rm407.ngc
|
||||
tests/remap/sequencing/rm408.ngc
|
||||
tests/remap/sequencing/rm409.ngc
|
||||
tests/remap/sequencing/rm410.ngc
|
||||
tests/remap/sequencing/test.ini
|
||||
tests/remap/sequencing/test.ngc
|
||||
tests/remap/sequencing/test.sh
|
||||
tests/remap/remap-io/README
|
||||
tests/remap/remap-io/expected
|
||||
tests/remap/remap-io/io_input_m66.ngc
|
||||
tests/remap/remap-io/io_output_m62.ngc
|
||||
tests/remap/remap-io/io_output_m63.ngc
|
||||
tests/remap/remap-io/io_output_m64.ngc
|
||||
tests/remap/remap-io/io_output_m65.ngc
|
||||
tests/remap/remap-io/io_output_m67.ngc
|
||||
tests/remap/remap-io/io_output_m68.ngc
|
||||
tests/remap/remap-io/test-ngc.ini
|
||||
tests/remap/remap-io/test.sh
|
||||
tests/interp/m98m99/01-basics/expected
|
||||
tests/interp/m98m99/01-basics/test.ngc
|
||||
tests/interp/m98m99/01-basics/test.sh
|
||||
tests/interp/m98m99/02-variables/expected
|
||||
tests/interp/m98m99/02-variables/test.ngc
|
||||
tests/interp/m98m99/02-variables/test.sh
|
||||
tests/interp/m98m99/07-nested-subs/expected
|
||||
tests/interp/m98m99/07-nested-subs/test.ngc
|
||||
tests/interp/m98m99/07-nested-subs/test.sh
|
||||
tests/interp/m98m99/08-sub-follows-main/expected
|
||||
tests/interp/m98m99/08-sub-follows-main/test.ngc
|
||||
tests/interp/m98m99/08-sub-follows-main/test.sh
|
||||
tests/interp/m98m99/10-M98-P001/expected
|
||||
tests/interp/m98m99/10-M98-P001/test.ngc
|
||||
tests/interp/m98m99/10-M98-P001/test.sh
|
||||
tests/interp/m98m99/13-named-program/expected
|
||||
tests/interp/m98m99/13-named-program/test-named.ngc
|
||||
tests/interp/m98m99/13-named-program/test-numbered.ngc
|
||||
tests/interp/m98m99/13-named-program/test.sh
|
||||
tests/interp/m98m99/14-o-expression-call/expected
|
||||
tests/interp/m98m99/14-o-expression-call/test.ngc
|
||||
tests/interp/m98m99/14-o-expression-call/test.sh
|
||||
tests/interp/do-while-break/README
|
||||
tests/interp/do-while-break/bug.ngc
|
||||
tests/interp/do-while-break/expected
|
||||
tests/interp/do-while-break/test.ngc
|
||||
tests/interp/do-while-break/test.sh
|
||||
tests/interp/oword-bug315/README
|
||||
tests/interp/oword-bug315/expected
|
||||
tests/interp/oword-bug315/test.ngc
|
||||
tests/interp/oword-bug315/test.sh
|
||||
tests/interp/oword-bug315-p2/README
|
||||
tests/interp/oword-bug315-p2/expected
|
||||
tests/interp/oword-bug315-p2/test.ngc
|
||||
tests/interp/oword-bug315-p2/test.sh
|
||||
tests/interp/exists/README
|
||||
tests/interp/exists/expected
|
||||
tests/interp/exists/test.ngc
|
||||
tests/interp/exists/test.sh
|
||||
tests/interp/return-value/expected
|
||||
tests/interp/return-value/test.ngc
|
||||
tests/interp/return-value/test.sh
|
||||
tests/interp/subs-follow-main/expected
|
||||
tests/interp/subs-follow-main/test.ngc
|
||||
tests/interp/subs-follow-main/test.sh
|
||||
tests/interp/fractional-linenumbers/README
|
||||
tests/interp/fractional-linenumbers/expected
|
||||
tests/interp/fractional-linenumbers/test.ngc
|
||||
tests/interp/fractional-linenumbers/test.sh
|
||||
tests/interp/namedparam-bug424/README
|
||||
tests/interp/namedparam-bug424/expected
|
||||
tests/interp/namedparam-bug424/test.ngc
|
||||
tests/interp/namedparam-bug424/test.sh
|
||||
tests/interp/g6164/expected
|
||||
tests/interp/g6164/test.ngc
|
||||
tests/interp/g6164/test.sh
|
||||
tests/interp/rotation/abs-pts/expected
|
||||
tests/interp/rotation/abs-pts/test.ngc
|
||||
tests/interp/rotation/abs-pts/test.sh
|
||||
tests/interp/rotation/abs-pts/test.tbl
|
||||
tests/interp/rotation/g28/expected
|
||||
tests/interp/rotation/g28/g28.ngc
|
||||
tests/interp/rotation/g28/test.sh
|
||||
tests/interp/rotation/g53/expected
|
||||
tests/interp/rotation/g53/g53.ngc
|
||||
tests/interp/rotation/g53/test.sh
|
||||
tests/interp/iniparam/README
|
||||
tests/interp/iniparam/expected
|
||||
tests/interp/iniparam/test.ini
|
||||
tests/interp/iniparam/test.ngc
|
||||
tests/interp/iniparam/test.sh
|
||||
tests/interp/iniparam-failassign/README
|
||||
tests/interp/iniparam-failassign/expected
|
||||
tests/interp/iniparam-failassign/test.ini
|
||||
tests/interp/iniparam-failassign/test.ngc
|
||||
tests/interp/iniparam-failassign/test.sh
|
||||
tests/interp/m19/README
|
||||
tests/interp/m19/expected
|
||||
tests/interp/m19/test.ini
|
||||
tests/interp/m19/test.ngc
|
||||
tests/interp/m19/test.sh
|
||||
tests/interp/magic_comments/param_format_printing/expected
|
||||
tests/interp/magic_comments/param_format_printing/test.ngc
|
||||
tests/interp/magic_comments/param_format_printing/test.sh
|
||||
tests/interp/sub-call-from-sub/expected
|
||||
tests/interp/sub-call-from-sub/subs/caller.ngc
|
||||
tests/interp/sub-call-from-sub/subs/helper.ngc
|
||||
tests/interp/sub-call-from-sub/test.ini
|
||||
tests/interp/sub-call-from-sub/test.ngc
|
||||
tests/interp/sub-call-from-sub/test.sh
|
||||
tests/interp/sequence-number/README
|
||||
tests/interp/sequence-number/expected
|
||||
tests/interp/sequence-number/rm400.ngc
|
||||
tests/interp/sequence-number/test.ini
|
||||
tests/interp/sequence-number/test.ngc
|
||||
tests/interp/sequence-number/test.sh
|
||||
tests/interp/nested-sub-error/expected
|
||||
tests/interp/nested-sub-error/subs/nested.ngc
|
||||
tests/interp/nested-sub-error/test.ini
|
||||
tests/interp/nested-sub-error/test.ngc
|
||||
tests/interp/nested-sub-error/test.sh
|
||||
tests/interp/nested-sub-in-file-error/expected
|
||||
tests/interp/nested-sub-in-file-error/subs/sequential.ngc
|
||||
tests/interp/nested-sub-in-file-error/test.ini
|
||||
tests/interp/nested-sub-in-file-error/test.ngc
|
||||
tests/interp/nested-sub-in-file-error/test.sh
|
||||
tests/interp/oword-unwind/README
|
||||
tests/interp/oword-unwind/expected
|
||||
tests/interp/oword-unwind/fail.ngc
|
||||
tests/interp/oword-unwind/test.ini
|
||||
tests/interp/oword-unwind/test.ngc
|
||||
tests/interp/oword-unwind/test.sh
|
||||
tests/interp/abort-hot-comment/README
|
||||
tests/interp/abort-hot-comment/expected
|
||||
tests/interp/abort-hot-comment/test.ini
|
||||
tests/interp/abort-hot-comment/test.ngc
|
||||
tests/interp/abort-hot-comment/test.sh
|
||||
configs/sim/axis/sim.tbl
|
||||
configs/sim/axis/external_offsets/M111
|
||||
configs/sim/axis/external_offsets/dyn_demo.ngc
|
||||
configs/sim/axis/external_offsets/dynamic_offsets.ini
|
||||
configs/sim/axis/external_offsets/eoffset.tbl
|
||||
configs/sim/axis/foam/axis_foam.ini
|
||||
configs/sim/axis/foam/foam.ngc
|
||||
configs/sim/axis/geometry/M110
|
||||
configs/sim/axis/geometry/xyzc.ini
|
||||
configs/sim/axis/geometry/xyzc.ngc
|
||||
configs/sim/axis/vismach/5axis/bridgemill/5axis.ini
|
||||
configs/sim/axis/vismach/5axis/bridgemill/5axis.tbl
|
||||
configs/sim/axis/vismach/5axis/bridgemill/5axis.xml
|
||||
@@ -199,3 +403,7 @@ configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini
|
||||
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.tbl
|
||||
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.txt
|
||||
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.xml
|
||||
nc_files/arcspiral.ngc
|
||||
nc_files/factorial.ngc
|
||||
nc_files/hole-circle.ngc
|
||||
nc_files/m6demo.ngc
|
||||
|
||||
@@ -7,6 +7,9 @@ GCODE_FIXTURE_DIR="$ROOT_DIR/tests/fixtures/gcode"
|
||||
CANON_FIXTURE_DIR="$ROOT_DIR/tests/fixtures/canon"
|
||||
GCODE_ERROR_FIXTURE_DIR="$ROOT_DIR/tests/fixtures/gcode_errors"
|
||||
CANON_ERROR_FIXTURE_DIR="$ROOT_DIR/tests/fixtures/canon_errors"
|
||||
BUILD_DIR="$ROOT_DIR/build/native"
|
||||
CACHE_KEY_FILE="$BUILD_DIR/native-linuxcnc-fixture-baseline.input.sha256"
|
||||
CACHE_OK_FILE="$BUILD_DIR/native-linuxcnc-fixture-baseline.ok"
|
||||
|
||||
FIXTURES=(
|
||||
minimal_linear
|
||||
@@ -56,6 +59,35 @@ if [[ ! -x "$UPSTREAM_RS274" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$BUILD_DIR"
|
||||
|
||||
hash_tree() {
|
||||
find "$@" -type f -print0 | sort -z | xargs -0 -r sha256sum
|
||||
}
|
||||
|
||||
fixture_baseline_fingerprint() {
|
||||
{
|
||||
sha256sum \
|
||||
"$ROOT_DIR/tools/verify_native_linuxcnc_fixture_baseline.sh" \
|
||||
"$UPSTREAM_RS274"
|
||||
"$UPSTREAM_RS274" --version 2>/dev/null || true
|
||||
hash_tree \
|
||||
"$GCODE_FIXTURE_DIR" \
|
||||
"$CANON_FIXTURE_DIR" \
|
||||
"$GCODE_ERROR_FIXTURE_DIR" \
|
||||
"$CANON_ERROR_FIXTURE_DIR" \
|
||||
"$ROOT_DIR/tests/fixtures/ini"
|
||||
} | sha256sum | awk '{ print $1 }'
|
||||
}
|
||||
|
||||
FIXTURE_BASELINE_FINGERPRINT="$(fixture_baseline_fingerprint)"
|
||||
if [[ -f "$CACHE_KEY_FILE" && -f "$CACHE_OK_FILE" ]] &&
|
||||
[[ "$(tr -d '[:space:]' < "$CACHE_KEY_FILE")" == "$FIXTURE_BASELINE_FINGERPRINT" ]] &&
|
||||
[[ "$(tr -d '[:space:]' < "$CACHE_OK_FILE")" == "$FIXTURE_BASELINE_FINGERPRINT" ]]; then
|
||||
echo "native LinuxCNC fixture baseline up to date"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TMP_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||
TOOL_TABLE_BASELINE="$TMP_DIR/tool_table_setup.tbl"
|
||||
@@ -967,4 +999,6 @@ for name in "${ERROR_FIXTURES[@]}"; do
|
||||
done < "$expected_file"
|
||||
done
|
||||
|
||||
printf '%s\n' "$FIXTURE_BASELINE_FINGERPRINT" > "$CACHE_KEY_FILE"
|
||||
printf '%s\n' "$FIXTURE_BASELINE_FINGERPRINT" > "$CACHE_OK_FILE"
|
||||
echo "native LinuxCNC fixture baseline validation complete"
|
||||
|
||||
@@ -5,6 +5,9 @@ ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
UPSTREAM_DIR="$ROOT_DIR/../linuxcnc"
|
||||
VENDOR_DIR="$ROOT_DIR/vendor/linuxcnc"
|
||||
MANIFEST_FILE="$ROOT_DIR/tools/source-manifest.txt"
|
||||
BUILD_DIR="$ROOT_DIR/build/native"
|
||||
CACHE_KEY_FILE="$BUILD_DIR/vendor-sync.input.sha256"
|
||||
CACHE_OK_FILE="$BUILD_DIR/vendor-sync.ok"
|
||||
|
||||
if [[ ! -d "$UPSTREAM_DIR" ]]; then
|
||||
echo "missing upstream directory: $UPSTREAM_DIR" >&2
|
||||
@@ -21,6 +24,36 @@ if [[ ! -f "$MANIFEST_FILE" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$BUILD_DIR"
|
||||
|
||||
vendor_sync_fingerprint() {
|
||||
{
|
||||
git -C "$UPSTREAM_DIR" rev-parse HEAD
|
||||
sha256sum \
|
||||
"$ROOT_DIR/tools/verify_vendor_sync.sh" \
|
||||
"$MANIFEST_FILE"
|
||||
while IFS= read -r src_rel; do
|
||||
[[ -z "$src_rel" ]] && continue
|
||||
[[ "${src_rel:0:1}" == "#" ]] && continue
|
||||
printf '%s\0' "$UPSTREAM_DIR/$src_rel"
|
||||
done < "$MANIFEST_FILE" | xargs -0 -r sha256sum 2>/dev/null || true
|
||||
while IFS= read -r src_rel; do
|
||||
[[ -z "$src_rel" ]] && continue
|
||||
[[ "${src_rel:0:1}" == "#" ]] && continue
|
||||
printf '%s\0' "$VENDOR_DIR/$src_rel"
|
||||
done < "$MANIFEST_FILE" | xargs -0 -r sha256sum 2>/dev/null || true
|
||||
find "$VENDOR_DIR" -type f -printf 'vendor-list:%P\n' | sort
|
||||
} | sha256sum | awk '{ print $1 }'
|
||||
}
|
||||
|
||||
VENDOR_SYNC_FINGERPRINT="$(vendor_sync_fingerprint)"
|
||||
if [[ -f "$CACHE_KEY_FILE" && -f "$CACHE_OK_FILE" ]] &&
|
||||
[[ "$(tr -d '[:space:]' < "$CACHE_KEY_FILE")" == "$VENDOR_SYNC_FINGERPRINT" ]] &&
|
||||
[[ "$(tr -d '[:space:]' < "$CACHE_OK_FILE")" == "$VENDOR_SYNC_FINGERPRINT" ]]; then
|
||||
echo "vendor sync up to date"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TMP_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||
|
||||
@@ -82,4 +115,6 @@ while IFS= read -r src_rel; do
|
||||
fi
|
||||
done < "$MANIFEST_SORTED"
|
||||
|
||||
printf '%s\n' "$VENDOR_SYNC_FINGERPRINT" > "$CACHE_KEY_FILE"
|
||||
printf '%s\n' "$VENDOR_SYNC_FINGERPRINT" > "$CACHE_OK_FILE"
|
||||
echo "vendor sync validation complete"
|
||||
|
||||
5
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/M111
vendored
Executable file
5
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/M111
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
halcmd setp axisui.notifications-clear-info 1
|
||||
sleep .1
|
||||
halcmd setp axisui.notifications-clear-info 0
|
||||
exit 0
|
||||
33
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/dyn_demo.ngc
vendored
Normal file
33
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/dyn_demo.ngc
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
#<xmax> = 9
|
||||
#<ymax> = 4
|
||||
#<zmax> = 3
|
||||
#<rct> = 100
|
||||
#<feed> = 100
|
||||
|
||||
#<x1> = #<xmax>
|
||||
#<y1> = 0
|
||||
#<z1> = [#<zmax> * 0.5]
|
||||
|
||||
#<x2> = #<xmax>
|
||||
#<y2> = #<ymax>
|
||||
#<z2> = 0
|
||||
|
||||
#<x3> = 0
|
||||
#<y3> = #<ymax>
|
||||
#<z3> = #<zmax>
|
||||
|
||||
m111 ;clear notifications
|
||||
g61
|
||||
g0 x0 y0 z0
|
||||
|
||||
o<rpt> repeat [#<rct>]
|
||||
f #<feed>
|
||||
g0 x 0 y 0 z 0
|
||||
g1 x #<x1> y #<y1> z #<z1>
|
||||
g1 x #<x2> y #<y2> z #<z2>
|
||||
g1 x #<x3> y #<y3> z #<z3>
|
||||
g1 x 0 y 0 z 0
|
||||
o<rpt> endrepeat
|
||||
|
||||
m111 ;clear notifications
|
||||
m2
|
||||
83
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini
vendored
Normal file
83
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
[APPLICATIONS]
|
||||
# delay because some items are done in postgui
|
||||
DELAY = 5
|
||||
APP = halscope -i dynamic_offsets.halscope
|
||||
|
||||
[HAL]
|
||||
HALUI = halui
|
||||
HALFILE = LIB:basic_sim.tcl -no_sim_spindle
|
||||
POSTGUI_HALFILE = dynamic_offsets_panel.hal
|
||||
|
||||
[EMC]
|
||||
MACHINE = Dynamic External Offsets
|
||||
VERSION = 1.1
|
||||
|
||||
[DISPLAY]
|
||||
PYVCP = dynamic_offsets_panel.xml
|
||||
DISPLAY = axis
|
||||
POSITION_OFFSET = RELATIVE
|
||||
POSITION_FEEDBACK = ACTUAL
|
||||
MAX_LINEAR_VELOCITY = 2
|
||||
OPEN_FILE = ./dyn_demo.ngc
|
||||
|
||||
[TASK]
|
||||
TASK = milltask
|
||||
CYCLE_TIME = 0.001
|
||||
|
||||
[RS274NGC]
|
||||
USER_M_PATH = .
|
||||
PARAMETER_FILE = sim.var
|
||||
|
||||
[EMCMOT]
|
||||
EMCMOT = motmod
|
||||
SERVO_PERIOD = 1000000
|
||||
|
||||
[TRAJ]
|
||||
COORDINATES = XYZ
|
||||
LINEAR_UNITS = inch
|
||||
ANGULAR_UNITS = degree
|
||||
|
||||
[KINS]
|
||||
JOINTS = 3
|
||||
KINEMATICS = trivkins coordinates=XYZ
|
||||
|
||||
[AXIS_X]
|
||||
MAX_VELOCITY = 2
|
||||
MAX_ACCELERATION = 20
|
||||
MIN_LIMIT = -1
|
||||
MAX_LIMIT = 10
|
||||
|
||||
[AXIS_Y]
|
||||
MAX_VELOCITY = 2
|
||||
MAX_ACCELERATION = 20
|
||||
MIN_LIMIT = -1
|
||||
MAX_LIMIT = 10
|
||||
|
||||
[AXIS_Z]
|
||||
# Note:give half to external_offsets:
|
||||
OFFSET_AV_RATIO = 0.5
|
||||
|
||||
# Note: modified in pyvcp panel:
|
||||
MAX_VELOCITY = 2
|
||||
MAX_ACCELERATION = 50
|
||||
|
||||
MIN_LIMIT = -5
|
||||
MAX_LIMIT = 5
|
||||
|
||||
[JOINT_0]
|
||||
TYPE = LINEAR
|
||||
HOME_SEQUENCE = 0
|
||||
MAX_VELOCITY = 2
|
||||
MAX_ACCELERATION = 20
|
||||
|
||||
[JOINT_1]
|
||||
TYPE = LINEAR
|
||||
HOME_SEQUENCE = 0
|
||||
MAX_VELOCITY = 2
|
||||
MAX_ACCELERATION = 20
|
||||
|
||||
[JOINT_2]
|
||||
TYPE = LINEAR
|
||||
HOME_SEQUENCE = 0
|
||||
MAX_VELOCITY = 2
|
||||
MAX_ACCELERATION = 50
|
||||
1
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/eoffset.tbl
vendored
Normal file
1
wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/eoffset.tbl
vendored
Normal file
@@ -0,0 +1 @@
|
||||
T1 P1 D0.125 Z0.5
|
||||
126
wasm-port/vendor/linuxcnc/configs/sim/axis/foam/axis_foam.ini
vendored
Normal file
126
wasm-port/vendor/linuxcnc/configs/sim/axis/foam/axis_foam.ini
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
[EMC]
|
||||
VERSION = 1.1
|
||||
MACHINE = LinuxCNC-HAL-SIM-AXIS
|
||||
DEBUG = 0
|
||||
|
||||
[DISPLAY]
|
||||
DISPLAY = axis
|
||||
CYCLE_TIME = 0.100
|
||||
HELP_FILE = doc/help.txt
|
||||
POSITION_OFFSET = RELATIVE
|
||||
POSITION_FEEDBACK = ACTUAL
|
||||
MAX_FEED_OVERRIDE = 1.2
|
||||
MAX_SPINDLE_OVERRIDE = 1.0
|
||||
PROGRAM_PREFIX = ../../nc_files/
|
||||
OPEN_FILE = ./foam.ngc
|
||||
INTRO_GRAPHIC = linuxcnc.gif
|
||||
INTRO_TIME = 5
|
||||
#EDITOR = geany
|
||||
INCREMENTS = 1 mm, .01 in, .1mm, 1 mil, .1 mil, 1/8000 in
|
||||
GEOMETRY = XY;UV
|
||||
FOAM = 1
|
||||
|
||||
[FILTER]
|
||||
PROGRAM_EXTENSION = .png,.gif,.jpg Grayscale Depth Image
|
||||
PROGRAM_EXTENSION = .py Python Script
|
||||
png = image-to-gcode
|
||||
gif = image-to-gcode
|
||||
jpg = image-to-gcode
|
||||
py = python3
|
||||
|
||||
[RS274NGC]
|
||||
PARAMETER_FILE = foam.var
|
||||
|
||||
[EMCMOT]
|
||||
EMCMOT = motmod
|
||||
COMM_TIMEOUT = 1.0
|
||||
SERVO_PERIOD = 1000000
|
||||
|
||||
[TASK]
|
||||
TASK = milltask
|
||||
CYCLE_TIME = 0.001
|
||||
|
||||
[HAL]
|
||||
HALUI = halui
|
||||
HALFILE = LIB:basic_sim.tcl
|
||||
|
||||
[TRAJ]
|
||||
NO_FORCE_HOMING = 1
|
||||
COORDINATES = X Y U V
|
||||
LINEAR_UNITS = inch
|
||||
ANGULAR_UNITS = degree
|
||||
DEFAULT_LINEAR_VELOCITY = 1.0
|
||||
DEFAULT_ANGULAR_VELOCITY = 45.0
|
||||
MAX_LINEAR_VELOCITY = 1.2
|
||||
MAX_ANGULAR_VELOCITY = 90.0
|
||||
|
||||
[EMCIO]
|
||||
TOOL_TABLE = sim.tbl
|
||||
TOOL_CHANGE_POSITION = 0 0 2
|
||||
|
||||
[KINS]
|
||||
KINEMATICS = trivkins coordinates=xyuv
|
||||
JOINTS = 4
|
||||
|
||||
[AXIS_X]
|
||||
MIN_LIMIT = -10.0
|
||||
MAX_LIMIT = 10.0
|
||||
MAX_VELOCITY = 1.2
|
||||
MAX_ACCELERATION = 20.0
|
||||
|
||||
[JOINT_0]
|
||||
TYPE = LINEAR
|
||||
HOME = 0.000
|
||||
MAX_VELOCITY = 1.2
|
||||
MAX_ACCELERATION = 20.0
|
||||
MIN_LIMIT = -10.0
|
||||
MAX_LIMIT = 10.0
|
||||
HOME_SEARCH_VEL = 0.0
|
||||
HOME_SEQUENCE = 0
|
||||
|
||||
[AXIS_Y]
|
||||
MIN_LIMIT = -10.0
|
||||
MAX_LIMIT = 10.0
|
||||
MAX_VELOCITY = 1.2
|
||||
MAX_ACCELERATION = 20.0
|
||||
|
||||
[JOINT_1]
|
||||
TYPE = LINEAR
|
||||
HOME = 0.000
|
||||
MAX_VELOCITY = 1.2
|
||||
MAX_ACCELERATION = 20.0
|
||||
MIN_LIMIT = -10.0
|
||||
MAX_LIMIT = 10.0
|
||||
HOME_SEARCH_VEL = 0.0
|
||||
HOME_SEQUENCE = 0
|
||||
|
||||
[AXIS_U]
|
||||
MIN_LIMIT = -10.0
|
||||
MAX_LIMIT = 10.0
|
||||
MAX_VELOCITY = 1.2
|
||||
MAX_ACCELERATION = 20.0
|
||||
|
||||
[JOINT_2]
|
||||
TYPE = LINEAR
|
||||
HOME = 0.0
|
||||
MAX_VELOCITY = 1.2
|
||||
MAX_ACCELERATION = 20.0
|
||||
MIN_LIMIT = -10.0
|
||||
MAX_LIMIT = 10.0
|
||||
HOME_SEARCH_VEL = 0.0
|
||||
HOME_SEQUENCE = 0
|
||||
|
||||
[AXIS_V]
|
||||
MIN_LIMIT = -10.0
|
||||
MAX_LIMIT = 10.0
|
||||
MAX_VELOCITY = 1.2
|
||||
MAX_ACCELERATION = 20.0
|
||||
|
||||
[JOINT_3]
|
||||
TYPE = ANGULAR
|
||||
HOME = 0.0
|
||||
MAX_VELOCITY = 90.0
|
||||
MAX_ACCELERATION = 1200.0
|
||||
HOME_SEARCH_VEL = 0.0
|
||||
HOME_SEQUENCE = 0
|
||||
|
||||
24
wasm-port/vendor/linuxcnc/configs/sim/axis/foam/foam.ngc
vendored
Normal file
24
wasm-port/vendor/linuxcnc/configs/sim/axis/foam/foam.ngc
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
(test this with axis_9axis sim machine )
|
||||
G17 G21 G90 G61 G54
|
||||
(AXIS,XY_Z_POS,5)
|
||||
(AXIS,UV_Z_POS,30)
|
||||
(AXIS,GRID,5)
|
||||
|
||||
G0 x0 y0 u0 v0
|
||||
|
||||
(square uv 45 deg turned offset 10mm to zero )
|
||||
G0 x5 y5
|
||||
G0 x10 y10 u22.5 v22.5
|
||||
G1 x10 y35 u10 v35 F200
|
||||
G1 x10 y60 u22.5 v47.5
|
||||
G1 x35 y60 u35 v60
|
||||
G2 r25 x60 y35 u60 v35
|
||||
G1 x60 y10 u47.5 v22.5
|
||||
G1 x35 y10 u35 v10
|
||||
G1 X10 Y10 u22.5 v22.5
|
||||
G1 X5 Y5 U5 V5
|
||||
G0 x0 u0
|
||||
|
||||
G0 x0 y0 u0 v0
|
||||
M30
|
||||
%
|
||||
7
wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/M110
vendored
Executable file
7
wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/M110
vendored
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
halcmd setp axisui.notifications-clear-info 1
|
||||
sleep .200
|
||||
halcmd setp axisui.notifications-clear-info 0
|
||||
|
||||
exit 0
|
||||
72
wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/xyzc.ini
vendored
Normal file
72
wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/xyzc.ini
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
# minimal sim config to demonstrate '!' in [DISPLAY]GEOMETRY
|
||||
# showing rotations respecting g5x,g92 offsets
|
||||
[EMC]
|
||||
VERSION = 1.1
|
||||
MACHINE = xyzc (offset rotations)
|
||||
|
||||
[DISPLAY]
|
||||
OPEN_FILE = ./xyzc.ngc
|
||||
GEOMETRY = !CXYZ
|
||||
DISPLAY = axis
|
||||
|
||||
[TASK]
|
||||
TASK = milltask
|
||||
CYCLE_TIME = 0.001
|
||||
|
||||
[RS274NGC]
|
||||
PARAMETER_FILE = xyzc.var
|
||||
USER_M_PATH = .
|
||||
|
||||
[EMCMOT]
|
||||
EMCMOT = motmod
|
||||
SERVO_PERIOD = 1000000
|
||||
|
||||
[HAL]
|
||||
HALFILE = LIB:basic_sim.tcl
|
||||
|
||||
[KINS]
|
||||
JOINTS = 4
|
||||
KINEMATICS = trivkins coordinates=XYZC kinstype=both
|
||||
|
||||
[TRAJ]
|
||||
COORDINATES = X Y Z C
|
||||
LINEAR_UNITS = inch
|
||||
ANGULAR_UNITS = degree
|
||||
MAX_LINEAR_VELOCITY = 10
|
||||
MAX_LINEAR_ACCELERATION = 10000
|
||||
MAX_ANGULAR_VELOCITY = 3600
|
||||
MAX_ANGULAR_ACCELERATION = 36000
|
||||
|
||||
[JOINT_0]
|
||||
TYPE = LINEAR
|
||||
HOME_SEQUENCE = 0
|
||||
|
||||
[JOINT_1]
|
||||
TYPE = LINEAR
|
||||
HOME_SEQUENCE = 0
|
||||
|
||||
[JOINT_2]
|
||||
TYPE = LINEAR
|
||||
HOME_SEQUENCE = 0
|
||||
|
||||
[JOINT_3]
|
||||
TYPE = ANGULAR
|
||||
HOME_SEQUENCE = 0
|
||||
MAX_VELOCITY=3600
|
||||
MAX_ACCELERATION=36000
|
||||
|
||||
[AXIS_X]
|
||||
MAX_VELOCITY=10
|
||||
MAX_ACCELERATION=1000
|
||||
|
||||
[AXIS_Y]
|
||||
MAX_VELOCITY=10
|
||||
MAX_ACCELERATION=1000
|
||||
|
||||
[AXIS_Z]
|
||||
MAX_VELOCITY=10
|
||||
MAX_ACCELERATION=1000
|
||||
|
||||
[AXIS_C]
|
||||
MAX_VELOCITY=3600
|
||||
MAX_ACCELERATION=36000
|
||||
66
wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/xyzc.ngc
vendored
Normal file
66
wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/xyzc.ngc
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
o110 sub
|
||||
f100
|
||||
g61
|
||||
g0 x1.0 y0.0
|
||||
g1 x1.5 y0.0
|
||||
g1 x1.5 y0.5
|
||||
g1 x1.0 y0.5
|
||||
g1 x1.0 y0.0
|
||||
o110 endsub
|
||||
|
||||
o100 sub
|
||||
g0 c90
|
||||
o110 call
|
||||
g0 c180
|
||||
o110 call
|
||||
g0 c270
|
||||
o110 call
|
||||
g0x0y0z0c0
|
||||
o100 endsub
|
||||
|
||||
;#########################################################
|
||||
m110 ; clear messages
|
||||
g0x0y0z0c0
|
||||
o110 call
|
||||
|
||||
o200 if [#5210 ne 0]
|
||||
(debug, ! Prog loaded with g92 offsets)
|
||||
(debug, RELOAD program required)
|
||||
g92.1
|
||||
(debug, bye)
|
||||
m2
|
||||
o200 endif
|
||||
|
||||
o210 if [[#5221 ne 0] or [#5222 ne 0] or [#5223 ne 0] or [#5223 ne 0] or [#5225 ne 0] or [#5226 ne 0] or [#5227 ne 0] or [#5228 ne 0] or [#5229 ne 0] ]
|
||||
(debug, ! Prog loaded with g5x offsets)
|
||||
(debug, RELOAD program required)
|
||||
g92.1
|
||||
g10l2p0x0y0z0c0
|
||||
(debug, bye)
|
||||
m2
|
||||
o210 endif
|
||||
|
||||
g0x0y0z0c0
|
||||
g10l2p0x0y0z0c0
|
||||
(debug, First: run with NO offsets, s to continue)
|
||||
m0
|
||||
o100 call
|
||||
|
||||
o300 if [#<_task> eq 1]
|
||||
g10l2p0x1
|
||||
(debug, Next: run with g5x xoffset=#5221, s to continue)
|
||||
m0
|
||||
o100 call
|
||||
|
||||
g10l2p0x0y0z0c0
|
||||
g92x2
|
||||
(debug, Next: run with g92 xoffset=#5211, s to continue)
|
||||
m0
|
||||
o100 call
|
||||
o300 endif
|
||||
|
||||
g10l2p0x0y0z0c0
|
||||
g92.1
|
||||
g0x0y0z0c0
|
||||
(debug,fini)
|
||||
m2
|
||||
5
wasm-port/vendor/linuxcnc/configs/sim/axis/sim.tbl
vendored
Normal file
5
wasm-port/vendor/linuxcnc/configs/sim/axis/sim.tbl
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
T1 P1 Z0.511 D0.125 ;1/8 end mill
|
||||
T2 P2 Z0.1 D0.0625 ;1/16 end mill
|
||||
T3 P3 Z1.273 D0.201 ;#7 tap drill
|
||||
T99999 P99999 Z0.1 ;big tool number
|
||||
T4 P4 Z0 D.005 ;Added 20131029
|
||||
1008
wasm-port/vendor/linuxcnc/nc_files/arcspiral.ngc
vendored
Normal file
1008
wasm-port/vendor/linuxcnc/nc_files/arcspiral.ngc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11
wasm-port/vendor/linuxcnc/nc_files/factorial.ngc
vendored
Normal file
11
wasm-port/vendor/linuxcnc/nc_files/factorial.ngc
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
; recursive function example
|
||||
; factorial
|
||||
o<factorial> sub
|
||||
o<factorialif> if [[#1] EQ 0]
|
||||
o<factorial> return [1]
|
||||
o<factorialif> else
|
||||
o<factorial> call [[#1] - 1]
|
||||
o<factorial> return [#<_value> * #1]
|
||||
o<factorialif> endif
|
||||
o<factorial> endsub
|
||||
m2
|
||||
12
wasm-port/vendor/linuxcnc/nc_files/hole-circle.ngc
vendored
Normal file
12
wasm-port/vendor/linuxcnc/nc_files/hole-circle.ngc
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
; drill a bolt hole circle for 6 bolts at diameter 3 inches
|
||||
|
||||
G20 G17 G90
|
||||
|
||||
; position over first hole, establishing our radius of 1.5
|
||||
; an equivalent command would be G0 @1.5 ^0 Z0
|
||||
G0 X1.5 Y0 Z0
|
||||
|
||||
; drill six holes, incrementing 60 degrees each time
|
||||
G91 G81 R.1 Z-.5 ^60 L6 F10
|
||||
|
||||
M2
|
||||
88
wasm-port/vendor/linuxcnc/nc_files/m6demo.ngc
vendored
Normal file
88
wasm-port/vendor/linuxcnc/nc_files/m6demo.ngc
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
; This demonstrates doing an M6 remapped to a named oword sub
|
||||
;
|
||||
; to activate, incantate as follows in the INI file:
|
||||
;
|
||||
; [RS274NGC]
|
||||
|
||||
; # remap M6 to a named oword subroutine.
|
||||
; M6_COMMAND=o<m6demo>call
|
||||
;
|
||||
; parameter #1: the current tool-in-spindle
|
||||
; parameter #2: the tool number requested in the last T (prepare) command
|
||||
; parameter #3: pocket of new tool
|
||||
;
|
||||
;
|
||||
;
|
||||
O<m6demo> sub
|
||||
;
|
||||
(DEBUG, executing M6 O-word sub, tool-in-spindle=#1 prepared=#2 pocket=#3)
|
||||
;
|
||||
M66 P2 L0
|
||||
;(debug, digital-input-02=#5399)
|
||||
|
||||
#<tool_change_with_spindle_on> = 0
|
||||
#<tool_change_quill_up> = 0
|
||||
#<tool_change_at_g30> = 0
|
||||
|
||||
; number of seconds to wait for 'tool-changed' equivalent
|
||||
#<timeout> = 9999
|
||||
;
|
||||
O<m6demo_spindle_off> if [#<tool_change_with_spindle_on> EQ 0]
|
||||
M5
|
||||
O<m6demo_spindle_off> endif
|
||||
|
||||
O<m6demo_quill_up> if [#<tool_change_quill_up> NE 0]
|
||||
G0 G53 Z0
|
||||
O<m6demo_quill_up> endif
|
||||
|
||||
O<m6demo_tc_at_g30> if [#<tool_change_at_g30> NE 0]
|
||||
G30
|
||||
O<m6demo_tc_at_g30> endif
|
||||
|
||||
; set analog output pin #2 to signal the pocket number
|
||||
; iocontrol.tool-number becomes motion.analog-out-02
|
||||
M68 E2 Q[#2]
|
||||
;(DEBUG, set current tool number on motion.analog-out-02: #2)
|
||||
;
|
||||
; assert the equivalent of the iocontrol.tool-change pin
|
||||
; which is now motion.digital-out-01
|
||||
M64 P1
|
||||
;(DEBUG, motion.digital-out-01 set high, waiting for motion.digital-in-01)
|
||||
|
||||
|
||||
; wait for the equivalent of the iocontrol.tool-changed pin to go high
|
||||
; we use motion.digital-in-01
|
||||
;
|
||||
M66 P1 L3 Q#<timeout>
|
||||
;
|
||||
; if we waited too long, fail change and abort.
|
||||
;
|
||||
O<m6demo_timeout> if [#5399 EQ -1]
|
||||
(DEBUG, timeout waiting for digital-in-01 to become true - failing change )
|
||||
O<m6demo> return [-1]
|
||||
O<m6demo_timeout> endif
|
||||
|
||||
; retract iocontrol.tool-change equivalent
|
||||
;(DEBUG, deasserting motion.digital-out-01)
|
||||
M65 P1
|
||||
;
|
||||
|
||||
; test fail-change line from gladevcp
|
||||
M66 P2 L0
|
||||
; (debug, digital-input-02=#5399)
|
||||
O<m6demo_change_fail> if [#5399 EQ 1]
|
||||
(DEBUG, returning -1 to fail change)
|
||||
O<m6demo> return [-1]
|
||||
O<m6demo_change_fail> else
|
||||
(debug, change ok, returning +1 to commit change)
|
||||
; a positive return value commits the tool change
|
||||
O<m6demo> return [1]
|
||||
O<m6demo_change_fail> endif
|
||||
;
|
||||
; return a positive value commit the change.
|
||||
; a negative return value will fail the change and
|
||||
; abort the interpreter with a message like
|
||||
; "M6 failed (<return value>)"
|
||||
;
|
||||
O<m6demo> endsub
|
||||
m2
|
||||
8
wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/README
vendored
Normal file
8
wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/README
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
exercise the (ABORT,<message>) hot comment:
|
||||
|
||||
numbered, named and INI parameter substitution in message
|
||||
case preservation
|
||||
unwind from oword flow
|
||||
|
||||
|
||||
|
||||
10
wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/expected
vendored
Normal file
10
wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/expected
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
executing
|
||||
1 N..... USE_LENGTH_UNITS(CANON_UNITS_MM)
|
||||
2 N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
3 N..... SET_G92_OFFSET(0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
4 N..... SET_XY_ROTATION(0.0000)
|
||||
5 N..... SET_FEED_REFERENCE(CANON_XYZ)
|
||||
6 N..... ON_RESET()
|
||||
MixedCase param42=20.000000 named=4711.000000 INI=3.140000
|
||||
(abort, MixedCase param42=#42 named=#<named> INI=#<_ini[a]value>)
|
||||
7 N..... ON_RESET()
|
||||
8
wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.ini
vendored
Normal file
8
wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.ini
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
[RS274NGC]
|
||||
# enable #<_ini[section]name> expansion
|
||||
INI_VARS = 1
|
||||
|
||||
# test ini variable expansion in (ABORT, text) comment
|
||||
[A]
|
||||
VALUE= 3.14
|
||||
|
||||
10
wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.ngc
vendored
Normal file
10
wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.ngc
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
#42 = 0
|
||||
#<named> = 4711
|
||||
o100 while [#42 lt 100]
|
||||
o200 if [#42 eq 20]
|
||||
(abort, MixedCase param42=#42 named=#<named> INI=#<_ini[a]value>)
|
||||
o200 endif
|
||||
#42 = [#42 + 1]
|
||||
o100 endwhile
|
||||
|
||||
M2
|
||||
5
wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.sh
vendored
Executable file
5
wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.sh
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
export PYTHONUNBUFFERED=1
|
||||
rs274 -n 2 -i test.ini -g test.ngc 2>&1
|
||||
exit 0
|
||||
|
||||
3
wasm-port/vendor/linuxcnc/tests/interp/do-while-break/README
vendored
Normal file
3
wasm-port/vendor/linuxcnc/tests/interp/do-while-break/README
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Tests for bug 3420655 (http://sourceforge.net/tracker/?func=detail&atid=106744&aid=3420655&group_id=6744)
|
||||
|
||||
|
||||
7
wasm-port/vendor/linuxcnc/tests/interp/do-while-break/bug.ngc
vendored
Normal file
7
wasm-port/vendor/linuxcnc/tests/interp/do-while-break/bug.ngc
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
o102 do
|
||||
(print,@start of do-while-loop)
|
||||
o102 break
|
||||
(print,@end of do-while-loop)
|
||||
o102 while [1]
|
||||
(print,@endsub)
|
||||
M2
|
||||
21
wasm-port/vendor/linuxcnc/tests/interp/do-while-break/expected
vendored
Normal file
21
wasm-port/vendor/linuxcnc/tests/interp/do-while-break/expected
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
N..... USE_LENGTH_UNITS(CANON_UNITS_MM)
|
||||
N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_G92_OFFSET(0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_XY_ROTATION(0.0000)
|
||||
N..... SET_FEED_REFERENCE(CANON_XYZ)
|
||||
N..... ON_RESET()
|
||||
N..... MESSAGE("must-execute-outer")
|
||||
N..... MESSAGE("must-execute-nested")
|
||||
N..... MESSAGE("must-execute-inner")
|
||||
N..... MESSAGE("post-inner-while")
|
||||
N..... MESSAGE("post-nested-while")
|
||||
N..... MESSAGE("post-outer-while")
|
||||
N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_XY_ROTATION(0.0000)
|
||||
N..... SET_FEED_MODE(0, 0)
|
||||
N..... SET_FEED_RATE(0.0000)
|
||||
N..... STOP_SPINDLE_TURNING(0)
|
||||
N..... SET_SPINDLE_MODE(0 0.0000)
|
||||
N..... PROGRAM_END()
|
||||
N..... ON_RESET()
|
||||
N..... ON_RESET()
|
||||
30
wasm-port/vendor/linuxcnc/tests/interp/do-while-break/test.ngc
vendored
Normal file
30
wasm-port/vendor/linuxcnc/tests/interp/do-while-break/test.ngc
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
#<one_pass> = 0
|
||||
|
||||
o100 do
|
||||
(debug,must-execute-outer)
|
||||
#<one_pass> = [#<one_pass> + 1]
|
||||
#<two_pass> = 0
|
||||
o200 do
|
||||
(debug,must-execute-nested)
|
||||
#<two_pass> = [#<two_pass> + 1]
|
||||
#<three_pass> = 0
|
||||
o300 do
|
||||
(debug,must-execute-inner)
|
||||
#<three_pass> = [#<three_pass> + 1]
|
||||
o300 break
|
||||
(debug,do-not-execute-inner)
|
||||
o300 while [#<three_pass> LT 3]
|
||||
(debug,post-inner-while)
|
||||
|
||||
o200 break
|
||||
(debug,do-not-execute-nested)
|
||||
o200 while [#<two_pass> LT 3]
|
||||
(debug,post-nested-while)
|
||||
|
||||
o100 break
|
||||
(debug,do-not-execute-outer)
|
||||
o100 while [#<one_pass> LT 3]
|
||||
(debug,post-outer-while)
|
||||
|
||||
M2
|
||||
3
wasm-port/vendor/linuxcnc/tests/interp/do-while-break/test.sh
vendored
Normal file
3
wasm-port/vendor/linuxcnc/tests/interp/do-while-break/test.sh
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
rs274 -g test.ngc | awk '{$1=""; print}'
|
||||
exit "${PIPESTATUS[0]}"
|
||||
1
wasm-port/vendor/linuxcnc/tests/interp/exists/README
vendored
Normal file
1
wasm-port/vendor/linuxcnc/tests/interp/exists/README
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Test that EXISTS[] works as desired
|
||||
18
wasm-port/vendor/linuxcnc/tests/interp/exists/expected
vendored
Normal file
18
wasm-port/vendor/linuxcnc/tests/interp/exists/expected
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
N..... USE_LENGTH_UNITS(CANON_UNITS_MM)
|
||||
N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_G92_OFFSET(0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_XY_ROTATION(0.0000)
|
||||
N..... SET_FEED_REFERENCE(CANON_XYZ)
|
||||
N..... ON_RESET()
|
||||
N..... STRAIGHT_TRAVERSE(1.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... COMMENT("comment")
|
||||
N..... STRAIGHT_TRAVERSE(1.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_XY_ROTATION(0.0000)
|
||||
N..... SET_FEED_MODE(0, 0)
|
||||
N..... SET_FEED_RATE(0.0000)
|
||||
N..... STOP_SPINDLE_TURNING(0)
|
||||
N..... SET_SPINDLE_MODE(0 0.0000)
|
||||
N..... PROGRAM_END()
|
||||
N..... ON_RESET()
|
||||
N..... ON_RESET()
|
||||
7
wasm-port/vendor/linuxcnc/tests/interp/exists/test.ngc
vendored
Normal file
7
wasm-port/vendor/linuxcnc/tests/interp/exists/test.ngc
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
#<a>=999
|
||||
G0 X EXISTS[#1] Y EXISTS[#99999] Z EXISTS[#<a>] A EXISTS[#<b>] ; comment
|
||||
|
||||
#1=2
|
||||
#2=99999
|
||||
G0 X EXISTS[##1] Y EXISTS[##2] Z EXISTS[###1] (comment)
|
||||
M2
|
||||
3
wasm-port/vendor/linuxcnc/tests/interp/exists/test.sh
vendored
Normal file
3
wasm-port/vendor/linuxcnc/tests/interp/exists/test.sh
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
rs274 -g test.ngc | awk '{$1=""; print}'
|
||||
exit "${PIPESTATUS[0]}"
|
||||
1
wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/README
vendored
Normal file
1
wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/README
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Test that line numbers like Ndddd.ddd are accepted too
|
||||
18
wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/expected
vendored
Normal file
18
wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/expected
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
N..... USE_LENGTH_UNITS(CANON_UNITS_MM)
|
||||
N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_G92_OFFSET(0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_XY_ROTATION(0.0000)
|
||||
N..... SET_FEED_REFERENCE(CANON_XYZ)
|
||||
N..... ON_RESET()
|
||||
N..... SET_SPINDLE_SPEED(0, 300.0000)
|
||||
N1234 SET_SPINDLE_SPEED(0, 600.0000)
|
||||
N4567 SET_SPINDLE_SPEED(0, 1200.0000)
|
||||
N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_XY_ROTATION(0.0000)
|
||||
N..... SET_FEED_MODE(0, 0)
|
||||
N..... SET_FEED_RATE(0.0000)
|
||||
N..... STOP_SPINDLE_TURNING(0)
|
||||
N..... SET_SPINDLE_MODE(0 0.0000)
|
||||
N..... PROGRAM_END()
|
||||
N..... ON_RESET()
|
||||
N..... ON_RESET()
|
||||
4
wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/test.ngc
vendored
Normal file
4
wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/test.ngc
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
S300
|
||||
N1234 S600
|
||||
N4567.789 S1200
|
||||
M2
|
||||
3
wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/test.sh
vendored
Normal file
3
wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/test.sh
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
rs274 -g test.ngc | awk '{$1=""; print}'
|
||||
exit "${PIPESTATUS[0]}"
|
||||
23
wasm-port/vendor/linuxcnc/tests/interp/g6164/expected
vendored
Normal file
23
wasm-port/vendor/linuxcnc/tests/interp/g6164/expected
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
N..... USE_LENGTH_UNITS(CANON_UNITS_MM)
|
||||
N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_G92_OFFSET(0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_XY_ROTATION(0.0000)
|
||||
N..... SET_FEED_REFERENCE(CANON_XYZ)
|
||||
N..... ON_RESET()
|
||||
N..... SET_MOTION_CONTROL_MODE(CANON_CONTINUOUS, 0.000000)
|
||||
N..... SET_NAIVECAM_TOLERANCE(0.0000)
|
||||
N..... SET_MOTION_CONTROL_MODE(CANON_CONTINUOUS, 1.000000)
|
||||
N..... SET_NAIVECAM_TOLERANCE(1.0000)
|
||||
N..... SET_MOTION_CONTROL_MODE(CANON_CONTINUOUS, 1.000000)
|
||||
N..... SET_NAIVECAM_TOLERANCE(2.0000)
|
||||
N..... SET_MOTION_CONTROL_MODE(CANON_EXACT_PATH)
|
||||
N..... SET_MOTION_CONTROL_MODE(CANON_EXACT_STOP)
|
||||
N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_XY_ROTATION(0.0000)
|
||||
N..... SET_FEED_MODE(0, 0)
|
||||
N..... SET_FEED_RATE(0.0000)
|
||||
N..... STOP_SPINDLE_TURNING(0)
|
||||
N..... SET_SPINDLE_MODE(0 0.0000)
|
||||
N..... PROGRAM_END()
|
||||
N..... ON_RESET()
|
||||
N..... ON_RESET()
|
||||
6
wasm-port/vendor/linuxcnc/tests/interp/g6164/test.ngc
vendored
Normal file
6
wasm-port/vendor/linuxcnc/tests/interp/g6164/test.ngc
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
G64
|
||||
G64P1
|
||||
G64P1Q2
|
||||
G61
|
||||
G61.1
|
||||
M2
|
||||
3
wasm-port/vendor/linuxcnc/tests/interp/g6164/test.sh
vendored
Normal file
3
wasm-port/vendor/linuxcnc/tests/interp/g6164/test.sh
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
rs274 -g test.ngc | awk '{$1=""; print}'
|
||||
exit "${PIPESTATUS[0]}"
|
||||
3
wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/README
vendored
Normal file
3
wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/README
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
assigning to an inifile variable reference must fail:
|
||||
|
||||
#<_ini[section]name> = <value>
|
||||
10
wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/expected
vendored
Normal file
10
wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/expected
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
executing
|
||||
1 N..... USE_LENGTH_UNITS(CANON_UNITS_MM)
|
||||
2 N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
3 N..... SET_G92_OFFSET(0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
4 N..... SET_XY_ROTATION(0.0000)
|
||||
5 N..... SET_FEED_REFERENCE(CANON_XYZ)
|
||||
6 N..... ON_RESET()
|
||||
Cannot assign to read-only parameter #<_ini[vars]toolchange_x>
|
||||
#<_ini[vars]toolchange_x> = 3.1415
|
||||
7 N..... ON_RESET()
|
||||
9
wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.ini
vendored
Normal file
9
wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.ini
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
[EMC]
|
||||
DEBUG=0
|
||||
LOG_LEVEL=0
|
||||
|
||||
[RS274NGC]
|
||||
INI_VARS = 1
|
||||
|
||||
[VARS]
|
||||
TOOLCHANGE_X = 10
|
||||
3
wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.ngc
vendored
Normal file
3
wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.ngc
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#<_ini[vars]toolchange_x> = 3.1415
|
||||
(debug, notreached: #<_ini[vars]toolchange_x>)
|
||||
M2
|
||||
8
wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.sh
vendored
Executable file
8
wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.sh
vendored
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
export PYTHONUNBUFFERED=1
|
||||
if ! rs274 -i test.ini -g test.ngc 2>&1; then
|
||||
# expected to fail
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exit 1
|
||||
5
wasm-port/vendor/linuxcnc/tests/interp/iniparam/README
vendored
Normal file
5
wasm-port/vendor/linuxcnc/tests/interp/iniparam/README
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
named parameters can now reference INI variables; they are retrieved on demand and
|
||||
cached as global read-only parameters.
|
||||
|
||||
Syntax: #<_ini[section]name>
|
||||
13
wasm-port/vendor/linuxcnc/tests/interp/iniparam/expected
vendored
Normal file
13
wasm-port/vendor/linuxcnc/tests/interp/iniparam/expected
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
executing
|
||||
1 N..... USE_LENGTH_UNITS(CANON_UNITS_MM)
|
||||
2 N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
3 N..... SET_G92_OFFSET(0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
4 N..... SET_XY_ROTATION(0.0000)
|
||||
5 N..... SET_FEED_REFERENCE(CANON_XYZ)
|
||||
6 N..... ON_RESET()
|
||||
7 N..... STRAIGHT_TRAVERSE(10.0000, 20.0000, 30.0000, 0.0000, 0.0000, 0.0000)
|
||||
8 N..... MESSAGE(" position now: 10.000000 20.000000 30.000000")
|
||||
9 N..... MESSAGE(" not in INI: ######")
|
||||
Named parameter #<_ini[nosuchsection]nosuchname> not defined
|
||||
#4711 = #<_iNI[nosuchsection]nosuchname>
|
||||
10 N..... ON_RESET()
|
||||
12
wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.ini
vendored
Normal file
12
wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.ini
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
[EMC]
|
||||
DEBUG=0
|
||||
LOG_LEVEL=0
|
||||
|
||||
[RS274NGC]
|
||||
INI_VARS = 1
|
||||
|
||||
|
||||
[VARS]
|
||||
TOOLCHANGE_X = 10
|
||||
TOOLCHANGE_Y = 20
|
||||
TOOLCHANGE_Z = 30
|
||||
9
wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.ngc
vendored
Normal file
9
wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.ngc
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
G53 G0 x#<_ini[vars]toolchange_x> y#<_InI[vars]toolchange_y> z#<_INi[vars]toolchange_z>
|
||||
(debug, position now: #<_x> #<_y> #<_z>)
|
||||
|
||||
(debug, not in INI: #<_iNi[nosuchsection]nosuchname>)
|
||||
|
||||
; now fail referencing an undefined INI variable:
|
||||
#4711 = #<_iNI[nosuchsection]nosuchname>
|
||||
|
||||
M2
|
||||
5
wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.sh
vendored
Executable file
5
wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.sh
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
export PYTHONUNBUFFERED=1
|
||||
rs274 -i test.ini -g test.ngc 2>&1
|
||||
# this is expected to fail on the undefined INI var
|
||||
exit 0
|
||||
2
wasm-port/vendor/linuxcnc/tests/interp/m19/README
vendored
Normal file
2
wasm-port/vendor/linuxcnc/tests/interp/m19/README
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
exercise M19 and possible parameters
|
||||
|
||||
20
wasm-port/vendor/linuxcnc/tests/interp/m19/expected
vendored
Normal file
20
wasm-port/vendor/linuxcnc/tests/interp/m19/expected
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
N..... USE_LENGTH_UNITS(CANON_UNITS_MM)
|
||||
N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_G92_OFFSET(0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_XY_ROTATION(0.0000)
|
||||
N..... SET_FEED_REFERENCE(CANON_XYZ)
|
||||
N..... ON_RESET()
|
||||
N..... ORIENT_SPINDLE(0, 87.0000, 0)
|
||||
N..... SPINDLE.0.WAIT_ORIENT_COMPLETE(2.0000)
|
||||
N..... ORIENT_SPINDLE(0, 42.0000, 1)
|
||||
N..... ORIENT_SPINDLE(0, 132.0000, 0)
|
||||
N..... ORIENT_SPINDLE(0, 132.0000, 1)
|
||||
N..... SPINDLE.0.WAIT_ORIENT_COMPLETE(1.0000)
|
||||
N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_XY_ROTATION(0.0000)
|
||||
N..... SET_FEED_MODE(0, 0)
|
||||
N..... SET_FEED_RATE(0.0000)
|
||||
N..... STOP_SPINDLE_TURNING(0)
|
||||
N..... SET_SPINDLE_MODE(0 0.0000)
|
||||
N..... PROGRAM_END()
|
||||
N..... ON_RESET()
|
||||
2
wasm-port/vendor/linuxcnc/tests/interp/m19/test.ini
vendored
Normal file
2
wasm-port/vendor/linuxcnc/tests/interp/m19/test.ini
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
[RS274NGC]
|
||||
ORIENT_OFFSET = 42.0
|
||||
8
wasm-port/vendor/linuxcnc/tests/interp/m19/test.ngc
vendored
Normal file
8
wasm-port/vendor/linuxcnc/tests/interp/m19/test.ngc
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
M19
|
||||
M19 R45 Q2
|
||||
M19 P1
|
||||
M19 R90 P0
|
||||
M19 R90 P1
|
||||
M19 Q1
|
||||
|
||||
M2
|
||||
3
wasm-port/vendor/linuxcnc/tests/interp/m19/test.sh
vendored
Normal file
3
wasm-port/vendor/linuxcnc/tests/interp/m19/test.sh
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
rs274 -n 0 -i test.ini -g test.ngc | awk '{$1=""; print}'
|
||||
exit "${PIPESTATUS[0]}"
|
||||
49
wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/expected
vendored
Normal file
49
wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/expected
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
N..... USE_LENGTH_UNITS(CANON_UNITS_MM)
|
||||
N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_G92_OFFSET(0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_XY_ROTATION(0.0000)
|
||||
N..... SET_FEED_REFERENCE(CANON_XYZ)
|
||||
N..... ON_RESET()
|
||||
N..... COMMENT("A simple O sub example ")
|
||||
N..... SET_FEED_RATE(40.0000)
|
||||
N..... STRAIGHT_TRAVERSE(0.0000, 0.0000, 0.2500, 0.0000, 0.0000, 0.0000)
|
||||
N..... COMMENT("interpreter: distance mode changed to incremental")
|
||||
N..... STRAIGHT_TRAVERSE(1.0000, 0.0000, 0.2500, 0.0000, 0.0000, 0.0000)
|
||||
N..... COMMENT("interpreter: distance mode changed to absolute")
|
||||
N..... COMMENT("interpreter: retract mode set to r_plane")
|
||||
N..... SET_MOTION_CONTROL_MODE(CANON_EXACT_PATH)
|
||||
N..... STRAIGHT_TRAVERSE(1.0000, 0.0000, 0.2500, 0.0000, 0.0000, 0.0000)
|
||||
N..... STRAIGHT_FEED(1.0000, 0.0000, -1.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... STRAIGHT_TRAVERSE(1.0000, 0.0000, 0.2500, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_MOTION_CONTROL_MODE(CANON_CONTINUOUS, 0.000000)
|
||||
N..... SET_NAIVECAM_TOLERANCE(0.0000)
|
||||
N..... COMMENT("interpreter: distance mode changed to incremental")
|
||||
N..... STRAIGHT_TRAVERSE(2.0000, 0.0000, 0.2500, 0.0000, 0.0000, 0.0000)
|
||||
N..... COMMENT("interpreter: distance mode changed to absolute")
|
||||
N..... COMMENT("interpreter: retract mode set to r_plane")
|
||||
N..... SET_MOTION_CONTROL_MODE(CANON_EXACT_PATH)
|
||||
N..... STRAIGHT_TRAVERSE(2.0000, 0.0000, 0.2500, 0.0000, 0.0000, 0.0000)
|
||||
N..... STRAIGHT_FEED(2.0000, 0.0000, -1.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... STRAIGHT_TRAVERSE(2.0000, 0.0000, 0.2500, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_MOTION_CONTROL_MODE(CANON_CONTINUOUS, 0.000000)
|
||||
N..... SET_NAIVECAM_TOLERANCE(0.0000)
|
||||
N..... COMMENT("interpreter: distance mode changed to incremental")
|
||||
N..... STRAIGHT_TRAVERSE(3.0000, 0.0000, 0.2500, 0.0000, 0.0000, 0.0000)
|
||||
N..... COMMENT("interpreter: distance mode changed to absolute")
|
||||
N..... COMMENT("interpreter: retract mode set to r_plane")
|
||||
N..... SET_MOTION_CONTROL_MODE(CANON_EXACT_PATH)
|
||||
N..... STRAIGHT_TRAVERSE(3.0000, 0.0000, 0.2500, 0.0000, 0.0000, 0.0000)
|
||||
N..... STRAIGHT_FEED(3.0000, 0.0000, -1.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... STRAIGHT_TRAVERSE(3.0000, 0.0000, 0.2500, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_MOTION_CONTROL_MODE(CANON_CONTINUOUS, 0.000000)
|
||||
N..... SET_NAIVECAM_TOLERANCE(0.0000)
|
||||
N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000)
|
||||
N..... SET_XY_ROTATION(0.0000)
|
||||
N..... SET_FEED_MODE(0, 0)
|
||||
N..... SET_FEED_RATE(0.0000)
|
||||
N..... STOP_SPINDLE_TURNING(0)
|
||||
N..... SET_SPINDLE_MODE(0 0.0000)
|
||||
N..... PALLET_SHUTTLE()
|
||||
N..... PROGRAM_END()
|
||||
N..... ON_RESET()
|
||||
N..... ON_RESET()
|
||||
13
wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/test.ngc
vendored
Normal file
13
wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/test.ngc
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
%
|
||||
( A simple O sub example )
|
||||
|
||||
F40
|
||||
G90 G0 X0 Y0 Z0.25
|
||||
M98 P1 L3
|
||||
M30
|
||||
|
||||
O1
|
||||
G91 G0 X1 ; Jog 1" along X (relative)
|
||||
G90 G99 G81 Z-1.0 R0.25 ; Drill to Z-1.0
|
||||
M99
|
||||
%
|
||||
3
wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/test.sh
vendored
Executable file
3
wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/test.sh
vendored
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
rs274 -g test.ngc | awk '{$1=""; print}'
|
||||
exit "${PIPESTATUS[0]}"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user