diff --git a/wasm-port/docs/compatibility-validation.md b/wasm-port/docs/compatibility-validation.md index a5d8e1b..59924b4 100644 --- a/wasm-port/docs/compatibility-validation.md +++ b/wasm-port/docs/compatibility-validation.md @@ -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. diff --git a/wasm-port/docs/drift-report.md b/wasm-port/docs/drift-report.md index 7f01641..00fb971 100644 --- a/wasm-port/docs/drift-report.md +++ b/wasm-port/docs/drift-report.md @@ -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. diff --git a/wasm-port/docs/linuxcnc-test-porting-tracker.md b/wasm-port/docs/linuxcnc-test-porting-tracker.md new file mode 100644 index 0000000..2e63812 --- /dev/null +++ b/wasm-port/docs/linuxcnc-test-porting-tracker.md @@ -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. diff --git a/wasm-port/docs/porting-steps-standalone.md b/wasm-port/docs/porting-steps-standalone.md index 16369c1..735c9df 100644 --- a/wasm-port/docs/porting-steps-standalone.md +++ b/wasm-port/docs/porting-steps-standalone.md @@ -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. diff --git a/wasm-port/docs/sim-configs-completion-plan.md b/wasm-port/docs/sim-configs-completion-plan.md new file mode 100644 index 0000000..69b022c --- /dev/null +++ b/wasm-port/docs/sim-configs-completion-plan.md @@ -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. diff --git a/wasm-port/docs/source-reuse-map.md b/wasm-port/docs/source-reuse-map.md index a6bfa7d..7d4f4f6 100644 --- a/wasm-port/docs/source-reuse-map.md +++ b/wasm-port/docs/source-reuse-map.md @@ -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 | diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_5axis_remap_execute_harness.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_5axis_remap_execute_harness.cpp index da82c23..94da53b 100644 --- a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_5axis_remap_execute_harness.cpp +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_5axis_remap_execute_harness.cpp @@ -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; diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_duplicate_oword_remap_harness.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_duplicate_oword_remap_harness.cpp new file mode 100644 index 0000000..b864c84 --- /dev/null +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_duplicate_oword_remap_harness.cpp @@ -0,0 +1,363 @@ +#define private public +#include "emc/rs274ngc/rs274ngc_interp.hh" +#undef private + +#include +#include +#include +#include +#include +#include +#include + +#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(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; +} diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_hal_adapter.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_hal_adapter.cpp index 9c409cd..6cbe363 100644 --- a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_hal_adapter.cpp +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_hal_adapter.cpp @@ -59,6 +59,18 @@ std::unordered_map> &pin_aliases() return values; } +std::unordered_map &digital_inputs() +{ + static std::unordered_map values; + return values; +} + +std::unordered_map &analog_inputs() +{ + static std::unordered_map values; + return values; +} + int lookup_hal_value(const char *name, std::unordered_map &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 *) diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_hal_adapter.hh b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_hal_adapter.hh index 80460e4..16f363d 100644 --- a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_hal_adapter.hh +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_hal_adapter.hh @@ -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 diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_harness.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_harness.cpp index c9eec1f..bc1fcea 100644 --- a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_harness.cpp +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_harness.cpp @@ -3,13 +3,19 @@ #undef private #include +#include +#include #include #include +#include #include #include #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 load_program(int argc, char **argv) @@ -117,11 +162,25 @@ std::vector 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 program = load_program(argc, argv); + const std::vector 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(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,7 +229,16 @@ 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)) { - break; + 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(); @@ -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"; diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cpp index af8ed23..0626ad7 100644 --- a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cpp +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cpp @@ -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 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 &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}; } diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_wasm.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_wasm.cpp index f0a54a1..06a8da9 100644 --- a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_wasm.cpp +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_wasm.cpp @@ -2,6 +2,7 @@ #include "emc/rs274ngc/rs274ngc_interp.hh" #undef private +#include #include #include #include @@ -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(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 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,7 +545,11 @@ 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"; } - break; + saw_error = true; + if (!continue_on_error) { + break; + } + continue; } const int execute_rc = interp.execute(); @@ -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) { diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_machine_config.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_machine_config.cpp new file mode 100644 index 0000000..0b623fa --- /dev/null +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_machine_config.cpp @@ -0,0 +1,280 @@ +#define private public +#include "emc/rs274ngc/rs274ngc_interp.hh" +#undef private + +#include +#include +#include +#include +#include +#include +#include + +#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(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('x')] = nullptr; + } + if (!(axis_mask & Interp::AXIS_MASK_Y)) { + interp._readers[static_cast('y')] = nullptr; + } + if (!(axis_mask & Interp::AXIS_MASK_Z)) { + interp._readers[static_cast('z')] = nullptr; + } + if (!(axis_mask & Interp::AXIS_MASK_A)) { + interp._readers[static_cast('a')] = nullptr; + } + if (!(axis_mask & Interp::AXIS_MASK_B)) { + interp._readers[static_cast('b')] = nullptr; + } + if (!(axis_mask & Interp::AXIS_MASK_C)) { + interp._readers[static_cast('c')] = nullptr; + } + if (!(axis_mask & Interp::AXIS_MASK_U)) { + interp._readers[static_cast('u')] = nullptr; + } + if (!(axis_mask & Interp::AXIS_MASK_V)) { + interp._readers[static_cast('v')] = nullptr; + } + if (!(axis_mask & Interp::AXIS_MASK_W)) { + interp._readers[static_cast('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 diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_machine_config.hh b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_machine_config.hh new file mode 100644 index 0000000..90bdfc5 --- /dev/null +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_machine_config.hh @@ -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 diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_runtime_state.hh b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_runtime_state.hh new file mode 100644 index 0000000..3b53af2 --- /dev/null +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_runtime_state.hh @@ -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 diff --git a/wasm-port/runtime/sdk/README.md b/wasm-port/runtime/sdk/README.md index 9807777..fbac913 100644 --- a/wasm-port/runtime/sdk/README.md +++ b/wasm-port/runtime/sdk/README.md @@ -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. diff --git a/wasm-port/runtime/sdk/src/linuxcnc-interp.js b/wasm-port/runtime/sdk/src/linuxcnc-interp.js index c38eba5..3661ba5 100644 --- a/wasm-port/runtime/sdk/src/linuxcnc-interp.js +++ b/wasm-port/runtime/sdk/src/linuxcnc-interp.js @@ -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); }, diff --git a/wasm-port/runtime/ui/ini-panel/app.js b/wasm-port/runtime/ui/ini-panel/app.js index d971856..e86a57b 100644 --- a/wasm-port/runtime/ui/ini-panel/app.js +++ b/wasm-port/runtime/ui/ini-panel/app.js @@ -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); } }); diff --git a/wasm-port/runtime/ui/ini-panel/index.html b/wasm-port/runtime/ui/ini-panel/index.html index 760fcaa..7620c50 100644 --- a/wasm-port/runtime/ui/ini-panel/index.html +++ b/wasm-port/runtime/ui/ini-panel/index.html @@ -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; } + } @@ -226,6 +278,28 @@
-
+

Run Monitor

+
+
+ + 0% +
+
idle
+
line -
+
-
+
+
X0.000
+
Y0.000
+
Z0.000
+
A0.000
+
B0.000
+
C0.000
+
U0.000
+
V0.000
+
W0.000
+
+
+

Canonical Events

diff --git a/wasm-port/tests/browser/ini_panel_smoke.html b/wasm-port/tests/browser/ini_panel_smoke.html index 90e025f..17a314c 100644 --- a/wasm-port/tests/browser/ini_panel_smoke.html +++ b/wasm-port/tests/browser/ini_panel_smoke.html @@ -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 })); diff --git a/wasm-port/tests/browser/interp_smoke.html b/wasm-port/tests/browser/interp_smoke.html index 4a6a0dd..a4abc1b 100644 --- a/wasm-port/tests/browser/interp_smoke.html +++ b/wasm-port/tests/browser/interp_smoke.html @@ -36,6 +36,7 @@ INTERP_ERROR_FIXTURES, INTERP_INI_FIXTURE, INTERP_POSITION_PARAMS_FILE_FIXTURE, + INTERP_SPINDLE_ORIENT_OFFSET_FIXTURE, } from "../fixtures/interp-fixture-matrix.mjs"; const status = document.getElementById("status"); @@ -93,8 +94,28 @@ } } - async function writeFetchedTextFile(interp, sourcePath, wasmPath) { + async function writeFetchedTextFile(interp, sourcePath, wasmPath, options = {}) { interp.writeTextFile(wasmPath, await fetchText(sourcePath)); + if (options.executable) { + interp.module.FS.chmod(wasmPath, 0o755); + } + } + + async function loadSimMachineFiles(machineRel, files, executableFiles = []) { + const sourceDir = `../../vendor/linuxcnc/configs/sim/${machineRel}`; + const wasmDir = `/work/browser-sim/${machineRel}`; + const executableSet = new Set(executableFiles); + const machineFiles = []; + + for (const filename of files) { + machineFiles.push({ + path: `${wasmDir}/${filename}`, + text: await fetchText(`${sourceDir}/${filename}`), + executable: executableSet.has(filename), + }); + } + + return { wasmDir, files: machineFiles }; } async function writeFiveAxisTrtMachineFiles(interp) { @@ -135,6 +156,21 @@ `${sourceDir}/demos/xyzbc_switchkins.ngc`, `${wasmDir}/demos/xyzbc_switchkins.ngc`, ); + await writeFetchedTextFile( + interp, + `${sourceDir}/demos/xyzac_switchkins_test_1.ngc`, + `${wasmDir}/demos/xyzac_switchkins_test_1.ngc`, + ); + await writeFetchedTextFile( + interp, + `${sourceDir}/demos/xyzac_switchkins_test_2.ngc`, + `${wasmDir}/demos/xyzac_switchkins_test_2.ngc`, + ); + await writeFetchedTextFile( + interp, + `${sourceDir}/demos/xyzac_switchkins_test_3.ngc`, + `${wasmDir}/demos/xyzac_switchkins_test_3.ngc`, + ); await writeFetchedTextFile( interp, `${sourceDir}/demos/boat-xyzac.ngc`, @@ -198,6 +234,47 @@ return wasmDir; } + async function writeRemapRegressionFiles(interp, name, files) { + const sourceDir = `../../vendor/linuxcnc/tests/remap/${name}`; + const wasmDir = `/work/browser-remap/${name}`; + + for (const filename of files) { + await writeFetchedTextFile(interp, `${sourceDir}/${filename}`, `${wasmDir}/${filename}`); + } + + return wasmDir; + } + + async function writeInterpRegressionFile(interp, name, filename) { + const sourceDir = `../../vendor/linuxcnc/tests/interp/${name}`; + const wasmDir = `/work/browser-interp/${name}`; + + await writeFetchedTextFile(interp, `${sourceDir}/${filename}`, `${wasmDir}/${filename}`); + + return `${wasmDir}/${filename}`; + } + + async function writeInterpRegressionFiles(interp, name, files) { + const sourceDir = `../../vendor/linuxcnc/tests/interp/${name}`; + const wasmDir = `/work/browser-interp/${name}`; + + for (const filename of files) { + await writeFetchedTextFile(interp, `${sourceDir}/${filename}`, `${wasmDir}/${filename}`); + } + + return wasmDir; + } + + async function runVendorNcFile(interp, filename) { + const wasmPath = `/work/browser-nc-files/${filename}`; + await writeFetchedTextFile( + interp, + `../../vendor/linuxcnc/nc_files/${filename}`, + wasmPath, + ); + return interp.runFile(wasmPath); + } + async function verifyRejects(fixtureName, operation, expectedPattern) { try { await operation(); @@ -210,6 +287,13 @@ throw new Error(`${fixtureName}: expected rejection`); } + const interpPrints = []; + function runWithCapturedPrints(operation) { + interpPrints.length = 0; + const output = operation(); + return { output, prints: interpPrints.join("\n") }; + } + try { const interp = await createLinuxCncInterpSdk({ locateFile(path) { @@ -218,7 +302,9 @@ } return path; }, - print() {}, + print(message) { + interpPrints.push(message); + }, printErr(message) { console.error(message); }, @@ -359,6 +445,28 @@ baselineIniExpectedText, ); + const spindleOrientOffsetProgramText = await fetchText( + `../fixtures/gcode/${INTERP_SPINDLE_ORIENT_OFFSET_FIXTURE}.ngc`, + ); + const spindleOrientOffsetExpectedText = ( + await fetchText(`../fixtures/canon/${INTERP_SPINDLE_ORIENT_OFFSET_FIXTURE}.events`) + ).trimEnd(); + const spindleOrientOffsetIniPath = "/work/browser-spindle-orient-offset.ini"; + interp.writeTextFile( + spindleOrientOffsetIniPath, + await fetchText("../fixtures/ini/spindle_orient_offset.ini"), + ); + const disableFanucStyleSubIniPath = "/work/browser-disable-fanuc-style-sub.ini"; + interp.writeTextFile( + disableFanucStyleSubIniPath, + await fetchText("../fixtures/ini/disable_fanuc_style_sub.ini"), + ); + verifyExpectedOutput( + INTERP_SPINDLE_ORIENT_OFFSET_FIXTURE, + interp.runProgramWithIni(spindleOrientOffsetProgramText, spindleOrientOffsetIniPath), + spindleOrientOffsetExpectedText, + ); + const coordinateOffsetsText = await fetchText( `../fixtures/gcode/${INTERP_COORDINATE_OFFSETS_FILE_FIXTURE}.ngc`, ); @@ -407,6 +515,24 @@ namedParamExpectedText, ); + const iniToolTableDir = "/work/browser-ini-tool-table"; + const iniToolTableIniPath = `${iniToolTableDir}/ini_tool_table.ini`; + const iniToolTableProgramPath = `${iniToolTableDir}/ini_tool_table.ngc`; + interp.writeTextFile(iniToolTableIniPath, await fetchText("../fixtures/ini/ini_tool_table.ini")); + interp.writeTextFile( + `${iniToolTableDir}/ini_tool_table.tbl`, + await fetchText("../fixtures/ini/ini_tool_table.tbl"), + ); + interp.writeTextFile( + iniToolTableProgramPath, + await fetchText("../fixtures/gcode/ini_tool_table.ngc"), + ); + verifyExpectedOutput( + "browser_ini_tool_table_file", + interp.runFileWithIni(iniToolTableProgramPath, iniToolTableIniPath), + (await fetchText("../fixtures/canon/ini_tool_table.events")).trimEnd(), + ); + const baselineIniPath = `/work/${INTERP_BASELINE_INI_FIXTURE}.ngc`; interp.writeTextFile(baselineIniPath, baselineIniProgramText); verifyExpectedOutput( @@ -415,6 +541,196 @@ baselineIniExpectedText, ); + const spindleOrientOffsetPath = `/work/${INTERP_SPINDLE_ORIENT_OFFSET_FIXTURE}.ngc`; + interp.writeTextFile(spindleOrientOffsetPath, spindleOrientOffsetProgramText); + verifyExpectedOutput( + `${INTERP_SPINDLE_ORIENT_OFFSET_FIXTURE}_file`, + interp.runFileWithIni(spindleOrientOffsetPath, spindleOrientOffsetIniPath), + spindleOrientOffsetExpectedText, + ); + + const disableFanucStyleSubPath = "/work/browser-disable_fanuc_style_sub_m98.ngc"; + interp.writeTextFile( + disableFanucStyleSubPath, + await fetchText("../fixtures/gcode/disable_fanuc_style_sub_m98.ngc"), + ); + verifyExpectedOutput( + "browser_disable_fanuc_style_sub_m98_file", + interp.runFileWithIni(disableFanucStyleSubPath, disableFanucStyleSubIniPath), + [ + "file_open=0", + "file_saw_error=1", + "file_error_text=DISABLE_FANUC_STYLE_SUB set in INI file, but found m98", + ].join("\n"), + ); + + verifyExpectedOutput( + "browser_nc_files_arcspiral", + await runVendorNcFile(interp, "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( + "browser_nc_files_hole_circle", + await runVendorNcFile(interp, "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( + "browser_nc_files_factorial", + await runVendorNcFile(interp, "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( + "browser_nc_files_m6demo", + await runVendorNcFile(interp, "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"), + ); + + const foam = await loadSimMachineFiles("axis/foam", [ + "axis_foam.ini", + "foam.ngc", + ]); + verifyExpectedOutput( + "browser_sim_axis_foam_uv", + 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 bridgeMillSim = await loadSimMachineFiles( + "axis/vismach/5axis/bridgemill", + [ + "5axis.ini", + "5axis.tbl", + "5axisgui.ngc", + "remap_subs/428remap.ngc", + "remap_subs/429remap.ngc", + "remap_subs/430remap.ngc", + ], + ); + verifyExpectedOutput( + "browser_sim_axis_bridgemill_w", + interp.runSimConfigProgram({ + files: bridgeMillSim.files, + programPath: `${bridgeMillSim.wasmDir}/5axisgui.ngc`, + iniPath: `${bridgeMillSim.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 = await loadSimMachineFiles( + "axis/geometry", + [ + "M110", + "xyzc.ini", + "xyzc.ngc", + ], + ["M110"], + ); + verifyExpectedOutput( + "browser_sim_axis_geometry_xyzc_user_m110", + 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 = await loadSimMachineFiles( + "axis/external_offsets", + [ + "M111", + "dyn_demo.ngc", + "dynamic_offsets.ini", + ], + ["M111"], + ); + verifyExpectedOutput( + "browser_sim_axis_external_offsets_user_m111", + 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"), + ); + const fiveAxisTrtDir = await writeFiveAxisTrtMachineFiles(interp); verifyExpectedOutput( "browser_fiveaxis_xyzac_switchkins", @@ -458,6 +774,78 @@ "fiveaxis_linuxcnc_remap_file_execute=1", ].join("\n"), ); + verifyExpectedOutput( + "browser_fiveaxis_xyzac_switchkins_test_1", + interp.runFiveAxisRemapFile( + `${fiveAxisTrtDir}/demos/xyzac_switchkins_test_1.ngc`, + `${fiveAxisTrtDir}/xyzac-trt.ini`, + ), + [ + "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=248", + "fiveaxis_file_execute_count=248", + "fiveaxis_file_finish_count=9", + "fiveaxis_file_final_rc=1", + "fiveaxis_file_reached_exit=1", + "fiveaxis_hal_switchkins: rc=0 found=1 value=0", + "fiveaxis_linuxcnc_remap_file_execute=1", + ].join("\n"), + ); + verifyExpectedOutput( + "browser_fiveaxis_xyzac_switchkins_test_2", + interp.runFiveAxisRemapFile( + `${fiveAxisTrtDir}/demos/xyzac_switchkins_test_2.ngc`, + `${fiveAxisTrtDir}/xyzac-trt.ini`, + ), + [ + "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=120", + "fiveaxis_file_execute_count=120", + "fiveaxis_file_finish_count=3", + "fiveaxis_file_final_rc=1", + "fiveaxis_file_reached_exit=1", + "fiveaxis_hal_switchkins: rc=0 found=1 value=0", + "fiveaxis_linuxcnc_remap_file_execute=1", + ].join("\n"), + ); + verifyExpectedOutput( + "browser_fiveaxis_xyzac_switchkins_test_3", + interp.runFiveAxisRemapFile( + `${fiveAxisTrtDir}/demos/xyzac_switchkins_test_3.ngc`, + `${fiveAxisTrtDir}/xyzac-trt.ini`, + ), + [ + "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=86", + "fiveaxis_file_execute_count=86", + "fiveaxis_file_finish_count=3", + "fiveaxis_file_final_rc=1", + "fiveaxis_file_reached_exit=1", + "fiveaxis_hal_switchkins: rc=0 found=1 value=0", + "fiveaxis_linuxcnc_remap_file_execute=1", + ].join("\n"), + ); verifyExpectedOutput( "browser_fiveaxis_boat_xyzac", interp.runFiveAxisRemapFile( @@ -574,6 +962,1043 @@ ].join("\n"), ); + const duplicateOwordDir = await writeRemapRegressionFiles(interp, "duplicate-o-word", [ + "test.ini", + "test.ngc", + "rm207.ngc", + "rm208.ngc", + ]); + verifyExpectedOutput( + "browser_duplicate_oword_remap", + interp.runRemapFile( + `${duplicateOwordDir}/test.ngc`, + `${duplicateOwordDir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parse_remap_2=0", + "remap_parsed_remap_count=2", + "remap_remaps_ready=1", + "remap_file_open=0", + "remap_file_read_count=31", + "remap_file_execute_count=31", + "remap_file_finish_count=0", + "remap_file_final_rc=3", + "remap_file_reached_endfile=1", + "remap_canon_event=MESSAGE: executing m207: run remapped m208 before o", + "remap_canon_event=MESSAGE: rm207 running remapped m208", + "remap_canon_event=MESSAGE: rm208 starting and done", + "remap_canon_event=FINISH", + "remap_linuxcnc_file_execute=1", + ].join("\n"), + ); + + const failArgs0Dir = await writeRemapRegressionFiles(interp, "fail/args.0", [ + "test.ini", + "test.ngc", + "rm400.ngc", + ]); + verifyExpectedOutput( + "browser_fail_args_0_remap", + interp.runRemapFile( + `${failArgs0Dir}/test.ngc`, + `${failArgs0Dir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parsed_remap_count=1", + "remap_remaps_ready=1", + "remap_file_open=0", + "remap_file_saw_error=0", + "remap_canon_event=MESSAGE: M400 call_level= 1.000000 remap_level=1.000000", + "remap_canon_event=MESSAGE: P word set: 47.110000", + "remap_canon_event=MESSAGE: Q word set: 8.150000", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), + ); + + const failArgs1Dir = await writeRemapRegressionFiles(interp, "fail/args.1", [ + "test.ini", + "test.ngc", + "rm400.ngc", + ]); + verifyExpectedOutput( + "browser_fail_args_1_remap", + interp.runRemapFileContinueOnError( + `${failArgs1Dir}/test.ngc`, + `${failArgs1Dir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_file_execute_1=5", + "remap_file_error_text=user-defined M400: missing: Q", + "remap_file_saw_error=1", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), + ); + + const failArgs2Dir = await writeRemapRegressionFiles(interp, "fail/args.2", [ + "test.ini", + "test.ngc", + "rm400.ngc", + ]); + verifyExpectedOutput( + "browser_fail_args_2_remap", + interp.runRemapFileContinueOnError( + `${failArgs2Dir}/test.ngc`, + `${failArgs2Dir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_file_execute_1=5", + "remap_file_error_text=user-defined M400: missing: P,Q", + "remap_file_saw_error=1", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), + ); + + const failBodyNgcDir = await writeRemapRegressionFiles(interp, "fail/body-ngc", [ + "test.ini", + "test.ngc", + "rm400.ngc", + ]); + verifyExpectedOutput( + "browser_fail_body_ngc_remap", + interp.runRemapFileContinueOnError( + `${failBodyNgcDir}/test.ngc`, + `${failBodyNgcDir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_file_read_5=5", + "remap_file_error_text=Attempt to divide by zero", + "remap_file_saw_error=1", + "remap_canon_event=MESSAGE: before M400: call_level= 0.000000 remap_level=0.000000", + "remap_canon_event=MESSAGE: in rm400: call_level= 1.000000 remap_level=1.000000", + "remap_canon_event=MESSAGE: after failed M400: call_level= 0.000000 remap_level=0.000000", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), + ); + + const m30InteractionDir = await writeRemapRegressionFiles(interp, "m30-interaction", [ + "test.ini", + "test.ngc", + "rm400.ngc", + ]); + verifyExpectedOutput( + "browser_m30_interaction_remap", + interp.runRemapFile( + `${m30InteractionDir}/test.ngc`, + `${m30InteractionDir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parsed_remap_count=1", + "remap_remaps_ready=1", + "remap_file_open=0", + "remap_file_read_count=4", + "remap_file_execute_count=4", + "remap_file_finish_count=0", + "remap_file_final_rc=1", + "remap_file_reached_exit=1", + "remap_canon_event=MESSAGE: m400 call_level=1.000000 remap_level=1.000000 line=2.000000", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), + ); + + const nestedRemapsOwordDir = await writeRemapRegressionFiles( + interp, + "nested-remaps-oword", + [ + "test.ini", + "test.ngc", + "rm400.ngc", + "rm401.ngc", + "rm402.ngc", + "rm403.ngc", + ], + ); + verifyExpectedOutput( + "browser_nested_remaps_oword_remap", + interp.runRemapFile( + `${nestedRemapsOwordDir}/test.ngc`, + `${nestedRemapsOwordDir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parse_remap_2=0", + "remap_parse_remap_3=0", + "remap_parse_remap_4=0", + "remap_parsed_remap_count=4", + "remap_remaps_ready=1", + "remap_file_open=0", + "remap_file_read_count=21", + "remap_file_execute_count=21", + "remap_file_finish_count=0", + "remap_file_final_rc=3", + "remap_file_reached_endfile=1", + "remap_canon_event=MESSAGE: main call_level=0.000000 remap_level=0.000000 line=2.000000", + "remap_canon_event=MESSAGE: m400 handler pre call_level=1.000000 remap_level=1.000000 line=2.000000", + "remap_canon_event=MESSAGE: m401 handler pre call_level=2.000000 remap_level=2.000000 line=2.000000", + "remap_canon_event=MESSAGE: m402 handler pre call_level=3.000000 remap_level=3.000000 line=2.000000", + "remap_canon_event=MESSAGE: m403 handler pre call_level=4.000000 remap_level=4.000000 line=2.000000", + "remap_canon_event=MESSAGE: m400 handler post call_level=1.000000 remap_level=1.000000 line=4.000000", + "remap_canon_event=FINISH", + "remap_linuxcnc_file_execute=1", + ].join("\n"), + ); + + const posargs0Dir = await writeRemapRegressionFiles(interp, "posargs.0", [ + "test.ini", + "test.ngc", + "rg881.ngc", + ]); + verifyExpectedOutput( + "browser_posargs_0_remap", + interp.runRemapFile( + `${posargs0Dir}/test.ngc`, + `${posargs0Dir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parsed_remap_count=1", + "remap_remaps_ready=1", + "remap_file_open=0", + "remap_file_read_count=19", + "remap_file_execute_count=19", + "remap_file_finish_count=0", + "remap_file_final_rc=1", + "remap_file_reached_exit=1", + "remap_canon_event=MESSAGE: in rg881: n_args=3.000000 [1.000000] [2.000000] [3.000000] [0.000000] [0.000000]", + "remap_canon_event=MESSAGE: in rg881: n_args=4.000000 [1.000000] [2.000000] [3.000000] [4.000000] [0.000000]", + "remap_canon_event=MESSAGE: in rg881: n_args=4.000000 [1.000000] [2.000000] [3.000000] [5.000000] [0.000000]", + "remap_canon_event=MESSAGE: in rg881: n_args=5.000000 [1.000000] [2.000000] [3.000000] [4.000000] [5.000000]", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), + ); + + const sequencingDir = await writeRemapRegressionFiles(interp, "sequencing", [ + "test.ini", + "test.ngc", + "rg881.ngc", + "rm405.ngc", + "rm406.ngc", + "rm407.ngc", + "rm408.ngc", + "rm409.ngc", + "rm410.ngc", + ]); + verifyExpectedOutput( + "browser_sequencing_remap", + interp.runRemapFile( + `${sequencingDir}/test.ngc`, + `${sequencingDir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parse_remap_2=0", + "remap_parse_remap_3=0", + "remap_parse_remap_4=0", + "remap_parse_remap_5=0", + "remap_parse_remap_6=0", + "remap_parse_remap_7=0", + "remap_parsed_remap_count=7", + "remap_remaps_ready=1", + "remap_file_open=0", + "remap_file_read_count=10084", + "remap_file_execute_count=10084", + "remap_file_final_rc=1", + "remap_file_reached_exit=1", + "remap_canon_event=MESSAGE: seq=1.000000", + "remap_canon_event=MESSAGE: seq=5.000000", + "remap_canon_event=MESSAGE: seq=6.000000", + "remap_canon_event=MESSAGE: seq=7.000000", + "remap_canon_event=MESSAGE: seq=8.000000 - reset to 1", + "remap_canon_event=MESSAGE: seq=8.000000", + "remap_canon_event=MESSAGE: seq=9.000000", + "remap_canon_event=MESSAGE: seq=10.000000 - reset to 1", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), + ); + + const remapIoDir = await writeRemapRegressionFiles(interp, "remap-io", [ + "test-ngc.ini", + "io_input_m66.ngc", + "io_output_m62.ngc", + "io_output_m63.ngc", + "io_output_m64.ngc", + "io_output_m65.ngc", + "io_output_m67.ngc", + "io_output_m68.ngc", + ]); + interp.writeTextFile(`${remapIoDir}/simpockets.tbl`, "T2 P2 Z0 ;remap-io tool\n"); + verifyExpectedOutput( + "browser_remap_io_ngc_mdi", + interp.runRemapIoMdiSequence(`${remapIoDir}/test-ngc.ini`), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parse_remap_7=0", + "remap_parsed_remap_count=7", + "remap_remaps_ready=1", + "remap_mdi_M62 P1_execute_0=0", + "remap_mdi_M66 P1_execute_0=2", + "remap_mdi_M66 P1_execute_1=0", + "remap_mdi_M66 E1 L0_execute_0=2", + "remap_mdi_M66 E1 L0_execute_1=0", + "remap_mdi_parameter_5399=42.13", + "remap_mdi_parameter_5399=-13.42", + "remap_mdi_canon_event=SET_MOTION_OUTPUT_BIT index=0", + "remap_mdi_canon_event=CLEAR_MOTION_OUTPUT_BIT index=0", + "remap_mdi_canon_event=SET_AUX_OUTPUT_BIT index=0", + "remap_mdi_canon_event=CLEAR_AUX_OUTPUT_BIT index=0", + "remap_mdi_canon_event=WAIT index=0 input_type=1 wait_type=0 timeout=0", + "remap_mdi_canon_event=WAIT index=0 input_type=0 wait_type=0 timeout=0", + "remap_mdi_canon_event=SET_MOTION_OUTPUT_VALUE index=0 value=42.13", + "remap_mdi_canon_event=SET_AUX_OUTPUT_VALUE index=0 value=-13.42", + "remap_io_ngc_linuxcnc_mdi_sequence=1", + ].join("\n"), + ); + + const doWhileBreakPath = await writeInterpRegressionFile( + interp, + "do-while-break", + "test.ngc", + ); + verifyExpectedOutput( + "browser_interp_do_while_break", + interp.runFile(doWhileBreakPath), + [ + "file_open=0", + "file_read_count=30", + "file_execute_count=30", + "canon_event=MESSAGE: must-execute-outer", + "canon_event=MESSAGE: must-execute-nested", + "canon_event=MESSAGE: must-execute-inner", + "canon_event=MESSAGE: post-inner-while", + "canon_event=MESSAGE: post-nested-while", + "canon_event=MESSAGE: post-outer-while", + "canon_event=PROGRAM_END", + "absent=canon_event=MESSAGE: do-not-execute", + ].join("\n"), + ); + + const owordBug315Path = await writeInterpRegressionFile( + interp, + "oword-bug315", + "test.ngc", + ); + verifyExpectedOutput( + "browser_interp_oword_bug315", + interp.runFile(owordBug315Path), + [ + "file_open=0", + "file_read_count=23", + "file_execute_count=23", + "canon_event=MESSAGE: running sub", + "canon_event=MESSAGE: breaking out of sub", + "canon_event=MESSAGE: done", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const owordBug315P2Path = await writeInterpRegressionFile( + interp, + "oword-bug315-p2", + "test.ngc", + ); + verifyExpectedOutput( + "browser_interp_oword_bug315_p2", + interp.runFile(owordBug315P2Path), + [ + "file_open=0", + "file_read_count=26", + "file_execute_count=26", + "canon_event=STRAIGHT_TRAVERSE line=7 x=2 y=2 z=2", + "canon_event=MESSAGE: executing this one", + "canon_event=PROGRAM_END", + "absent=canon_event=MESSAGE: not executing this one", + ].join("\n"), + ); + + const existsPath = await writeInterpRegressionFile(interp, "exists", "test.ngc"); + verifyExpectedOutput( + "browser_interp_exists", + interp.runFile(existsPath), + [ + "file_open=0", + "file_read_count=7", + "file_execute_count=7", + "canon_event=STRAIGHT_TRAVERSE line=2 x=1 y=0 z=1", + "canon_event=COMMENT: comment", + "canon_event=STRAIGHT_TRAVERSE line=6 x=1 y=0 z=0", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const returnValuePath = await writeInterpRegressionFile( + interp, + "return-value", + "test.ngc", + ); + verifyExpectedOutput( + "browser_interp_return_value", + interp.runFile(returnValuePath), + [ + "file_open=0", + "file_read_count=75", + "file_execute_count=75", + "canon_event=MESSAGE: line 6.000000: _value: - expected 0.000000, got 0.000000", + "canon_event=MESSAGE: line 28.000000: call with arg1=2.000000 expect 246.000000, got 246.000000", + "canon_event=MESSAGE: line 37.000000: call with arg1=-1.000000 expect 0.000000, got 0.000000", + "canon_event=MESSAGE: line 47.000000: call with arg1=0.000000 expect 4712.000000, got 4712.000000", + "canon_event=MESSAGE: line 53.000000: _value=4712.000000 - expected 4712.000000", + "canon_event=PROGRAM_END", + "absent=fail:", + ].join("\n"), + ); + + const subsFollowMainPath = await writeInterpRegressionFile( + interp, + "subs-follow-main", + "test.ngc", + ); + verifyExpectedOutput( + "browser_interp_subs_follow_main", + interp.runFile(subsFollowMainPath), + [ + "file_open=0", + "file_read_count=9", + "file_execute_count=9", + "canon_event=COMMENT: Subs may follow main program ", + "canon_event=PALLET_SHUTTLE", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const fractionalLinenumbersPath = await writeInterpRegressionFile( + interp, + "fractional-linenumbers", + "test.ngc", + ); + verifyExpectedOutput( + "browser_interp_fractional_linenumbers", + interp.runFile(fractionalLinenumbersPath), + [ + "file_open=0", + "file_read_count=4", + "file_execute_count=4", + "canon_event=SET_SPINDLE_SPEED spindle=0 speed=300", + "canon_event=SET_SPINDLE_SPEED spindle=0 speed=600", + "canon_event=SET_SPINDLE_SPEED spindle=0 speed=1200", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const namedparamBug424Path = await writeInterpRegressionFile( + interp, + "namedparam-bug424", + "test.ngc", + ); + verifyExpectedOutput( + "browser_interp_namedparam_bug424", + interp.runFile(namedparamBug424Path), + [ + "file_open=0", + "file_read_count=6", + "file_execute_count=6", + "setup.current_x=2", + "setup.current_y=3", + "setup.current_z=4", + "canon_event=USE_LENGTH_UNITS units=1", + "canon_event=STRAIGHT_TRAVERSE line=5 x=2 y=3 z=4", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const g6164Path = await writeInterpRegressionFile(interp, "g6164", "test.ngc"); + verifyExpectedOutput( + "browser_interp_g6164", + interp.runFile(g6164Path), + [ + "file_open=0", + "file_read_count=6", + "file_execute_count=6", + "canon_event=SET_MOTION_CONTROL_MODE mode=3 tolerance=0", + "canon_event=SET_NAIVECAM_TOLERANCE tolerance=0", + "canon_event=SET_MOTION_CONTROL_MODE mode=3 tolerance=1", + "canon_event=SET_NAIVECAM_TOLERANCE tolerance=1", + "canon_event=SET_NAIVECAM_TOLERANCE tolerance=2", + "canon_event=SET_MOTION_CONTROL_MODE mode=2 tolerance=0", + "canon_event=SET_MOTION_CONTROL_MODE mode=1 tolerance=0", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const rotationAbsPtsPath = await writeInterpRegressionFile( + interp, + "rotation/abs-pts", + "test.ngc", + ); + const rotationAbsPtsOutput = interp.runFile(rotationAbsPtsPath); + verifyExpectedOutput( + "browser_interp_rotation_abs_pts", + rotationAbsPtsOutput, + [ + "file_open=0", + "file_read_count=192", + "file_execute_count=192", + "file_saw_error=0", + "canon_event=MESSAGE: 0.000000 0.000000 0.000000", + "canon_event=MESSAGE: 1.000000 2.000000 3.000000", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + if ( + (rotationAbsPtsOutput.match(/canon_event=MESSAGE: 0\.000000 0\.000000 0\.000000/g) || []) + .length !== 14 + ) { + throw new Error("browser_interp_rotation_abs_pts: zero absolute-position message count"); + } + if ( + (rotationAbsPtsOutput.match(/canon_event=MESSAGE: 1\.000000 2\.000000 3\.000000/g) || []) + .length !== 14 + ) { + throw new Error("browser_interp_rotation_abs_pts: target absolute-position message count"); + } + + const rotationG28Path = await writeInterpRegressionFile(interp, "rotation/g28", "g28.ngc"); + const rotationG28Output = interp.runFile(rotationG28Path); + verifyExpectedOutput( + "browser_interp_rotation_g28", + rotationG28Output, + [ + "file_open=0", + "file_read_count=13", + "file_execute_count=13", + "file_saw_error=0", + "canon_event=SET_XY_ROTATION rotation=45", + "canon_event=COMMENT: G55 G28", + "canon_event=STRAIGHT_TRAVERSE line=9 x=10 y=10 z=0", + "canon_event=COMMENT: G56 G28", + "canon_event=STRAIGHT_TRAVERSE line=14 x=0 y=14.1421 z=0 a=1", + "canon_event=FINISH", + ].join("\n"), + ); + if (!/canon_event=STRAIGHT_TRAVERSE line=14 x=(0|[0-9.e-]+) y=14\.1421 z=0 a=0/.test(rotationG28Output)) { + throw new Error("browser_interp_rotation_g28: G56 G28 final machine point"); + } + + const rotationG53Path = await writeInterpRegressionFile(interp, "rotation/g53", "g53.ngc"); + const rotationG53Output = interp.runFile(rotationG53Path); + verifyExpectedOutput( + "browser_interp_rotation_g53", + rotationG53Output, + [ + "file_open=0", + "file_read_count=17", + "file_execute_count=17", + "file_saw_error=0", + "canon_event=SET_XY_ROTATION rotation=45", + "canon_event=COMMENT: g53 + g55 to 1,1", + "canon_event=COMMENT: g53 + g55 + g92 to 1,1", + "canon_event=STRAIGHT_TRAVERSE line=13 x=0 y=0 z=0", + "canon_event=COMMENT: g53 + g56 + g92 to 1,1", + "canon_event=STRAIGHT_TRAVERSE line=18 x=-0.414214 y=1 z=0 a=1", + "canon_event=FINISH", + ].join("\n"), + ); + if (!/canon_event=STRAIGHT_TRAVERSE line=8 x=1\.41421 y=([0-9.e-]+) z=0/.test(rotationG53Output)) { + throw new Error("browser_interp_rotation_g53: rotated G53 endpoint"); + } + + const iniparamDir = await writeInterpRegressionFiles( + interp, + "iniparam", + [ + "test.ini", + "test.ngc", + ], + ); + verifyExpectedOutput( + "browser_interp_iniparam", + interp.runFileWithIniContinueOnError( + `${iniparamDir}/test.ngc`, + `${iniparamDir}/test.ini`, + ), + [ + "file_open=0", + "file_read_count=9", + "file_execute_count=8", + "file_saw_error=1", + "file_error_text=Named parameter #<_ini[nosuchsection]nosuchname> not defined", + "setup.current_x=10", + "setup.current_y=20", + "setup.current_z=30", + "canon_event=STRAIGHT_TRAVERSE line=1 x=10 y=20 z=30", + "canon_event=MESSAGE: position now: 10.000000 20.000000 30.000000", + "canon_event=MESSAGE: not in INI: ######", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const iniparamFailassignDir = await writeInterpRegressionFiles( + interp, + "iniparam-failassign", + [ + "test.ini", + "test.ngc", + ], + ); + verifyExpectedOutput( + "browser_interp_iniparam_failassign", + interp.runFileWithIni( + `${iniparamFailassignDir}/test.ngc`, + `${iniparamFailassignDir}/test.ini`, + ), + [ + "file_open=0", + "file_execute_1=5", + "file_read_count=1", + "file_execute_count=1", + "file_saw_error=1", + "file_error_text=Cannot assign to read-only parameter #<_ini[vars]toolchange_x>", + "absent=canon_event=MESSAGE: notreached", + ].join("\n"), + ); + + const subCallFromSubDir = await writeInterpRegressionFiles( + interp, + "sub-call-from-sub", + [ + "test.ini", + "test.ngc", + "subs/caller.ngc", + "subs/helper.ngc", + ], + ); + verifyExpectedOutput( + "browser_interp_sub_call_from_sub", + interp.runFileWithIni( + `${subCallFromSubDir}/test.ngc`, + `${subCallFromSubDir}/test.ini`, + ), + [ + "file_open=0", + "file_read_count=10", + "file_execute_count=10", + "canon_event=COMMENT: Test: calling a sub from within another sub is valid", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const sequenceNumberDir = await writeInterpRegressionFiles( + interp, + "sequence-number", + [ + "test.ini", + "test.ngc", + "rm400.ngc", + ], + ); + verifyExpectedOutput( + "browser_interp_sequence_number", + interp.runFileWithIni( + `${sequenceNumberDir}/test.ngc`, + `${sequenceNumberDir}/test.ini`, + ), + [ + "file_open=0", + "file_read_count=13", + "file_execute_count=13", + "canon_event=MESSAGE: main: line=7.000000 - expect 7", + "canon_event=MESSAGE: in rm400.ngc line=2.000000 - expect 2", + "canon_event=MESSAGE: main: line=9.000000 - expect 9", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const nestedSubErrorDir = await writeInterpRegressionFiles( + interp, + "nested-sub-error", + [ + "test.ini", + "test.ngc", + "subs/nested.ngc", + ], + ); + verifyExpectedOutput( + "browser_interp_nested_sub_error", + interp.runFileWithIni( + `${nestedSubErrorDir}/test.ngc`, + `${nestedSubErrorDir}/test.ini`, + ), + [ + "file_open=0", + "file_read_4=5", + "file_error_text=Nested subroutine definition: 'O100 sub' found inside called subroutine 'Onested'", + "file_read_count=4", + "file_execute_count=3", + "canon_event=COMMENT: Test: nested sub definition inside named sub should error", + "absent=canon_event=PROGRAM_END", + ].join("\n"), + ); + + const nestedSubInFileErrorDir = await writeInterpRegressionFiles( + interp, + "nested-sub-in-file-error", + [ + "test.ini", + "test.ngc", + "subs/sequential.ngc", + ], + ); + verifyExpectedOutput( + "browser_interp_nested_sub_in_file_error", + interp.runFileWithIni( + `${nestedSubInFileErrorDir}/test.ngc`, + `${nestedSubInFileErrorDir}/test.ini`, + ), + [ + "file_open=0", + "file_execute_5=5", + "file_error_text=Subroutine 'O200' not found -- not in offset table and no file '", + "file_read_count=5", + "file_execute_count=5", + "canon_event=COMMENT: Test: numbered sub after named endsub in same file should error", + "canon_event=MESSAGE: sequential main: 7.000000 8.000000 9.000000", + "absent=canon_event=PROGRAM_END", + ].join("\n"), + ); + + const owordUnwindDir = await writeInterpRegressionFiles( + interp, + "oword-unwind", + [ + "test.ini", + "test.ngc", + "fail.ngc", + ], + ); + verifyExpectedOutput( + "browser_interp_oword_unwind", + interp.runFileWithIniContinueOnError( + `${owordUnwindDir}/test.ngc`, + `${owordUnwindDir}/test.ini`, + ), + [ + "file_open=0", + "file_read_5=5", + "file_read_10=5", + "file_read_count=11", + "file_execute_count=9", + "file_saw_error=1", + "canon_event=MESSAGE: pre divide-by-zero", + "canon_event=PROGRAM_END", + "absent=canon_event=MESSAGE: post divide-by-zero", + ].join("\n"), + ); + + const abortHotCommentDir = await writeInterpRegressionFiles( + interp, + "abort-hot-comment", + [ + "test.ini", + "test.ngc", + ], + ); + verifyExpectedOutput( + "browser_interp_abort_hot_comment", + interp.runFileWithIniContinueOnError( + `${abortHotCommentDir}/test.ngc`, + `${abortHotCommentDir}/test.ini`, + ), + [ + "file_open=0", + "file_read_count=125", + "file_execute_count=125", + "file_saw_error=1", + "file_error_text= MixedCase param42=20.000000 named=4711.000000 INI=3.140000", + "absent=canon_event=PROGRAM_END", + ].join("\n"), + ); + + const m19Dir = await writeInterpRegressionFiles( + interp, + "m19", + [ + "test.ini", + "test.ngc", + ], + ); + verifyExpectedOutput( + "browser_interp_m19", + interp.runFileWithIni(`${m19Dir}/test.ngc`, `${m19Dir}/test.ini`), + [ + "file_open=0", + "file_read_count=8", + "file_execute_count=8", + "file_saw_error=0", + "canon_event=ORIENT_SPINDLE spindle=0 orientation=87 mode=0", + "canon_event=WAIT_SPINDLE_ORIENT_COMPLETE spindle=0 timeout=2", + "canon_event=ORIENT_SPINDLE spindle=0 orientation=42 mode=1", + "canon_event=ORIENT_SPINDLE spindle=0 orientation=132 mode=0", + "canon_event=ORIENT_SPINDLE spindle=0 orientation=132 mode=1", + "canon_event=WAIT_SPINDLE_ORIENT_COMPLETE spindle=0 timeout=1", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const magicCommentsParamFormatPath = await writeInterpRegressionFile( + interp, + "magic_comments/param_format_printing", + "test.ngc", + ); + verifyExpectedOutput( + "browser_interp_magic_comments_param_format", + interp.runFile(magicCommentsParamFormatPath), + [ + "file_open=0", + "file_read_count=13", + "file_execute_count=13", + "file_saw_error=0", + "canon_event=MESSAGE: native value = 1.123457", + "canon_event=MESSAGE: Test round to integer: 1", + "canon_event=MESSAGE: Test round to 4 decimals: 1.1235", + "canon_event=MESSAGE: Test format separate from param: The value is: 1.1235", + "canon_event=MESSAGE: Test round to 7 decimals: 1.1234568", + "canon_event=MESSAGE: native value2 = 2.345679", + "canon_event=MESSAGE: Test2 round all params in line to 4 decimals: The values are: 1.1235, 2.3457", + "canon_event=MESSAGE: Test2 only round last value to integer: The values are: 1.123457, 2", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const m98m99BasicsPath = await writeInterpRegressionFile( + interp, + "m98m99/01-basics", + "test.ngc", + ); + verifyExpectedOutput( + "browser_interp_m98m99_01_basics", + interp.runFile(m98m99BasicsPath), + [ + "file_open=0", + "file_read_count=22", + "file_execute_count=22", + "file_saw_error=0", + "canon_event=COMMENT: A simple O sub example ", + "canon_event=STRAIGHT_TRAVERSE line=10 x=3 y=0 z=0.25", + "canon_event=STRAIGHT_FEED line=11 x=3 y=0 z=-1", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const m98m99VariablesPath = await writeInterpRegressionFile( + interp, + "m98m99/02-variables", + "test.ngc", + ); + const m98m99VariablesRun = runWithCapturedPrints(() => + interp.runFile(m98m99VariablesPath), + ); + verifyExpectedOutput( + "browser_interp_m98m99_02_variables", + m98m99VariablesRun.output, + [ + "file_open=0", + "file_read_count=54", + "file_execute_count=54", + "file_saw_error=0", + "canon_event=COMMENT: Fanuc params have global scope; rs274ngc params #1..#30 have local scope ", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + verifyExpectedOutput( + "browser_interp_m98m99_02_variables_prints", + m98m99VariablesRun.prints, + [ + "Q MAIN/FANUC: POST-M98: 1=13.010000; 30=13.300000; 31=13.310000", + "Q MAIN/RS274NGC: POST-O-CALL: 1=42.010000; 30=42.300000; 31=13.310000", + ].join("\n"), + ); + + const m98m99NestedSubsPath = await writeInterpRegressionFile( + interp, + "m98m99/07-nested-subs", + "test.ngc", + ); + const m98m99NestedSubsRun = runWithCapturedPrints(() => + interp.runFile(m98m99NestedSubsPath), + ); + verifyExpectedOutput( + "browser_interp_m98m99_07_nested_subs", + m98m99NestedSubsRun.output, + [ + "file_open=0", + "file_read_count=163", + "file_execute_count=163", + "file_saw_error=0", + "canon_event=COMMENT: A nested Fanuc subroutine example ", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + verifyExpectedOutput( + "browser_interp_m98m99_07_nested_subs_prints", + m98m99NestedSubsRun.prints, + [ + "X >>>> LOOP [O2.O1]: 4.500000", + "X MAIN END: 1=5.000000", + ].join("\n"), + ); + + const m98m99SubFollowsMainPath = await writeInterpRegressionFile( + interp, + "m98m99/08-sub-follows-main", + "test.ngc", + ); + const m98m99SubFollowsMainRun = runWithCapturedPrints(() => + interp.runFile(m98m99SubFollowsMainPath), + ); + verifyExpectedOutput( + "browser_interp_m98m99_08_sub_follows_main", + m98m99SubFollowsMainRun.output, + [ + "file_open=0", + "file_read_count=9", + "file_execute_count=9", + "file_saw_error=0", + "canon_event=COMMENT: Fanuc-style subs may follow main program ", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + verifyExpectedOutput( + "browser_interp_m98m99_08_sub_follows_main_prints", + m98m99SubFollowsMainRun.prints, + "X IN O1", + ); + + const m98m99M98P001Path = await writeInterpRegressionFile( + interp, + "m98m99/10-M98-P001", + "test.ngc", + ); + const m98m99M98P001Run = runWithCapturedPrints(() => + interp.runFile(m98m99M98P001Path), + ); + verifyExpectedOutput( + "browser_interp_m98m99_10_m98_p001", + m98m99M98P001Run.output, + [ + "file_open=0", + "file_read_count=8", + "file_execute_count=8", + "file_saw_error=0", + "canon_event=COMMENT: main program", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + verifyExpectedOutput( + "browser_interp_m98m99_10_m98_p001_prints", + m98m99M98P001Run.prints, + [ + "x got here", + "absent=ERROR: should not get here", + ].join("\n"), + ); + + const m98m99NamedProgramNamedPath = await writeInterpRegressionFile( + interp, + "m98m99/13-named-program", + "test-named.ngc", + ); + verifyExpectedOutput( + "browser_interp_m98m99_13_named_program_named", + interp.runFile(m98m99NamedProgramNamedPath), + [ + "file_open=0", + "file_read_count=4", + "file_execute_count=4", + "file_saw_error=0", + "canon_event=COMMENT: test-named.ngc: Test named programs", + "canon_event=COMMENT: ...program body", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const m98m99NamedProgramNumberedPath = await writeInterpRegressionFile( + interp, + "m98m99/13-named-program", + "test-numbered.ngc", + ); + verifyExpectedOutput( + "browser_interp_m98m99_13_named_program_numbered", + interp.runFile(m98m99NamedProgramNumberedPath), + [ + "file_open=0", + "file_read_count=4", + "file_execute_count=4", + "file_saw_error=0", + "canon_event=COMMENT: test-numbered.ngc: Test numbered programs", + "canon_event=COMMENT: ...program body", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + + const m98m99OExpressionCallPath = await writeInterpRegressionFile( + interp, + "m98m99/14-o-expression-call", + "test.ngc", + ); + const m98m99OExpressionCallRun = runWithCapturedPrints(() => + interp.runFile(m98m99OExpressionCallPath), + ); + verifyExpectedOutput( + "browser_interp_m98m99_14_o_expression_call", + m98m99OExpressionCallRun.output, + [ + "file_open=0", + "file_read_count=29", + "file_execute_count=29", + "file_saw_error=0", + "canon_event=PROGRAM_END", + ].join("\n"), + ); + verifyExpectedOutput( + "browser_interp_m98m99_14_o_expression_call_prints", + m98m99OExpressionCallRun.prints, + [ + "In sub 100", + "In sub 200", + ].join("\n"), + ); + verifyExpectedOutput( "restore_parameters_missing_file", interp.restoreParameters("/work/browser-missing.var"), diff --git a/wasm-port/tests/fixtures/canon/ini_tool_table.events b/wasm-port/tests/fixtures/canon/ini_tool_table.events new file mode 100644 index 0000000..0261f51 --- /dev/null +++ b/wasm-port/tests/fixtures/canon/ini_tool_table.events @@ -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 diff --git a/wasm-port/tests/fixtures/canon/spindle_orient_offset.events b/wasm-port/tests/fixtures/canon/spindle_orient_offset.events new file mode 100644 index 0000000..2aa79b6 --- /dev/null +++ b/wasm-port/tests/fixtures/canon/spindle_orient_offset.events @@ -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 diff --git a/wasm-port/tests/fixtures/gcode/disable_fanuc_style_sub_m98.ngc b/wasm-port/tests/fixtures/gcode/disable_fanuc_style_sub_m98.ngc new file mode 100644 index 0000000..76174f0 --- /dev/null +++ b/wasm-port/tests/fixtures/gcode/disable_fanuc_style_sub_m98.ngc @@ -0,0 +1,4 @@ +M98 P1 +O1 +M99 +M2 diff --git a/wasm-port/tests/fixtures/gcode/ini_tool_table.ngc b/wasm-port/tests/fixtures/gcode/ini_tool_table.ngc new file mode 100644 index 0000000..851ef57 --- /dev/null +++ b/wasm-port/tests/fixtures/gcode/ini_tool_table.ngc @@ -0,0 +1,2 @@ +G43 H2 +M2 diff --git a/wasm-port/tests/fixtures/gcode/spindle_orient_offset.ngc b/wasm-port/tests/fixtures/gcode/spindle_orient_offset.ngc new file mode 100644 index 0000000..6070bba --- /dev/null +++ b/wasm-port/tests/fixtures/gcode/spindle_orient_offset.ngc @@ -0,0 +1,2 @@ +G90 G17 G0 X0 Y0 Z0 +M19 R45 P2 Q1.5 diff --git a/wasm-port/tests/fixtures/ini/disable_fanuc_style_sub.ini b/wasm-port/tests/fixtures/ini/disable_fanuc_style_sub.ini new file mode 100644 index 0000000..dd5a681 --- /dev/null +++ b/wasm-port/tests/fixtures/ini/disable_fanuc_style_sub.ini @@ -0,0 +1,5 @@ +[RS274NGC] +DISABLE_FANUC_STYLE_SUB = 1 + +[TRAJ] +COORDINATES = XYZ diff --git a/wasm-port/tests/fixtures/ini/ini_tool_table.ini b/wasm-port/tests/fixtures/ini/ini_tool_table.ini new file mode 100644 index 0000000..64ca684 --- /dev/null +++ b/wasm-port/tests/fixtures/ini/ini_tool_table.ini @@ -0,0 +1,6 @@ +[TRAJ] +LINEAR_UNITS = mm + +[EMCIO] +TOOL_TABLE = ini_tool_table.tbl +RANDOM_TOOLCHANGER = 0 diff --git a/wasm-port/tests/fixtures/ini/ini_tool_table.tbl b/wasm-port/tests/fixtures/ini/ini_tool_table.tbl new file mode 100644 index 0000000..7ec4bf0 --- /dev/null +++ b/wasm-port/tests/fixtures/ini/ini_tool_table.tbl @@ -0,0 +1 @@ +T2 P7 Z6.25 D1.5 ;ini-driven tool table entry diff --git a/wasm-port/tests/fixtures/ini/spindle_orient_offset.ini b/wasm-port/tests/fixtures/ini/spindle_orient_offset.ini new file mode 100644 index 0000000..65a45ca --- /dev/null +++ b/wasm-port/tests/fixtures/ini/spindle_orient_offset.ini @@ -0,0 +1,5 @@ +[TRAJ] +COORDINATES = XYZ + +[RS274NGC] +ORIENT_OFFSET = 12.5 diff --git a/wasm-port/tests/fixtures/interp-fixture-matrix.mjs b/wasm-port/tests/fixtures/interp-fixture-matrix.mjs index 0923071..b8c9d4d 100644 --- a/wasm-port/tests/fixtures/interp-fixture-matrix.mjs +++ b/wasm-port/tests/fixtures/interp-fixture-matrix.mjs @@ -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"; diff --git a/wasm-port/tests/host/verify_host_smokes.sh b/wasm-port/tests/host/verify_host_smokes.sh index 3d7c0c3..ddbd3c0 100755 --- a/wasm-port/tests/host/verify_host_smokes.sh +++ b/wasm-port/tests/host/verify_host_smokes.sh @@ -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" diff --git a/wasm-port/tests/native/verify_native_probes.sh b/wasm-port/tests/native/verify_native_probes.sh index f039999..1e21584 100755 --- a/wasm-port/tests/native/verify_native_probes.sh +++ b/wasm-port/tests/native/verify_native_probes.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" "$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" diff --git a/wasm-port/tests/native/verify_nc_files.sh b/wasm-port/tests/native/verify_nc_files.sh new file mode 100755 index 0000000..50c22c7 --- /dev/null +++ b/wasm-port/tests/native/verify_nc_files.sh @@ -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 <&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 diff --git a/wasm-port/tests/native/verify_sim_configs.sh b/wasm-port/tests/native/verify_sim_configs.sh new file mode 100755 index 0000000..dcb6d9f --- /dev/null +++ b/wasm-port/tests/native/verify_sim_configs.sh @@ -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 <&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 diff --git a/wasm-port/tests/wasm/node/verify_interp_wasm.mjs b/wasm-port/tests/wasm/node/verify_interp_wasm.mjs index fdb766f..80f98d2 100644 --- a/wasm-port/tests/wasm/node/verify_interp_wasm.mjs +++ b/wasm-port/tests/wasm/node/verify_interp_wasm.mjs @@ -12,6 +12,7 @@ import { INTERP_INI_FIXTURE, INTERP_MDI_FIXTURES, INTERP_POSITION_PARAMS_FILE_FIXTURE, + INTERP_SPINDLE_ORIENT_OFFSET_FIXTURE, } from "../../fixtures/interp-fixture-matrix.mjs"; function verifyExpectedOutput(fixtureName, output, expectedText) { @@ -79,15 +80,24 @@ 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 interpPrints = []; const interp = await createLinuxCncInterpSdk({ wasmBinary: readFileSync(wasmPath), - print() {}, + print(message) { + interpPrints.push(message); + }, printErr(message) { console.error(message); }, }); +function runWithCapturedPrints(operation) { + interpPrints.length = 0; + const output = operation(); + return { output, prints: interpPrints.join("\n") }; +} + function writeVendorTextFile(sourcePath, wasmPath) { interp.writeTextFile(wasmPath, readFileSync(sourcePath, "utf8")); } @@ -121,6 +131,18 @@ function writeFiveAxisTrtMachineFiles() { resolve(sourceDir, "demos/xyzbc_switchkins.ngc"), `${wasmDir}/demos/xyzbc_switchkins.ngc`, ); + writeVendorTextFile( + resolve(sourceDir, "demos/xyzac_switchkins_test_1.ngc"), + `${wasmDir}/demos/xyzac_switchkins_test_1.ngc`, + ); + writeVendorTextFile( + resolve(sourceDir, "demos/xyzac_switchkins_test_2.ngc"), + `${wasmDir}/demos/xyzac_switchkins_test_2.ngc`, + ); + writeVendorTextFile( + resolve(sourceDir, "demos/xyzac_switchkins_test_3.ngc"), + `${wasmDir}/demos/xyzac_switchkins_test_3.ngc`, + ); writeVendorTextFile( resolve(sourceDir, "demos/boat-xyzac.ngc"), `${wasmDir}/demos/boat-xyzac.ngc`, @@ -184,6 +206,63 @@ function writeFiveAxisBridgeMillMachineFiles() { return wasmDir; } +function writeRemapRegressionFiles(name, files) { + const sourceDir = resolve(rootDir, "vendor/linuxcnc/tests/remap", name); + const wasmDir = `/work/remap/${name}`; + + for (const filename of files) { + writeVendorTextFile(resolve(sourceDir, filename), `${wasmDir}/${filename}`); + } + + return wasmDir; +} + +function writeInterpRegressionFile(name, filename) { + const sourceDir = resolve(rootDir, "vendor/linuxcnc/tests/interp", name); + const wasmDir = `/work/interp/${name}`; + + writeVendorTextFile(resolve(sourceDir, filename), `${wasmDir}/${filename}`); + + return `${wasmDir}/${filename}`; +} + +function writeInterpRegressionFiles(name, files) { + const sourceDir = resolve(rootDir, "vendor/linuxcnc/tests/interp", name); + const wasmDir = `/work/interp/${name}`; + + for (const filename of files) { + writeVendorTextFile(resolve(sourceDir, filename), `${wasmDir}/${filename}`); + } + + return wasmDir; +} + +function writeUserMCodeFixture(name, code) { + const wasmDir = `/work/user-m/${name}`; + const iniPath = `${wasmDir}/test.ini`; + const programPath = `${wasmDir}/test.ngc`; + const mcodePath = `${wasmDir}/${code}`; + + interp.writeTextFile( + iniPath, + [ + "[DISPLAY]", + "PROGRAM_PREFIX = .", + "", + "[RS274NGC]", + "USER_M_PATH = .", + "", + "[TRAJ]", + "COORDINATES = XYZ", + ].join("\n"), + ); + interp.writeTextFile(programPath, `${code}\nM2\n`); + interp.writeTextFile(mcodePath, "#!/bin/sh\nexit 0\n"); + interp.module.FS.chmod(mcodePath, 0o755); + + return { iniPath, programPath }; +} + const namedParamIniPath = "/work/namedparams.ini"; interp.writeTextFile( namedParamIniPath, @@ -300,6 +379,30 @@ verifyExpectedOutput( baselineIniExpected, ); +const spindleOrientOffsetProgramText = readFileSync( + resolve(rootDir, `tests/fixtures/gcode/${INTERP_SPINDLE_ORIENT_OFFSET_FIXTURE}.ngc`), + "utf8", +); +const spindleOrientOffsetExpected = readFileSync( + resolve(rootDir, `tests/fixtures/canon/${INTERP_SPINDLE_ORIENT_OFFSET_FIXTURE}.events`), + "utf8", +).trimEnd(); +const spindleOrientOffsetIniPath = "/work/spindle-orient-offset.ini"; +interp.writeTextFile( + spindleOrientOffsetIniPath, + readFileSync(resolve(rootDir, "tests/fixtures/ini/spindle_orient_offset.ini"), "utf8"), +); +const disableFanucStyleSubIniPath = "/work/disable-fanuc-style-sub.ini"; +interp.writeTextFile( + disableFanucStyleSubIniPath, + readFileSync(resolve(rootDir, "tests/fixtures/ini/disable_fanuc_style_sub.ini"), "utf8"), +); +verifyExpectedOutput( + INTERP_SPINDLE_ORIENT_OFFSET_FIXTURE, + interp.runProgramWithIni(spindleOrientOffsetProgramText, spindleOrientOffsetIniPath), + spindleOrientOffsetExpected, +); + for (const fixtureName of INTERP_ERROR_FIXTURES) { const programText = readFileSync( resolve(rootDir, `tests/fixtures/gcode_errors/${fixtureName}.ngc`), @@ -351,6 +454,27 @@ verifyExpectedOutput( namedParamExpected, ); +const iniToolTableDir = "/work/ini-tool-table"; +const iniToolTableIniPath = `${iniToolTableDir}/ini_tool_table.ini`; +const iniToolTableProgramPath = `${iniToolTableDir}/ini_tool_table.ngc`; +interp.writeTextFile( + iniToolTableIniPath, + readFileSync(resolve(rootDir, "tests/fixtures/ini/ini_tool_table.ini"), "utf8"), +); +interp.writeTextFile( + `${iniToolTableDir}/ini_tool_table.tbl`, + readFileSync(resolve(rootDir, "tests/fixtures/ini/ini_tool_table.tbl"), "utf8"), +); +interp.writeTextFile( + iniToolTableProgramPath, + readFileSync(resolve(rootDir, "tests/fixtures/gcode/ini_tool_table.ngc"), "utf8"), +); +verifyExpectedOutput( + "ini_tool_table_file", + interp.runFileWithIni(iniToolTableProgramPath, iniToolTableIniPath), + readFileSync(resolve(rootDir, "tests/fixtures/canon/ini_tool_table.events"), "utf8").trimEnd(), +); + const baselineIniFilePath = `/work/${INTERP_BASELINE_INI_FIXTURE}.ngc`; interp.writeTextFile(baselineIniFilePath, baselineIniProgramText); verifyExpectedOutput( @@ -359,6 +483,29 @@ verifyExpectedOutput( baselineIniExpected, ); +const spindleOrientOffsetFilePath = `/work/${INTERP_SPINDLE_ORIENT_OFFSET_FIXTURE}.ngc`; +interp.writeTextFile(spindleOrientOffsetFilePath, spindleOrientOffsetProgramText); +verifyExpectedOutput( + `${INTERP_SPINDLE_ORIENT_OFFSET_FIXTURE}_file`, + interp.runFileWithIni(spindleOrientOffsetFilePath, spindleOrientOffsetIniPath), + spindleOrientOffsetExpected, +); + +const disableFanucStyleSubFilePath = "/work/disable_fanuc_style_sub_m98.ngc"; +interp.writeTextFile( + disableFanucStyleSubFilePath, + readFileSync(resolve(rootDir, "tests/fixtures/gcode/disable_fanuc_style_sub_m98.ngc"), "utf8"), +); +verifyExpectedOutput( + "disable_fanuc_style_sub_m98_file_wasm", + interp.runFileWithIni(disableFanucStyleSubFilePath, disableFanucStyleSubIniPath), + [ + "file_open=0", + "file_saw_error=1", + "file_error_text=DISABLE_FANUC_STYLE_SUB set in INI file, but found m98", + ].join("\n"), +); + const coordinateOffsetsFilePath = `/work/${INTERP_COORDINATE_OFFSETS_FILE_FIXTURE}.ngc`; interp.writeTextFile( coordinateOffsetsFilePath, @@ -448,6 +595,78 @@ verifyExpectedOutput( "fiveaxis_linuxcnc_remap_file_execute=1", ].join("\n"), ); +verifyExpectedOutput( + "fiveaxis_xyzac_switchkins_test_1_wasm", + interp.runFiveAxisRemapFile( + `${fiveAxisTrtDir}/demos/xyzac_switchkins_test_1.ngc`, + `${fiveAxisTrtDir}/xyzac-trt.ini`, + ), + [ + "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=248", + "fiveaxis_file_execute_count=248", + "fiveaxis_file_finish_count=9", + "fiveaxis_file_final_rc=1", + "fiveaxis_file_reached_exit=1", + "fiveaxis_hal_switchkins: rc=0 found=1 value=0", + "fiveaxis_linuxcnc_remap_file_execute=1", + ].join("\n"), +); +verifyExpectedOutput( + "fiveaxis_xyzac_switchkins_test_2_wasm", + interp.runFiveAxisRemapFile( + `${fiveAxisTrtDir}/demos/xyzac_switchkins_test_2.ngc`, + `${fiveAxisTrtDir}/xyzac-trt.ini`, + ), + [ + "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=120", + "fiveaxis_file_execute_count=120", + "fiveaxis_file_finish_count=3", + "fiveaxis_file_final_rc=1", + "fiveaxis_file_reached_exit=1", + "fiveaxis_hal_switchkins: rc=0 found=1 value=0", + "fiveaxis_linuxcnc_remap_file_execute=1", + ].join("\n"), +); +verifyExpectedOutput( + "fiveaxis_xyzac_switchkins_test_3_wasm", + interp.runFiveAxisRemapFile( + `${fiveAxisTrtDir}/demos/xyzac_switchkins_test_3.ngc`, + `${fiveAxisTrtDir}/xyzac-trt.ini`, + ), + [ + "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=86", + "fiveaxis_file_execute_count=86", + "fiveaxis_file_finish_count=3", + "fiveaxis_file_final_rc=1", + "fiveaxis_file_reached_exit=1", + "fiveaxis_hal_switchkins: rc=0 found=1 value=0", + "fiveaxis_linuxcnc_remap_file_execute=1", + ].join("\n"), +); verifyExpectedOutput( "fiveaxis_boat_xyzac_wasm", @@ -567,6 +786,977 @@ verifyExpectedOutput( ].join("\n"), ); +const duplicateOwordDir = writeRemapRegressionFiles("duplicate-o-word", [ + "test.ini", + "test.ngc", + "rm207.ngc", + "rm208.ngc", +]); +verifyExpectedOutput( + "duplicate_oword_remap_wasm", + interp.runRemapFile( + `${duplicateOwordDir}/test.ngc`, + `${duplicateOwordDir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parse_remap_2=0", + "remap_parsed_remap_count=2", + "remap_remaps_ready=1", + "remap_file_open=0", + "remap_file_read_count=31", + "remap_file_execute_count=31", + "remap_file_finish_count=0", + "remap_file_final_rc=3", + "remap_file_reached_endfile=1", + "remap_canon_event=MESSAGE: executing m207: run remapped m208 before o", + "remap_canon_event=MESSAGE: rm207 running remapped m208", + "remap_canon_event=MESSAGE: rm208 starting and done", + "remap_canon_event=FINISH", + "remap_linuxcnc_file_execute=1", + ].join("\n"), +); + +const failArgs0Dir = writeRemapRegressionFiles("fail/args.0", [ + "test.ini", + "test.ngc", + "rm400.ngc", +]); +verifyExpectedOutput( + "fail_args_0_remap_wasm", + interp.runRemapFile( + `${failArgs0Dir}/test.ngc`, + `${failArgs0Dir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parsed_remap_count=1", + "remap_remaps_ready=1", + "remap_file_open=0", + "remap_file_saw_error=0", + "remap_canon_event=MESSAGE: M400 call_level= 1.000000 remap_level=1.000000", + "remap_canon_event=MESSAGE: P word set: 47.110000", + "remap_canon_event=MESSAGE: Q word set: 8.150000", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), +); + +const failArgs1Dir = writeRemapRegressionFiles("fail/args.1", [ + "test.ini", + "test.ngc", + "rm400.ngc", +]); +verifyExpectedOutput( + "fail_args_1_remap_wasm", + interp.runRemapFileContinueOnError( + `${failArgs1Dir}/test.ngc`, + `${failArgs1Dir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_file_execute_1=5", + "remap_file_error_text=user-defined M400: missing: Q", + "remap_file_saw_error=1", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), +); + +const failArgs2Dir = writeRemapRegressionFiles("fail/args.2", [ + "test.ini", + "test.ngc", + "rm400.ngc", +]); +verifyExpectedOutput( + "fail_args_2_remap_wasm", + interp.runRemapFileContinueOnError( + `${failArgs2Dir}/test.ngc`, + `${failArgs2Dir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_file_execute_1=5", + "remap_file_error_text=user-defined M400: missing: P,Q", + "remap_file_saw_error=1", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), +); + +const failBodyNgcDir = writeRemapRegressionFiles("fail/body-ngc", [ + "test.ini", + "test.ngc", + "rm400.ngc", +]); +verifyExpectedOutput( + "fail_body_ngc_remap_wasm", + interp.runRemapFileContinueOnError( + `${failBodyNgcDir}/test.ngc`, + `${failBodyNgcDir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_file_read_5=5", + "remap_file_error_text=Attempt to divide by zero", + "remap_file_saw_error=1", + "remap_canon_event=MESSAGE: before M400: call_level= 0.000000 remap_level=0.000000", + "remap_canon_event=MESSAGE: in rm400: call_level= 1.000000 remap_level=1.000000", + "remap_canon_event=MESSAGE: after failed M400: call_level= 0.000000 remap_level=0.000000", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), +); + +const m30InteractionDir = writeRemapRegressionFiles("m30-interaction", [ + "test.ini", + "test.ngc", + "rm400.ngc", +]); +verifyExpectedOutput( + "m30_interaction_remap_wasm", + interp.runRemapFile( + `${m30InteractionDir}/test.ngc`, + `${m30InteractionDir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parsed_remap_count=1", + "remap_remaps_ready=1", + "remap_file_open=0", + "remap_file_read_count=4", + "remap_file_execute_count=4", + "remap_file_finish_count=0", + "remap_file_final_rc=1", + "remap_file_reached_exit=1", + "remap_canon_event=MESSAGE: m400 call_level=1.000000 remap_level=1.000000 line=2.000000", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), +); + +const nestedRemapsOwordDir = writeRemapRegressionFiles("nested-remaps-oword", [ + "test.ini", + "test.ngc", + "rm400.ngc", + "rm401.ngc", + "rm402.ngc", + "rm403.ngc", +]); +verifyExpectedOutput( + "nested_remaps_oword_remap_wasm", + interp.runRemapFile( + `${nestedRemapsOwordDir}/test.ngc`, + `${nestedRemapsOwordDir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parse_remap_2=0", + "remap_parse_remap_3=0", + "remap_parse_remap_4=0", + "remap_parsed_remap_count=4", + "remap_remaps_ready=1", + "remap_file_open=0", + "remap_file_read_count=21", + "remap_file_execute_count=21", + "remap_file_finish_count=0", + "remap_file_final_rc=3", + "remap_file_reached_endfile=1", + "remap_canon_event=MESSAGE: main call_level=0.000000 remap_level=0.000000 line=2.000000", + "remap_canon_event=MESSAGE: m400 handler pre call_level=1.000000 remap_level=1.000000 line=2.000000", + "remap_canon_event=MESSAGE: m401 handler pre call_level=2.000000 remap_level=2.000000 line=2.000000", + "remap_canon_event=MESSAGE: m402 handler pre call_level=3.000000 remap_level=3.000000 line=2.000000", + "remap_canon_event=MESSAGE: m403 handler pre call_level=4.000000 remap_level=4.000000 line=2.000000", + "remap_canon_event=MESSAGE: m400 handler post call_level=1.000000 remap_level=1.000000 line=4.000000", + "remap_canon_event=FINISH", + "remap_linuxcnc_file_execute=1", + ].join("\n"), +); + +const posargs0Dir = writeRemapRegressionFiles("posargs.0", [ + "test.ini", + "test.ngc", + "rg881.ngc", +]); +verifyExpectedOutput( + "posargs_0_remap_wasm", + interp.runRemapFile( + `${posargs0Dir}/test.ngc`, + `${posargs0Dir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parsed_remap_count=1", + "remap_remaps_ready=1", + "remap_file_open=0", + "remap_file_read_count=19", + "remap_file_execute_count=19", + "remap_file_finish_count=0", + "remap_file_final_rc=1", + "remap_file_reached_exit=1", + "remap_canon_event=MESSAGE: in rg881: n_args=3.000000 [1.000000] [2.000000] [3.000000] [0.000000] [0.000000]", + "remap_canon_event=MESSAGE: in rg881: n_args=4.000000 [1.000000] [2.000000] [3.000000] [4.000000] [0.000000]", + "remap_canon_event=MESSAGE: in rg881: n_args=4.000000 [1.000000] [2.000000] [3.000000] [5.000000] [0.000000]", + "remap_canon_event=MESSAGE: in rg881: n_args=5.000000 [1.000000] [2.000000] [3.000000] [4.000000] [5.000000]", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), +); + +const sequencingDir = writeRemapRegressionFiles("sequencing", [ + "test.ini", + "test.ngc", + "rg881.ngc", + "rm405.ngc", + "rm406.ngc", + "rm407.ngc", + "rm408.ngc", + "rm409.ngc", + "rm410.ngc", +]); +verifyExpectedOutput( + "sequencing_remap_wasm", + interp.runRemapFile( + `${sequencingDir}/test.ngc`, + `${sequencingDir}/test.ini`, + ), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parse_remap_2=0", + "remap_parse_remap_3=0", + "remap_parse_remap_4=0", + "remap_parse_remap_5=0", + "remap_parse_remap_6=0", + "remap_parse_remap_7=0", + "remap_parsed_remap_count=7", + "remap_remaps_ready=1", + "remap_file_open=0", + "remap_file_read_count=10084", + "remap_file_execute_count=10084", + "remap_file_final_rc=1", + "remap_file_reached_exit=1", + "remap_canon_event=MESSAGE: seq=1.000000", + "remap_canon_event=MESSAGE: seq=5.000000", + "remap_canon_event=MESSAGE: seq=6.000000", + "remap_canon_event=MESSAGE: seq=7.000000", + "remap_canon_event=MESSAGE: seq=8.000000 - reset to 1", + "remap_canon_event=MESSAGE: seq=8.000000", + "remap_canon_event=MESSAGE: seq=9.000000", + "remap_canon_event=MESSAGE: seq=10.000000 - reset to 1", + "remap_canon_event=PROGRAM_END", + "remap_linuxcnc_file_execute=1", + ].join("\n"), +); + +const remapIoDir = writeRemapRegressionFiles("remap-io", [ + "test-ngc.ini", + "io_input_m66.ngc", + "io_output_m62.ngc", + "io_output_m63.ngc", + "io_output_m64.ngc", + "io_output_m65.ngc", + "io_output_m67.ngc", + "io_output_m68.ngc", +]); +interp.writeTextFile(`${remapIoDir}/simpockets.tbl`, "T2 P2 Z0 ;remap-io tool\n"); +verifyExpectedOutput( + "remap_io_ngc_mdi_wasm", + interp.runRemapIoMdiSequence(`${remapIoDir}/test-ngc.ini`), + [ + "remap_ini_open=1", + "remap_subroutine_path_count=1", + "remap_parse_remap_1=0", + "remap_parse_remap_7=0", + "remap_parsed_remap_count=7", + "remap_remaps_ready=1", + "remap_mdi_M62 P1_execute_0=0", + "remap_mdi_M66 P1_execute_0=2", + "remap_mdi_M66 P1_execute_1=0", + "remap_mdi_M66 E1 L0_execute_0=2", + "remap_mdi_M66 E1 L0_execute_1=0", + "remap_mdi_parameter_5399=42.13", + "remap_mdi_parameter_5399=-13.42", + "remap_mdi_canon_event=SET_MOTION_OUTPUT_BIT index=0", + "remap_mdi_canon_event=CLEAR_MOTION_OUTPUT_BIT index=0", + "remap_mdi_canon_event=SET_AUX_OUTPUT_BIT index=0", + "remap_mdi_canon_event=CLEAR_AUX_OUTPUT_BIT index=0", + "remap_mdi_canon_event=WAIT index=0 input_type=1 wait_type=0 timeout=0", + "remap_mdi_canon_event=WAIT index=0 input_type=0 wait_type=0 timeout=0", + "remap_mdi_canon_event=SET_MOTION_OUTPUT_VALUE index=0 value=42.13", + "remap_mdi_canon_event=SET_AUX_OUTPUT_VALUE index=0 value=-13.42", + "remap_io_ngc_linuxcnc_mdi_sequence=1", + ].join("\n"), +); + +const doWhileBreakPath = writeInterpRegressionFile("do-while-break", "test.ngc"); +verifyExpectedOutput( + "interp_do_while_break_wasm", + interp.runFile(doWhileBreakPath), + [ + "file_open=0", + "file_read_count=30", + "file_execute_count=30", + "canon_event=MESSAGE: must-execute-outer", + "canon_event=MESSAGE: must-execute-nested", + "canon_event=MESSAGE: must-execute-inner", + "canon_event=MESSAGE: post-inner-while", + "canon_event=MESSAGE: post-nested-while", + "canon_event=MESSAGE: post-outer-while", + "canon_event=PROGRAM_END", + "absent=canon_event=MESSAGE: do-not-execute", + ].join("\n"), +); + +const owordBug315Path = writeInterpRegressionFile("oword-bug315", "test.ngc"); +verifyExpectedOutput( + "interp_oword_bug315_wasm", + interp.runFile(owordBug315Path), + [ + "file_open=0", + "file_read_count=23", + "file_execute_count=23", + "canon_event=MESSAGE: running sub", + "canon_event=MESSAGE: breaking out of sub", + "canon_event=MESSAGE: done", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const owordBug315P2Path = writeInterpRegressionFile("oword-bug315-p2", "test.ngc"); +verifyExpectedOutput( + "interp_oword_bug315_p2_wasm", + interp.runFile(owordBug315P2Path), + [ + "file_open=0", + "file_read_count=26", + "file_execute_count=26", + "canon_event=STRAIGHT_TRAVERSE line=7 x=2 y=2 z=2", + "canon_event=MESSAGE: executing this one", + "canon_event=PROGRAM_END", + "absent=canon_event=MESSAGE: not executing this one", + ].join("\n"), +); + +const existsPath = writeInterpRegressionFile("exists", "test.ngc"); +verifyExpectedOutput( + "interp_exists_wasm", + interp.runFile(existsPath), + [ + "file_open=0", + "file_read_count=7", + "file_execute_count=7", + "canon_event=STRAIGHT_TRAVERSE line=2 x=1 y=0 z=1", + "canon_event=COMMENT: comment", + "canon_event=STRAIGHT_TRAVERSE line=6 x=1 y=0 z=0", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const returnValuePath = writeInterpRegressionFile("return-value", "test.ngc"); +verifyExpectedOutput( + "interp_return_value_wasm", + interp.runFile(returnValuePath), + [ + "file_open=0", + "file_read_count=75", + "file_execute_count=75", + "canon_event=MESSAGE: line 6.000000: _value: - expected 0.000000, got 0.000000", + "canon_event=MESSAGE: line 28.000000: call with arg1=2.000000 expect 246.000000, got 246.000000", + "canon_event=MESSAGE: line 37.000000: call with arg1=-1.000000 expect 0.000000, got 0.000000", + "canon_event=MESSAGE: line 47.000000: call with arg1=0.000000 expect 4712.000000, got 4712.000000", + "canon_event=MESSAGE: line 53.000000: _value=4712.000000 - expected 4712.000000", + "canon_event=PROGRAM_END", + "absent=fail:", + ].join("\n"), +); + +const subsFollowMainPath = writeInterpRegressionFile("subs-follow-main", "test.ngc"); +verifyExpectedOutput( + "interp_subs_follow_main_wasm", + interp.runFile(subsFollowMainPath), + [ + "file_open=0", + "file_read_count=9", + "file_execute_count=9", + "canon_event=COMMENT: Subs may follow main program ", + "canon_event=PALLET_SHUTTLE", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const fractionalLinenumbersPath = writeInterpRegressionFile( + "fractional-linenumbers", + "test.ngc", +); +verifyExpectedOutput( + "interp_fractional_linenumbers_wasm", + interp.runFile(fractionalLinenumbersPath), + [ + "file_open=0", + "file_read_count=4", + "file_execute_count=4", + "canon_event=SET_SPINDLE_SPEED spindle=0 speed=300", + "canon_event=SET_SPINDLE_SPEED spindle=0 speed=600", + "canon_event=SET_SPINDLE_SPEED spindle=0 speed=1200", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const namedparamBug424Path = writeInterpRegressionFile("namedparam-bug424", "test.ngc"); +verifyExpectedOutput( + "interp_namedparam_bug424_wasm", + interp.runFile(namedparamBug424Path), + [ + "file_open=0", + "file_read_count=6", + "file_execute_count=6", + "setup.current_x=2", + "setup.current_y=3", + "setup.current_z=4", + "canon_event=USE_LENGTH_UNITS units=1", + "canon_event=STRAIGHT_TRAVERSE line=5 x=2 y=3 z=4", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const g6164Path = writeInterpRegressionFile("g6164", "test.ngc"); +verifyExpectedOutput( + "interp_g6164_wasm", + interp.runFile(g6164Path), + [ + "file_open=0", + "file_read_count=6", + "file_execute_count=6", + "canon_event=SET_MOTION_CONTROL_MODE mode=3 tolerance=0", + "canon_event=SET_NAIVECAM_TOLERANCE tolerance=0", + "canon_event=SET_MOTION_CONTROL_MODE mode=3 tolerance=1", + "canon_event=SET_NAIVECAM_TOLERANCE tolerance=1", + "canon_event=SET_NAIVECAM_TOLERANCE tolerance=2", + "canon_event=SET_MOTION_CONTROL_MODE mode=2 tolerance=0", + "canon_event=SET_MOTION_CONTROL_MODE mode=1 tolerance=0", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const rotationAbsPtsPath = writeInterpRegressionFile("rotation/abs-pts", "test.ngc"); +const rotationAbsPtsOutput = interp.runFile(rotationAbsPtsPath); +verifyExpectedOutput( + "interp_rotation_abs_pts_wasm", + rotationAbsPtsOutput, + [ + "file_open=0", + "file_read_count=192", + "file_execute_count=192", + "file_saw_error=0", + "canon_event=MESSAGE: 0.000000 0.000000 0.000000", + "canon_event=MESSAGE: 1.000000 2.000000 3.000000", + "canon_event=PROGRAM_END", + ].join("\n"), +); +assert.equal( + rotationAbsPtsOutput.match(/canon_event=MESSAGE: 0\.000000 0\.000000 0\.000000/g)?.length, + 14, + "interp_rotation_abs_pts_wasm: zero absolute-position message count", +); +assert.equal( + rotationAbsPtsOutput.match(/canon_event=MESSAGE: 1\.000000 2\.000000 3\.000000/g)?.length, + 14, + "interp_rotation_abs_pts_wasm: target absolute-position message count", +); + +const rotationG28Path = writeInterpRegressionFile("rotation/g28", "g28.ngc"); +const rotationG28Output = interp.runFile(rotationG28Path); +verifyExpectedOutput( + "interp_rotation_g28_wasm", + rotationG28Output, + [ + "file_open=0", + "file_read_count=13", + "file_execute_count=13", + "file_saw_error=0", + "canon_event=SET_XY_ROTATION rotation=45", + "canon_event=COMMENT: G55 G28", + "canon_event=STRAIGHT_TRAVERSE line=9 x=10 y=10 z=0", + "canon_event=COMMENT: G56 G28", + "canon_event=STRAIGHT_TRAVERSE line=14 x=0 y=14.1421 z=0 a=1", + "canon_event=FINISH", + ].join("\n"), +); +assert.match( + rotationG28Output, + /canon_event=STRAIGHT_TRAVERSE line=14 x=(0|[0-9.e-]+) y=14\.1421 z=0 a=0/, + "interp_rotation_g28_wasm: G56 G28 final machine point", +); + +const rotationG53Path = writeInterpRegressionFile("rotation/g53", "g53.ngc"); +const rotationG53Output = interp.runFile(rotationG53Path); +verifyExpectedOutput( + "interp_rotation_g53_wasm", + rotationG53Output, + [ + "file_open=0", + "file_read_count=17", + "file_execute_count=17", + "file_saw_error=0", + "canon_event=SET_XY_ROTATION rotation=45", + "canon_event=COMMENT: g53 + g55 to 1,1", + "canon_event=COMMENT: g53 + g55 + g92 to 1,1", + "canon_event=STRAIGHT_TRAVERSE line=13 x=0 y=0 z=0", + "canon_event=COMMENT: g53 + g56 + g92 to 1,1", + "canon_event=STRAIGHT_TRAVERSE line=18 x=-0.414214 y=1 z=0 a=1", + "canon_event=FINISH", + ].join("\n"), +); +assert.match( + rotationG53Output, + /canon_event=STRAIGHT_TRAVERSE line=8 x=1\.41421 y=([0-9.e-]+) z=0/, + "interp_rotation_g53_wasm: rotated G53 endpoint", +); + +const iniparamDir = writeInterpRegressionFiles("iniparam", [ + "test.ini", + "test.ngc", +]); +verifyExpectedOutput( + "interp_iniparam_wasm", + interp.runFileWithIniContinueOnError( + `${iniparamDir}/test.ngc`, + `${iniparamDir}/test.ini`, + ), + [ + "file_open=0", + "file_read_count=9", + "file_execute_count=8", + "file_saw_error=1", + "file_error_text=Named parameter #<_ini[nosuchsection]nosuchname> not defined", + "setup.current_x=10", + "setup.current_y=20", + "setup.current_z=30", + "canon_event=STRAIGHT_TRAVERSE line=1 x=10 y=20 z=30", + "canon_event=MESSAGE: position now: 10.000000 20.000000 30.000000", + "canon_event=MESSAGE: not in INI: ######", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const iniparamFailassignDir = writeInterpRegressionFiles("iniparam-failassign", [ + "test.ini", + "test.ngc", +]); +verifyExpectedOutput( + "interp_iniparam_failassign_wasm", + interp.runFileWithIni( + `${iniparamFailassignDir}/test.ngc`, + `${iniparamFailassignDir}/test.ini`, + ), + [ + "file_open=0", + "file_execute_1=5", + "file_read_count=1", + "file_execute_count=1", + "file_saw_error=1", + "file_error_text=Cannot assign to read-only parameter #<_ini[vars]toolchange_x>", + "absent=canon_event=MESSAGE: notreached", + ].join("\n"), +); + +const subCallFromSubDir = writeInterpRegressionFiles("sub-call-from-sub", [ + "test.ini", + "test.ngc", + "subs/caller.ngc", + "subs/helper.ngc", +]); +verifyExpectedOutput( + "interp_sub_call_from_sub_wasm", + interp.runFileWithIni( + `${subCallFromSubDir}/test.ngc`, + `${subCallFromSubDir}/test.ini`, + ), + [ + "file_open=0", + "file_read_count=10", + "file_execute_count=10", + "canon_event=COMMENT: Test: calling a sub from within another sub is valid", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const sequenceNumberDir = writeInterpRegressionFiles("sequence-number", [ + "test.ini", + "test.ngc", + "rm400.ngc", +]); +verifyExpectedOutput( + "interp_sequence_number_wasm", + interp.runFileWithIni( + `${sequenceNumberDir}/test.ngc`, + `${sequenceNumberDir}/test.ini`, + ), + [ + "file_open=0", + "file_read_count=13", + "file_execute_count=13", + "canon_event=MESSAGE: main: line=7.000000 - expect 7", + "canon_event=MESSAGE: in rm400.ngc line=2.000000 - expect 2", + "canon_event=MESSAGE: main: line=9.000000 - expect 9", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const nestedSubErrorDir = writeInterpRegressionFiles("nested-sub-error", [ + "test.ini", + "test.ngc", + "subs/nested.ngc", +]); +verifyExpectedOutput( + "interp_nested_sub_error_wasm", + interp.runFileWithIni( + `${nestedSubErrorDir}/test.ngc`, + `${nestedSubErrorDir}/test.ini`, + ), + [ + "file_open=0", + "file_read_4=5", + "file_error_text=Nested subroutine definition: 'O100 sub' found inside called subroutine 'Onested'", + "file_read_count=4", + "file_execute_count=3", + "canon_event=COMMENT: Test: nested sub definition inside named sub should error", + "absent=canon_event=PROGRAM_END", + ].join("\n"), +); + +const nestedSubInFileErrorDir = writeInterpRegressionFiles("nested-sub-in-file-error", [ + "test.ini", + "test.ngc", + "subs/sequential.ngc", +]); +verifyExpectedOutput( + "interp_nested_sub_in_file_error_wasm", + interp.runFileWithIni( + `${nestedSubInFileErrorDir}/test.ngc`, + `${nestedSubInFileErrorDir}/test.ini`, + ), + [ + "file_open=0", + "file_execute_5=5", + "file_error_text=Subroutine 'O200' not found -- not in offset table and no file '", + "file_read_count=5", + "file_execute_count=5", + "canon_event=COMMENT: Test: numbered sub after named endsub in same file should error", + "canon_event=MESSAGE: sequential main: 7.000000 8.000000 9.000000", + "absent=canon_event=PROGRAM_END", + ].join("\n"), +); + +const owordUnwindDir = writeInterpRegressionFiles("oword-unwind", [ + "test.ini", + "test.ngc", + "fail.ngc", +]); +verifyExpectedOutput( + "interp_oword_unwind_wasm", + interp.runFileWithIniContinueOnError( + `${owordUnwindDir}/test.ngc`, + `${owordUnwindDir}/test.ini`, + ), + [ + "file_open=0", + "file_read_5=5", + "file_read_10=5", + "file_read_count=11", + "file_execute_count=9", + "file_saw_error=1", + "canon_event=MESSAGE: pre divide-by-zero", + "canon_event=PROGRAM_END", + "absent=canon_event=MESSAGE: post divide-by-zero", + ].join("\n"), +); + +const abortHotCommentDir = writeInterpRegressionFiles("abort-hot-comment", [ + "test.ini", + "test.ngc", +]); +verifyExpectedOutput( + "interp_abort_hot_comment_wasm", + interp.runFileWithIniContinueOnError( + `${abortHotCommentDir}/test.ngc`, + `${abortHotCommentDir}/test.ini`, + ), + [ + "file_open=0", + "file_read_count=125", + "file_execute_count=125", + "file_saw_error=1", + "file_error_text= MixedCase param42=20.000000 named=4711.000000 INI=3.140000", + "absent=canon_event=PROGRAM_END", + ].join("\n"), +); + +const m19Dir = writeInterpRegressionFiles("m19", [ + "test.ini", + "test.ngc", +]); +verifyExpectedOutput( + "interp_m19_wasm", + interp.runFileWithIni(`${m19Dir}/test.ngc`, `${m19Dir}/test.ini`), + [ + "file_open=0", + "file_read_count=8", + "file_execute_count=8", + "file_saw_error=0", + "canon_event=ORIENT_SPINDLE spindle=0 orientation=87 mode=0", + "canon_event=WAIT_SPINDLE_ORIENT_COMPLETE spindle=0 timeout=2", + "canon_event=ORIENT_SPINDLE spindle=0 orientation=42 mode=1", + "canon_event=ORIENT_SPINDLE spindle=0 orientation=132 mode=0", + "canon_event=ORIENT_SPINDLE spindle=0 orientation=132 mode=1", + "canon_event=WAIT_SPINDLE_ORIENT_COMPLETE spindle=0 timeout=1", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const magicCommentsParamFormatPath = writeInterpRegressionFile( + "magic_comments/param_format_printing", + "test.ngc", +); +verifyExpectedOutput( + "interp_magic_comments_param_format_wasm", + interp.runFile(magicCommentsParamFormatPath), + [ + "file_open=0", + "file_read_count=13", + "file_execute_count=13", + "file_saw_error=0", + "canon_event=MESSAGE: native value = 1.123457", + "canon_event=MESSAGE: Test round to integer: 1", + "canon_event=MESSAGE: Test round to 4 decimals: 1.1235", + "canon_event=MESSAGE: Test format separate from param: The value is: 1.1235", + "canon_event=MESSAGE: Test round to 7 decimals: 1.1234568", + "canon_event=MESSAGE: native value2 = 2.345679", + "canon_event=MESSAGE: Test2 round all params in line to 4 decimals: The values are: 1.1235, 2.3457", + "canon_event=MESSAGE: Test2 only round last value to integer: The values are: 1.123457, 2", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const m98m99BasicsPath = writeInterpRegressionFile("m98m99/01-basics", "test.ngc"); +verifyExpectedOutput( + "interp_m98m99_01_basics_wasm", + interp.runFile(m98m99BasicsPath), + [ + "file_open=0", + "file_read_count=22", + "file_execute_count=22", + "file_saw_error=0", + "canon_event=COMMENT: A simple O sub example ", + "canon_event=STRAIGHT_TRAVERSE line=10 x=3 y=0 z=0.25", + "canon_event=STRAIGHT_FEED line=11 x=3 y=0 z=-1", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const m98m99VariablesPath = writeInterpRegressionFile("m98m99/02-variables", "test.ngc"); +const m98m99VariablesRun = runWithCapturedPrints(() => interp.runFile(m98m99VariablesPath)); +verifyExpectedOutput( + "interp_m98m99_02_variables_wasm", + m98m99VariablesRun.output, + [ + "file_open=0", + "file_read_count=54", + "file_execute_count=54", + "file_saw_error=0", + "canon_event=COMMENT: Fanuc params have global scope; rs274ngc params #1..#30 have local scope ", + "canon_event=PROGRAM_END", + ].join("\n"), +); +verifyExpectedOutput( + "interp_m98m99_02_variables_prints_wasm", + m98m99VariablesRun.prints, + [ + "Q MAIN/FANUC: POST-M98: 1=13.010000; 30=13.300000; 31=13.310000", + "Q MAIN/RS274NGC: POST-O-CALL: 1=42.010000; 30=42.300000; 31=13.310000", + ].join("\n"), +); + +const m98m99NestedSubsPath = writeInterpRegressionFile("m98m99/07-nested-subs", "test.ngc"); +const m98m99NestedSubsRun = runWithCapturedPrints(() => interp.runFile(m98m99NestedSubsPath)); +verifyExpectedOutput( + "interp_m98m99_07_nested_subs_wasm", + m98m99NestedSubsRun.output, + [ + "file_open=0", + "file_read_count=163", + "file_execute_count=163", + "file_saw_error=0", + "canon_event=COMMENT: A nested Fanuc subroutine example ", + "canon_event=PROGRAM_END", + ].join("\n"), +); +verifyExpectedOutput( + "interp_m98m99_07_nested_subs_prints_wasm", + m98m99NestedSubsRun.prints, + [ + "X >>>> LOOP [O2.O1]: 4.500000", + "X MAIN END: 1=5.000000", + ].join("\n"), +); + +const m98m99SubFollowsMainPath = writeInterpRegressionFile( + "m98m99/08-sub-follows-main", + "test.ngc", +); +const m98m99SubFollowsMainRun = runWithCapturedPrints(() => + interp.runFile(m98m99SubFollowsMainPath), +); +verifyExpectedOutput( + "interp_m98m99_08_sub_follows_main_wasm", + m98m99SubFollowsMainRun.output, + [ + "file_open=0", + "file_read_count=9", + "file_execute_count=9", + "file_saw_error=0", + "canon_event=COMMENT: Fanuc-style subs may follow main program ", + "canon_event=PROGRAM_END", + ].join("\n"), +); +verifyExpectedOutput( + "interp_m98m99_08_sub_follows_main_prints_wasm", + m98m99SubFollowsMainRun.prints, + "X IN O1", +); + +const m98m99M98P001Path = writeInterpRegressionFile("m98m99/10-M98-P001", "test.ngc"); +const m98m99M98P001Run = runWithCapturedPrints(() => interp.runFile(m98m99M98P001Path)); +verifyExpectedOutput( + "interp_m98m99_10_m98_p001_wasm", + m98m99M98P001Run.output, + [ + "file_open=0", + "file_read_count=8", + "file_execute_count=8", + "file_saw_error=0", + "canon_event=COMMENT: main program", + "canon_event=PROGRAM_END", + ].join("\n"), +); +verifyExpectedOutput( + "interp_m98m99_10_m98_p001_prints_wasm", + m98m99M98P001Run.prints, + [ + "x got here", + "absent=ERROR: should not get here", + ].join("\n"), +); + +const m98m99NamedProgramNamedPath = writeInterpRegressionFile( + "m98m99/13-named-program", + "test-named.ngc", +); +verifyExpectedOutput( + "interp_m98m99_13_named_program_named_wasm", + interp.runFile(m98m99NamedProgramNamedPath), + [ + "file_open=0", + "file_read_count=4", + "file_execute_count=4", + "file_saw_error=0", + "canon_event=COMMENT: test-named.ngc: Test named programs", + "canon_event=COMMENT: ...program body", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const m98m99NamedProgramNumberedPath = writeInterpRegressionFile( + "m98m99/13-named-program", + "test-numbered.ngc", +); +verifyExpectedOutput( + "interp_m98m99_13_named_program_numbered_wasm", + interp.runFile(m98m99NamedProgramNumberedPath), + [ + "file_open=0", + "file_read_count=4", + "file_execute_count=4", + "file_saw_error=0", + "canon_event=COMMENT: test-numbered.ngc: Test numbered programs", + "canon_event=COMMENT: ...program body", + "canon_event=PROGRAM_END", + ].join("\n"), +); + +const m98m99OExpressionCallPath = writeInterpRegressionFile( + "m98m99/14-o-expression-call", + "test.ngc", +); +const m98m99OExpressionCallRun = runWithCapturedPrints(() => + interp.runFile(m98m99OExpressionCallPath), +); +verifyExpectedOutput( + "interp_m98m99_14_o_expression_call_wasm", + m98m99OExpressionCallRun.output, + [ + "file_open=0", + "file_read_count=29", + "file_execute_count=29", + "file_saw_error=0", + "canon_event=PROGRAM_END", + ].join("\n"), +); +verifyExpectedOutput( + "interp_m98m99_14_o_expression_call_prints_wasm", + m98m99OExpressionCallRun.prints, + [ + "In sub 100", + "In sub 200", + ].join("\n"), +); + +const userM110 = writeUserMCodeFixture("m110", "M110"); +verifyExpectedOutput( + "interp_user_m110_wasm", + interp.runFileWithIni(userM110.programPath, userM110.iniPath), + [ + "file_open=0", + "file_read_count=2", + "file_execute_count=2", + "canon_event=USER_M_COMMAND code=M110", + "canon_event=PROGRAM_END", + "absent=Unknown m code used: M110", + ].join("\n"), +); + +const userM111 = writeUserMCodeFixture("m111", "M111"); +verifyExpectedOutput( + "interp_user_m111_wasm", + interp.runFileWithIni(userM111.programPath, userM111.iniPath), + [ + "file_open=0", + "file_read_count=2", + "file_execute_count=2", + "canon_event=USER_M_COMMAND code=M111", + "canon_event=PROGRAM_END", + "absent=Unknown m code used: M111", + ].join("\n"), +); + const parameterFilePath = "/work/rs274ngc.var"; interp.writeTextFile( parameterFilePath, diff --git a/wasm-port/tests/wasm/node/verify_nc_files_wasm.mjs b/wasm-port/tests/wasm/node/verify_nc_files_wasm.mjs new file mode 100644 index 0000000..ef9cb43 --- /dev/null +++ b/wasm-port/tests/wasm/node/verify_nc_files_wasm.mjs @@ -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"); diff --git a/wasm-port/tests/wasm/node/verify_nc_files_wasm.sh b/wasm-port/tests/wasm/node/verify_nc_files_wasm.sh new file mode 100755 index 0000000..620878a --- /dev/null +++ b/wasm-port/tests/wasm/node/verify_nc_files_wasm.sh @@ -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" diff --git a/wasm-port/tests/wasm/node/verify_sim_configs_wasm.mjs b/wasm-port/tests/wasm/node/verify_sim_configs_wasm.mjs new file mode 100644 index 0000000..785553f --- /dev/null +++ b/wasm-port/tests/wasm/node/verify_sim_configs_wasm.mjs @@ -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"); diff --git a/wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh b/wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh new file mode 100755 index 0000000..5b84686 --- /dev/null +++ b/wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh @@ -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" diff --git a/wasm-port/tools/build_native_probes.sh b/wasm-port/tools/build_native_probes.sh index cc91dda..cee8f8b 100755 --- a/wasm-port/tools/build_native_probes.sh +++ b/wasm-port/tools/build_native_probes.sh @@ -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" diff --git a/wasm-port/tools/build_wasm_core.sh b/wasm-port/tools/build_wasm_core.sh index 95db5a3..8480fc2 100755 --- a/wasm-port/tools/build_wasm_core.sh +++ b/wasm-port/tools/build_wasm_core.sh @@ -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"]' diff --git a/wasm-port/tools/extract_sources.sh b/wasm-port/tools/extract_sources.sh index c7af09e..b7a2442 100755 --- a/wasm-port/tools/extract_sources.sh +++ b/wasm-port/tools/extract_sources.sh @@ -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" } diff --git a/wasm-port/tools/source-manifest.txt b/wasm-port/tools/source-manifest.txt index 9ad391d..0772a65 100644 --- a/wasm-port/tools/source-manifest.txt +++ b/wasm-port/tools/source-manifest.txt @@ -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 diff --git a/wasm-port/tools/verify_native_linuxcnc_fixture_baseline.sh b/wasm-port/tools/verify_native_linuxcnc_fixture_baseline.sh index 57b6708..0814f49 100755 --- a/wasm-port/tools/verify_native_linuxcnc_fixture_baseline.sh +++ b/wasm-port/tools/verify_native_linuxcnc_fixture_baseline.sh @@ -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" diff --git a/wasm-port/tools/verify_vendor_sync.sh b/wasm-port/tools/verify_vendor_sync.sh index da3a80c..23f909e 100755 --- a/wasm-port/tools/verify_vendor_sync.sh +++ b/wasm-port/tools/verify_vendor_sync.sh @@ -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" diff --git a/wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/M111 b/wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/M111 new file mode 100755 index 0000000..718681d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/M111 @@ -0,0 +1,5 @@ +#!/bin/bash +halcmd setp axisui.notifications-clear-info 1 +sleep .1 +halcmd setp axisui.notifications-clear-info 0 +exit 0 diff --git a/wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/dyn_demo.ngc b/wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/dyn_demo.ngc new file mode 100644 index 0000000..621f825 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/dyn_demo.ngc @@ -0,0 +1,33 @@ +# = 9 +# = 4 +# = 3 +# = 100 +# = 100 + +# = # +# = 0 +# = [# * 0.5] + +# = # +# = # +# = 0 + +# = 0 +# = # +# = # + +m111 ;clear notifications +g61 +g0 x0 y0 z0 + +o repeat [#] +f # +g0 x 0 y 0 z 0 +g1 x # y # z # +g1 x # y # z # +g1 x # y # z # +g1 x 0 y 0 z 0 +o endrepeat + +m111 ;clear notifications +m2 diff --git a/wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini b/wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini new file mode 100644 index 0000000..b07b103 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/dynamic_offsets.ini @@ -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 diff --git a/wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/eoffset.tbl b/wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/eoffset.tbl new file mode 100644 index 0000000..c657689 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets/eoffset.tbl @@ -0,0 +1 @@ +T1 P1 D0.125 Z0.5 diff --git a/wasm-port/vendor/linuxcnc/configs/sim/axis/foam/axis_foam.ini b/wasm-port/vendor/linuxcnc/configs/sim/axis/foam/axis_foam.ini new file mode 100644 index 0000000..db93a5f --- /dev/null +++ b/wasm-port/vendor/linuxcnc/configs/sim/axis/foam/axis_foam.ini @@ -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 + diff --git a/wasm-port/vendor/linuxcnc/configs/sim/axis/foam/foam.ngc b/wasm-port/vendor/linuxcnc/configs/sim/axis/foam/foam.ngc new file mode 100644 index 0000000..6f73a2c --- /dev/null +++ b/wasm-port/vendor/linuxcnc/configs/sim/axis/foam/foam.ngc @@ -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 +% diff --git a/wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/M110 b/wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/M110 new file mode 100755 index 0000000..589b5e5 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/M110 @@ -0,0 +1,7 @@ +#!/bin/sh + +halcmd setp axisui.notifications-clear-info 1 +sleep .200 +halcmd setp axisui.notifications-clear-info 0 + +exit 0 diff --git a/wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/xyzc.ini b/wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/xyzc.ini new file mode 100644 index 0000000..3a6dd4c --- /dev/null +++ b/wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/xyzc.ini @@ -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 diff --git a/wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/xyzc.ngc b/wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/xyzc.ngc new file mode 100644 index 0000000..e81955a --- /dev/null +++ b/wasm-port/vendor/linuxcnc/configs/sim/axis/geometry/xyzc.ngc @@ -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 diff --git a/wasm-port/vendor/linuxcnc/configs/sim/axis/sim.tbl b/wasm-port/vendor/linuxcnc/configs/sim/axis/sim.tbl new file mode 100644 index 0000000..6239879 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/configs/sim/axis/sim.tbl @@ -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 diff --git a/wasm-port/vendor/linuxcnc/nc_files/arcspiral.ngc b/wasm-port/vendor/linuxcnc/nc_files/arcspiral.ngc new file mode 100644 index 0000000..e2e5aab --- /dev/null +++ b/wasm-port/vendor/linuxcnc/nc_files/arcspiral.ngc @@ -0,0 +1,1008 @@ +g20 g64 +s3400 m3 +g0z1 +g0x0y0z1 +g0 x1.724638 y-1.012731 +g1z-.1f24 +g1 x1.724638 y-1.012731 +g2 r1.997999 x1.613302 y-1.178668 +r1.996000 x1.486083 y-1.332506 +r1.994000 x1.344282 y-1.472733 +r1.992000 x1.189344 y-1.597975 +r1.990000 x1.022843 y-1.707013 +r1.988000 x0.846464 y-1.798789 +r1.986000 x0.661990 y-1.872422 +r1.984000 x0.471277 y-1.927214 +r1.982000 x0.276244 y-1.962655 +r1.980000 x0.078845 y-1.978430 +r1.978000 x-0.118942 y-1.974421 +r1.976000 x-0.315142 y-1.950708 +r1.974000 x-0.507799 y-1.907568 +r1.972000 x-0.694996 y-1.845471 +r1.970000 x-0.874875 y-1.765076 +r1.968000 x-1.045656 y-1.667222 +r1.966000 x-1.205650 y-1.552921 +r1.964000 x-1.353282 y-1.423350 +r1.962000 x-1.487103 y-1.279832 +r1.960000 x-1.605805 y-1.123828 +r1.958000 x-1.708233 y-0.956924 +r1.956001 x-1.793399 y-0.780806 +r1.954000 x-1.860485 y-0.597253 +r1.952000 x-1.908861 y-0.408112 +r1.950000 x-1.938080 y-0.215284 +r1.948000 x-1.947890 y-0.020702 +r1.946000 x-1.938233 y0.173687 +r1.944000 x-1.909246 y0.365943 +r1.942000 x-1.861258 y0.554151 +r1.940000 x-1.794786 y0.736439 +r1.938000 x-1.710533 y0.910999 +r1.936000 x-1.609377 y1.076105 +r1.934000 x-1.492362 y1.230126 +r1.932000 x-1.360690 y1.371549 +r1.930000 x-1.215706 y1.498986 +r1.928000 x-1.058886 y1.611194 +r1.926000 x-0.891819 y1.707084 +r1.924000 x-0.716195 y1.785733 +r1.922000 x-0.533785 y1.846390 +r1.919999 x-0.346426 y1.888488 +r1.918000 x-0.155999 y1.911645 +r1.916000 x0.035589 y1.915669 +r1.914000 x0.226423 y1.900560 +r1.912000 x0.414597 y1.866508 +r1.910000 x0.598240 y1.813893 +r1.908000 x0.775525 y1.743280 +r1.906000 x0.944697 y1.655410 +r1.904000 x1.104083 y1.551198 +r1.902000 x1.252112 y1.431719 +r1.900000 x1.387330 y1.298197 +r1.898000 x1.508413 y1.151996 +r1.896000 x1.614182 y0.994602 +r1.893999 x1.703613 y0.827609 +r1.892000 x1.775848 y0.652707 +r1.890000 x1.830202 y0.471658 +r1.888000 x1.866169 y0.286284 +r1.886000 x1.883429 y0.098443 +r1.884000 x1.881850 y-0.089983 +r1.882000 x1.861487 y-0.277110 +r1.880000 x1.822584 y-0.461074 +r1.877999 x1.765567 y-0.640043 +r1.876000 x1.691046 y-0.812243 +r1.874000 x1.599802 y-0.975966 +r1.872000 x1.492781 y-1.129597 +r1.870000 x1.371085 y-1.271623 +r1.868000 x1.235962 y-1.400651 +r1.866000 x1.088788 y-1.515420 +r1.864000 x0.931060 y-1.614814 +r1.861999 x0.764375 y-1.697873 +r1.860000 x0.590417 y-1.763805 +r1.858000 x0.410939 y-1.811986 +r1.856000 x0.227744 y-1.841974 +r1.854000 x0.042669 y-1.853509 +r1.852000 x-0.142432 y-1.846515 +r1.850000 x-0.325712 y-1.821102 +r1.848000 x-0.505345 y-1.777563 +r1.846000 x-0.679544 y-1.716373 +r1.844000 x-0.846583 y-1.638180 +r1.841999 x-1.004807 y-1.543802 +r1.840000 x-1.152658 y-1.434218 +r1.838000 x-1.288680 y-1.310553 +r1.836000 x-1.411541 y-1.174073 +r1.834000 x-1.520043 y-1.026170 +r1.832000 x-1.613134 y-0.868344 +r1.830000 x-1.689918 y-0.702194 +r1.828000 x-1.749664 y-0.529396 +r1.826000 x-1.791812 y-0.351691 +r1.824000 x-1.815979 y-0.170864 +r1.822000 x-1.821965 y0.011273 +r1.820000 x-1.809749 y0.192897 +r1.818000 x-1.779492 y0.372198 +r1.816000 x-1.731538 y0.547388 +r1.814000 x-1.666402 y0.716728 +r1.812000 x-1.584774 y0.878541 +r1.810000 x-1.487506 y1.031226 +r1.808000 x-1.375602 y1.173279 +r1.806000 x-1.250213 y1.303305 +r1.804000 x-1.112620 y1.420033 +r1.802000 x-0.964225 y1.522325 +r1.800000 x-0.806533 y1.609194 +r1.798000 x-0.641139 y1.679805 +r1.796000 x-0.469712 y1.733490 +r1.794000 x-0.293977 y1.769750 +r1.792000 x-0.115699 y1.788261 +r1.790000 x0.063336 y1.788879 +r1.788000 x0.241340 y1.771637 +r1.786000 x0.416536 y1.736748 +r1.784000 x0.587182 y1.684599 +r1.782000 x0.751585 y1.615749 +r1.780000 x0.908115 y1.530924 +r1.778000 x1.055229 y1.431005 +r1.776000 x1.191477 y1.317026 +r1.774000 x1.315525 y1.190155 +r1.771999 x1.426160 y1.051689 +r1.770000 x1.522309 y0.903036 +r1.768000 x1.603044 y0.745704 +r1.766000 x1.667593 y0.581283 +r1.764000 x1.715349 y0.411431 +r1.762000 x1.745872 y0.237856 +r1.760000 x1.758897 y0.062301 +r1.758000 x1.754334 y-0.113478 +r1.756000 x1.732268 y-0.287724 +r1.754000 x1.692958 y-0.458702 +r1.752000 x1.636838 y-0.624711 +r1.750000 x1.564506 y-0.784105 +r1.748000 x1.476720 y-0.935308 +r1.746000 x1.374394 y-1.076828 +r1.744000 x1.258581 y-1.207274 +r1.742000 x1.130469 y-1.325369 +r1.740000 x0.991366 y-1.429963 +r1.738000 x0.842685 y-1.520041 +r1.736000 x0.685934 y-1.594738 +r1.734000 x0.522696 y-1.653344 +r1.732000 x0.354616 y-1.695309 +r1.730000 x0.183384 y-1.720253 +r1.728000 x0.010717 y-1.727967 +r1.726000 x-0.161658 y-1.718413 +r1.724000 x-0.332020 y-1.691727 +r1.722000 x-0.498673 y-1.648214 +r1.720000 x-0.659961 y-1.588349 +r1.718000 x-0.814287 y-1.512766 +r1.716000 x-0.960124 y-1.422258 +r1.713999 x-1.096037 y-1.317762 +r1.712001 x-1.220693 y-1.200356 +r1.710000 x-1.332871 y-1.071240 +r1.708000 x-1.431481 y-0.931732 +r1.706000 x-1.515571 y-0.783250 +r1.704000 x-1.584335 y-0.627296 +r1.702000 x-1.637121 y-0.465445 +r1.700000 x-1.673440 y-0.299329 +r1.698000 x-1.692969 y-0.130614 +r1.696000 x-1.695551 y0.039007 +r1.694000 x-1.681202 y0.207840 +r1.692000 x-1.650103 y0.374199 +r1.690000 x-1.602605 y0.536430 +r1.688000 x-1.539221 y0.692923 +r1.686000 x-1.460622 y0.842128 +r1.684000 x-1.367628 y0.982573 +r1.682000 x-1.261202 y1.112876 +r1.680000 x-1.142439 y1.231760 +r1.678000 x-1.012554 y1.338065 +r1.676001 x-0.872871 y1.430760 +r1.674000 x-0.724806 y1.508951 +r1.672000 x-0.569860 y1.571892 +r1.670000 x-0.409595 y1.618991 +r1.668000 x-0.245625 y1.649816 +r1.666001 x-0.079596 y1.664098 +r1.664000 x0.086830 y1.661733 +r1.662000 x0.251990 y1.642786 +r1.660000 x0.414237 y1.607485 +r1.658000 x0.571958 y1.556222 +r1.656000 x0.723590 y1.489548 +r1.654000 x0.867632 y1.408166 +r1.652000 x1.002666 y1.312922 +r1.650000 x1.127364 y1.204803 +r1.648000 x1.240506 y1.084919 +r1.646000 x1.340990 y0.954495 +r1.644000 x1.427844 y0.814860 +r1.642000 x1.500234 y0.667430 +r1.640000 x1.557471 y0.513695 +r1.638000 x1.599022 y0.355207 +r1.636000 x1.624509 y0.193560 +r1.634000 x1.633718 y0.030376 +r1.632000 x1.626595 y-0.132713 +r1.629999 x1.603252 y-0.294077 +r1.628000 x1.563963 y-0.452111 +r1.626000 x1.509157 y-0.605244 +r1.624000 x1.439422 y-0.751958 +r1.622001 x1.355489 y-0.890806 +r1.620000 x1.258231 y-1.020419 +r1.618000 x1.148654 y-1.139526 +r1.616000 x1.027880 y-1.246964 +r1.614000 x0.897145 y-1.341688 +r1.612000 x0.757777 y-1.422785 +r1.610000 x0.611191 y-1.489478 +r1.608000 x0.458867 y-1.541138 +r1.606000 x0.302341 y-1.577284 +r1.604000 x0.143186 y-1.597596 +r1.602000 x-0.017001 y-1.601910 +r1.600000 x-0.176620 y-1.590222 +r1.598000 x-0.334076 y-1.562689 +r1.596000 x-0.487805 y-1.519626 +r1.594000 x-0.636279 y-1.461501 +r1.592000 x-0.778029 y-1.388933 +r1.590000 x-0.911658 y-1.302682 +r1.588000 x-1.035850 y-1.203644 +r1.586000 x-1.149389 y-1.092841 +r1.584000 x-1.251169 y-0.971407 +r1.582000 x-1.340203 y-0.840583 +r1.580000 x-1.415634 y-0.701698 +r1.578000 x-1.476743 y-0.556160 +r1.576000 x-1.522956 y-0.405439 +r1.574000 x-1.553850 y-0.251052 +r1.572000 x-1.569154 y-0.094552 +r1.570000 x-1.568756 y0.062495 +r1.568000 x-1.552699 y0.218518 +r1.566000 x-1.521184 y0.371963 +r1.564000 x-1.474564 y0.521303 +r1.562000 x-1.413344 y0.665058 +r1.560000 x-1.338173 y0.801806 +r1.558000 x-1.249836 y0.930201 +r1.556000 x-1.149250 y1.048981 +r1.554000 x-1.037450 y1.156985 +r1.552000 x-0.915581 y1.253162 +r1.550000 x-0.784887 y1.336582 +r1.548000 x-0.646695 y1.406446 +r1.546000 x-0.502404 y1.462090 +r1.544000 x-0.353470 y1.502995 +r1.542000 x-0.201394 y1.528792 +r1.540000 x-0.047702 y1.539261 +r1.538000 x0.106069 y1.534338 +r1.536000 x0.258380 y1.514112 +r1.534000 x0.407717 y1.478825 +r1.532000 x0.552595 y1.428868 +r1.530000 x0.691579 y1.364778 +r1.528000 x0.823297 y1.287232 +r1.526000 x0.946452 y1.197040 +r1.524000 x1.059837 y1.095135 +r1.522000 x1.162346 y0.982566 +r1.520001 x1.252984 y0.860484 +r1.517999 x1.330875 y0.730133 +r1.516001 x1.395278 y0.592838 +r1.514000 x1.445582 y0.449986 +r1.512000 x1.481325 y0.303020 +r1.510000 x1.502186 y0.153417 +r1.508000 x1.507998 y0.002679 +r1.506000 x1.498741 y-0.147687 +r1.504000 x1.474549 y-0.296180 +r1.502000 x1.435702 y-0.441322 +r1.500000 x1.382627 y-0.581672 +r1.498000 x1.315892 y-0.715843 +r1.496001 x1.236201 y-0.842511 +r1.494000 x1.144382 y-0.960430 +r1.492000 x1.041386 y-1.068447 +r1.490000 x0.928271 y-1.165510 +r1.488000 x0.806193 y-1.250679 +r1.486000 x0.676395 y-1.323135 +r1.484000 x0.540195 y-1.382189 +r1.482000 x0.398969 y-1.427287 +r1.480000 x0.254142 y-1.458016 +r1.478000 x0.107168 y-1.474110 +r1.476000 x-0.040478 y-1.475445 +r1.474000 x-0.187320 y-1.462049 +r1.472001 x-0.331895 y-1.434096 +r1.470000 x-0.472764 y-1.391903 +r1.468000 x-0.608531 y-1.335932 +r1.466000 x-0.737855 y-1.266778 +r1.464000 x-0.859462 y-1.185167 +r1.462000 x-0.972157 y-1.091950 +r1.460000 x-1.074841 y-0.988087 +r1.458000 x-1.166516 y-0.874646 +r1.456000 x-1.246295 y-0.752785 +r1.454000 x-1.313415 y-0.623744 +r1.452000 x-1.367241 y-0.488832 +r1.450000 x-1.407271 y-0.349412 +r1.448000 x-1.433144 y-0.206888 +r1.446000 x-1.444640 y-0.062692 +r1.444000 x-1.441685 y0.081732 +r1.442000 x-1.424348 y0.224940 +r1.440000 x-1.392841 y0.365506 +r1.438000 x-1.347519 y0.502033 +r1.436000 x-1.288872 y0.633171 +r1.434000 x-1.217523 y0.757624 +r1.432000 x-1.134220 y0.874167 +r1.430000 x-1.039829 y0.981660 +r1.428000 x-0.935321 y1.079054 +r1.426000 x-0.821770 y1.165405 +r1.424000 x-0.700335 y1.239882 +r1.422001 x-0.572250 y1.301774 +r1.420000 x-0.438812 y1.350498 +r1.418000 x-0.301370 y1.385605 +r1.416000 x-0.161307 y1.406782 +r1.414000 x-0.020029 y1.413858 +r1.412000 x0.121050 y1.406802 +r1.410000 x0.260521 y1.385723 +r1.408000 x0.396997 y1.350873 +r1.406000 x0.529124 y1.302637 +r1.404000 x0.655593 y1.241537 +r1.402000 x0.775159 y1.168218 +r1.400000 x0.886647 y1.083447 +r1.398000 x0.988967 y0.988104 +r1.396000 x1.081123 y0.883170 +r1.394000 x1.162224 y0.769721 +r1.392000 x1.231492 y0.648915 +r1.390000 x1.288270 y0.521978 +r1.388000 x1.332025 y0.390195 +r1.386000 x1.362359 y0.254898 +r1.384000 x1.379008 y0.117445 +r1.382000 x1.381844 y-0.020782 +r1.380000 x1.370879 y-0.158403 +r1.378000 x1.346262 y-0.294044 +r1.376000 x1.308279 y-0.426358 +r1.374000 x1.257349 y-0.554031 +r1.372000 x1.194016 y-0.675804 +r1.370000 x1.118949 y-0.790476 +r1.368000 x1.032933 y-0.896924 +r1.366000 x0.936858 y-0.994109 +r1.364000 x0.831713 y-1.081087 +r1.362000 x0.718574 y-1.157020 +r1.360001 x0.598595 y-1.221182 +r1.358000 x0.472993 y-1.272966 +r1.356000 x0.343039 y-1.311892 +r1.354000 x0.210045 y-1.337609 +r1.352000 x0.075346 y-1.349899 +r1.350000 x-0.059707 y-1.348679 +r1.348000 x-0.193765 y-1.334001 +r1.346000 x-0.325491 y-1.306052 +r1.344001 x-0.453578 y-1.265150 +r1.342000 x-0.576756 y-1.211741 +r1.340000 x-0.693812 y-1.146397 +r1.338000 x-0.803593 y-1.069805 +r1.336000 x-0.905026 y-0.982764 +r1.334000 x-0.997122 y-0.886174 +r1.332000 x-1.078990 y-0.781028 +r1.330000 x-1.149843 y-0.668401 +r1.328000 x-1.209007 y-0.549442 +r1.326000 x-1.255925 y-0.425356 +r1.324000 x-1.290167 y-0.297398 +r1.322001 x-1.311428 y-0.166859 +r1.320000 x-1.319535 y-0.035048 +r1.318000 x-1.314447 y0.096714 +r1.316000 x-1.296255 y0.227112 +r1.314000 x-1.265180 y0.354847 +r1.311999 x-1.221571 y0.478651 +r1.310000 x-1.165903 y0.597302 +r1.308000 x-1.098768 y0.709629 +r1.306000 x-1.020871 y0.814530 +r1.304000 x-0.933022 y0.910981 +r1.302000 x-0.836130 y0.998043 +r1.300000 x-0.731190 y1.074877 +r1.298000 x-0.619274 y1.140747 +r1.296000 x-0.501522 y1.195028 +r1.294000 x-0.379127 y1.237214 +r1.292000 x-0.253325 y1.266922 +r1.290000 x-0.125384 y1.283892 +r1.288000 x0.003412 y1.287995 +r1.286000 x0.131775 y1.279231 +r1.284000 x0.258425 y1.257725 +r1.282000 x0.382100 y1.223733 +r1.280000 x0.501577 y1.177633 +r1.278000 x0.615675 y1.119923 +r1.276000 x0.723271 y1.051216 +r1.274000 x0.823312 y0.972231 +r1.272000 x0.914822 y0.883790 +r1.270000 x0.996913 y0.786806 +r1.268000 x1.068797 y0.682274 +r1.266000 x1.129786 y0.571261 +r1.264000 x1.179307 y0.454897 +r1.262001 x1.216901 y0.334361 +r1.260000 x1.242230 y0.210868 +r1.258000 x1.255080 y0.085662 +r1.256000 x1.255363 y-0.040001 +r1.254000 x1.243115 y-0.164865 +r1.252000 x1.218499 y-0.287686 +r1.250000 x1.181800 y-0.407244 +r1.248000 x1.133423 y-0.522356 +r1.246001 x1.073889 y-0.631886 +r1.244000 x1.003826 y-0.734758 +r1.242000 x0.923970 y-0.829966 +r1.240000 x0.835149 y-0.916584 +r1.238000 x0.738278 y-0.993775 +r1.236000 x0.634351 y-1.060799 +r1.234000 x0.524429 y-1.117018 +r1.232000 x0.409628 y-1.161907 +r1.230000 x0.291112 y-1.195054 +r1.228000 x0.170074 y-1.216166 +r1.226000 x0.047732 y-1.225070 +r1.224000 x-0.074687 y-1.221719 +r1.222000 x-0.195962 y-1.206185 +r1.220000 x-0.314884 y-1.178664 +r1.218000 x-0.430274 y-1.139468 +r1.216000 x-0.540992 y-1.089029 +r1.214000 x-0.645947 y-1.027886 +r1.212000 x-0.744109 y-0.956685 +r1.210000 x-0.834521 y-0.876170 +r1.208000 x-0.916306 y-0.787177 +r1.206000 x-0.988675 y-0.690621 +r1.204000 x-1.050937 y-0.587492 +r1.202000 x-1.102504 y-0.478841 +r1.200000 x-1.142896 y-0.365773 +r1.198000 x-1.171746 y-0.249430 +r1.196000 x-1.188806 y-0.130985 +r1.194000 x-1.193943 y-0.011629 +r1.192000 x-1.187148 y0.107444 +r1.189999 x-1.168526 y0.225046 +r1.188000 x-1.138305 y0.340008 +r1.186000 x-1.096825 y0.451189 +r1.184000 x-1.044537 y0.557493 +r1.182000 x-0.982001 y0.657874 +r1.180000 x-0.909875 y0.751351 +r1.178000 x-0.828912 y0.837012 +r1.176000 x-0.739951 y0.914029 +r1.174000 x-0.643906 y0.981662 +r1.172000 x-0.541762 y1.039268 +r1.170000 x-0.434559 y1.086305 +r1.168000 x-0.323385 y1.122340 +r1.166000 x-0.209363 y1.147050 +r1.164000 x-0.093642 y1.160227 +r1.162000 x0.022616 y1.161780 +r1.160000 x0.138249 y1.151732 +r1.158000 x0.252104 y1.130225 +r1.156000 x0.363051 y1.097511 +r1.154000 x0.469991 y1.053957 +r1.152000 x0.571870 y1.000034 +r1.150000 x0.667689 y0.936318 +r1.148000 x0.756511 y0.863479 +r1.146000 x0.837474 y0.782274 +r1.144000 x0.909797 y0.693546 +r1.142000 x0.972787 y0.598205 +r1.140000 x1.025848 y0.497228 +r1.138000 x1.068485 y0.391642 +r1.136000 x1.100309 y0.282517 +r1.134000 x1.121040 y0.170956 +r1.132000 x1.130509 y0.058083 +r1.130000 x1.128662 y-0.054973 +r1.128000 x1.115557 y-0.167080 +r1.126000 x1.091366 y-0.277123 +r1.124000 x1.056367 y-0.384010 +r1.122000 x1.010951 y-0.486685 +r1.120000 x0.955607 y-0.584137 +r1.118000 x0.890922 y-0.675412 +r1.115999 x0.817577 y-0.759620 +r1.114000 x0.736336 y-0.835946 +r1.112000 x0.648036 y-0.903656 +r1.110000 x0.553586 y-0.962103 +r1.108000 x0.453951 y-1.010739 +r1.106000 x0.350145 y-1.049111 +r1.104000 x0.243218 y-1.076876 +r1.102000 x0.134251 y-1.093792 +r1.100000 x0.024339 y-1.099731 +r1.098000 x-0.085416 y-1.094673 +r1.096000 x-0.193921 y-1.078708 +r1.094000 x-0.300094 y-1.052036 +r1.092000 x-0.402886 y-1.014962 +r1.090000 x-0.501280 y-0.967894 +r1.088000 x-0.594312 y-0.911338 +r1.086000 x-0.681070 y-0.845896 +r1.084000 x-0.760713 y-0.772251 +r1.082000 x-0.832470 y-0.691171 +r1.080000 x-0.895655 y-0.603492 +r1.078000 x-0.949667 y-0.510115 +r1.076000 x-0.994001 y-0.411992 +r1.074000 x-1.028251 y-0.310122 +r1.072000 x-1.052112 y-0.205535 +r1.070000 x-1.065384 y-0.099287 +r1.068000 x-1.067973 y0.007556 +r1.066000 x-1.059895 y0.113924 +r1.064000 x-1.041269 y0.218757 +r1.062001 x-1.012322 y0.321013 +r1.060000 x-0.973380 y0.419681 +r1.058000 x-0.924870 y0.513789 +r1.056000 x-0.867314 y0.602414 +r1.054000 x-0.801319 y0.684692 +r1.052000 x-0.727578 y0.759825 +r1.050000 x-0.646855 y0.827090 +r1.048000 x-0.559983 y0.885846 +r1.046000 x-0.467854 y0.935536 +r1.044000 x-0.371408 y0.975701 +r1.042000 x-0.271623 y1.005975 +r1.040000 x-0.169510 y1.026093 +r1.038000 x-0.066098 y1.035893 +r1.036000 x0.037577 y1.035318 +r1.034000 x0.140476 y1.024413 +r1.032000 x0.241577 y1.003327 +r1.030000 x0.339876 y0.972309 +r1.028000 x0.434402 y0.931708 +r1.026000 x0.524225 y0.881966 +r1.024000 x0.608467 y0.823616 +r1.022000 x0.686309 y0.757274 +r1.020000 x0.756997 y0.683634 +r1.018000 x0.819854 y0.603459 +r1.016000 x0.874283 y0.517577 +r1.014000 x0.919772 y0.426866 +r1.012000 x0.955904 y0.332253 +r1.010000 x0.982353 y0.234697 +r1.008000 x0.998894 y0.135185 +r1.006000 x1.005401 y0.034718 +r1.004000 x1.001848 y-0.065697 +r1.002000 x0.988312 y-0.165058 +r1.000000 x0.964966 y-0.262375 +r0.998000 x0.932084 y-0.356685 +r0.996000 x0.890031 y-0.447059 +r0.994000 x0.839264 y-0.532608 +r0.992000 x0.780326 y-0.612499 +r0.990000 x0.713838 y-0.685956 +r0.988000 x0.640494 y-0.752271 +r0.986000 x0.561054 y-0.810811 +r0.984000 x0.476337 y-0.861022 +r0.982000 x0.387210 y-0.902437 +r0.980000 x0.294581 y-0.934678 +r0.978000 x0.199389 y-0.957459 +r0.976000 x0.102596 y-0.970593 +r0.974000 x0.005176 y-0.973986 +r0.972000 x-0.091897 y-0.967646 +r0.970000 x-0.187655 y-0.951675 +r0.968000 x-0.281145 y-0.926273 +r0.966000 x-0.371445 y-0.891731 +r0.964000 x-0.457664 y-0.848434 +r0.962000 x-0.538959 y-0.796848 +r0.960000 x-0.614539 y-0.737524 +r0.958000 x-0.683671 y-0.671087 +r0.956000 x-0.745692 y-0.598230 +r0.954000 x-0.800013 y-0.519707 +r0.952000 x-0.846123 y-0.436326 +r0.950000 x-0.883595 y-0.348940 +r0.948000 x-0.912093 y-0.258439 +r0.946000 x-0.931368 y-0.165740 +r0.944000 x-0.941267 y-0.071779 +r0.942000 x-0.941731 y0.022502 +r0.940000 x-0.932795 y0.116159 +r0.938000 x-0.914589 y0.208259 +r0.936000 x-0.887332 y0.297888 +r0.934000 x-0.851337 y0.384163 +r0.932000 x-0.807000 y0.466235 +r0.930000 x-0.754799 y0.543303 +r0.928000 x-0.695290 y0.614618 +r0.926000 x-0.629099 y0.679493 +r0.924000 x-0.556914 y0.737308 +r0.922000 x-0.479484 y0.787515 +r0.920000 x-0.397604 y0.829645 +r0.918000 x-0.312111 y0.863314 +r0.916000 x-0.223875 y0.888221 +r0.914000 x-0.133790 y0.904155 +r0.912000 x-0.042763 y0.910997 +r0.910000 x0.048292 y0.908718 +r0.908000 x0.138467 y0.897380 +r0.906000 x0.226862 y0.877137 +r0.904000 x0.312605 y0.848230 +r0.902000 x0.394850 y0.810986 +r0.900000 x0.472790 y0.765813 +r0.898000 x0.545666 y0.713199 +r0.896000 x0.612773 y0.653701 +r0.894000 x0.673467 y0.587944 +r0.892000 x0.727168 y0.516614 +r0.890000 x0.773373 y0.440448 +r0.888000 x0.811653 y0.360228 +r0.886000 x0.841661 y0.276773 +r0.884000 x0.863134 y0.190933 +r0.882000 x0.875897 y0.103574 +r0.880000 x0.879862 y0.015578 +r0.878000 x0.875028 y-0.072175 +r0.876000 x0.861485 y-0.158809 +r0.874000 x0.839405 y-0.243464 +r0.872000 x0.809050 y-0.325302 +r0.870000 x0.770761 y-0.403519 +r0.868000 x0.724955 y-0.477351 +r0.866000 x0.672125 y-0.546080 +r0.864000 x0.612832 y-0.609043 +r0.862000 x0.547697 y-0.665637 +r0.860000 x0.477397 y-0.715326 +r0.858000 x0.402660 y-0.757647 +r0.856000 x0.324253 y-0.792210 +r0.854000 x0.242975 y-0.818706 +r0.852000 x0.159652 y-0.836908 +r0.850000 x0.075126 y-0.846674 +r0.848000 x-0.009752 y-0.847944 +r0.846000 x-0.094134 y-0.840747 +r0.844000 x-0.177179 y-0.825193 +r0.842000 x-0.258063 y-0.801478 +r0.840000 x-0.335988 y-0.769878 +r0.838000 x-0.410190 y-0.730745 +r0.836000 x-0.479945 y-0.684506 +r0.834000 x-0.544578 y-0.631657 +r0.832000 x-0.603467 y-0.572758 +r0.830000 x-0.656052 y-0.508425 +r0.828000 x-0.701837 y-0.439328 +r0.826001 x-0.740398 y-0.366180 +r0.824000 x-0.771383 y-0.289731 +r0.822000 x-0.794521 y-0.210761 +r0.820000 x-0.809618 y-0.130071 +r0.818000 x-0.816562 y-0.048475 +r0.816000 x-0.815324 y0.033206 +r0.814000 x-0.805956 y0.114156 +r0.812000 x-0.788590 y0.193570 +r0.810000 x-0.763441 y0.270662 +r0.808000 x-0.730797 y0.344674 +r0.806000 x-0.691021 y0.414881 +r0.804000 x-0.644547 y0.480599 +r0.802000 x-0.591871 y0.541196 +r0.800000 x-0.533550 y0.596091 +r0.798000 x-0.470197 y0.644763 +r0.796000 x-0.402468 y0.686757 +r0.794000 x-0.331062 y0.721688 +r0.792000 x-0.256711 y0.749242 +r0.790000 x-0.180173 y0.769180 +r0.788000 x-0.102223 y0.781341 +r0.786000 x-0.023649 y0.785644 +r0.784000 x0.054763 y0.782085 +r0.782000 x0.132230 y0.770739 +r0.779999 x0.207981 y0.751760 +r0.778000 x0.281270 y0.725377 +r0.776000 x0.351376 y0.691889 +r0.774000 x0.417615 y0.651670 +r0.772000 x0.479346 y0.605154 +r0.769999 x0.535973 y0.552840 +r0.768000 x0.586959 y0.495281 +r0.766000 x0.631823 y0.433077 +r0.763999 x0.670147 y0.366876 +r0.762000 x0.701585 y0.297360 +r0.760000 x0.725856 y0.225240 +r0.758000 x0.742756 y0.151251 +r0.756000 x0.752156 y0.076142 +r0.754000 x0.754000 y0.000670 +r0.752000 x0.748310 y-0.074410 +r0.750000 x0.735182 y-0.148349 +r0.748000 x0.714788 y-0.220414 +r0.746000 x0.687369 y-0.289896 +r0.744000 x0.653238 y-0.356113 +r0.742000 x0.612771 y-0.418421 +r0.740000 x0.566406 y-0.476218 +r0.738000 x0.514640 y-0.528952 +r0.736000 x0.458017 y-0.576122 +r0.734000 x0.397130 y-0.617287 +r0.732000 x0.332612 y-0.652069 +r0.730000 x0.265125 y-0.680153 +r0.728000 x0.195362 y-0.701297 +r0.726000 x0.124032 y-0.715327 +r0.724000 x0.051855 y-0.722141 +r0.722000 x-0.020441 y-0.721711 +r0.720000 x-0.092134 y-0.714081 +r0.718000 x-0.162510 y-0.699367 +r0.716000 x-0.230873 y-0.677756 +r0.714000 x-0.296552 y-0.649502 +r0.712000 x-0.358904 y-0.614924 +r0.710000 x-0.417326 y-0.574403 +r0.708000 x-0.471254 y-0.528378 +r0.706000 x-0.520176 y-0.477339 +r0.704000 x-0.563631 y-0.421825 +r0.702000 x-0.601214 y-0.362416 +r0.700000 x-0.632585 y-0.299728 +r0.698000 x-0.657463 y-0.234406 +r0.696000 x-0.675639 y-0.167118 +r0.694000 x-0.686968 y-0.098547 +r0.692000 x-0.691376 y-0.029388 +r0.690000 x-0.688859 y0.039666 +r0.688000 x-0.679482 y0.107926 +r0.686000 x-0.663379 y0.174712 +r0.684000 x-0.640749 y0.239367 +r0.682000 x-0.611857 y0.301256 +r0.680000 x-0.577028 y0.359776 +r0.678000 x-0.536644 y0.414363 +r0.676000 x-0.491143 y0.464494 +r0.674000 x-0.441009 y0.509693 +r0.672000 x-0.386770 y0.549539 +r0.670000 x-0.328993 y0.583664 +r0.668000 x-0.268277 y0.611761 +r0.666000 x-0.205246 y0.633585 +r0.664000 x-0.140545 y0.648955 +r0.662000 x-0.074829 y0.657757 +r0.660000 x-0.008763 y0.659942 +r0.658000 x0.056992 y0.655527 +r0.656000 x0.121780 y0.644597 +r0.654000 x0.184958 y0.627301 +r0.652000 x0.245905 y0.603850 +r0.650000 x0.304026 y0.574516 +r0.648000 x0.358755 y0.539628 +r0.646000 x0.409568 y0.499570 +r0.644000 x0.455980 y0.454773 +r0.642000 x0.497553 y0.405715 +r0.640000 x0.533903 y0.352913 +r0.638000 x0.564698 y0.296918 +r0.636000 x0.589665 y0.238309 +r0.634000 x0.608590 y0.177690 +r0.632000 x0.621323 y0.115679 +r0.630000 x0.627775 y0.052904 +r0.628000 x0.627920 y-0.010001 +r0.626000 x0.621798 y-0.072408 +r0.624000 x0.609510 y-0.133694 +r0.622001 x0.591217 y-0.193254 +r0.620000 x0.567140 y-0.250503 +r0.618000 x0.537559 y-0.304885 +r0.616000 x0.502803 y-0.355872 +r0.614000 x0.463254 y-0.402978 +r0.612000 x0.419339 y-0.445757 +r0.610000 x0.371524 y-0.483808 +r0.608000 x0.320314 y-0.516781 +r0.606000 x0.266243 y-0.544381 +r0.604000 x0.209871 y-0.566366 +r0.602000 x0.151776 y-0.582553 +r0.600000 x0.092551 y-0.592819 +r0.598000 x0.032796 y-0.597100 +r0.596000 x-0.026888 y-0.595393 +r0.594000 x-0.085905 y-0.587755 +r0.592000 x-0.143668 y-0.574303 +r0.590000 x-0.199608 y-0.555209 +r0.588000 x-0.253178 y-0.530702 +r0.586000 x-0.303858 y-0.501065 +r0.584001 x-0.351161 y-0.466629 +r0.582000 x-0.394635 y-0.427770 +r0.580000 x-0.433873 y-0.384908 +r0.578000 x-0.468511 y-0.338498 +r0.576000 x-0.498234 y-0.289031 +r0.573999 x-0.522778 y-0.237020 +r0.572000 x-0.541934 y-0.183006 +r0.570000 x-0.555548 y-0.127541 +r0.568000 x-0.563521 y-0.071191 +r0.566000 x-0.565814 y-0.014525 +r0.564001 x-0.562443 y0.041886 +r0.562000 x-0.553481 y0.097480 +r0.560000 x-0.539059 y0.151707 +r0.558000 x-0.519359 y0.204034 +r0.556000 x-0.494616 y0.253951 +r0.554000 x-0.465113 y0.300975 +r0.552000 x-0.431180 y0.344656 +r0.550000 x-0.393188 y0.384582 +r0.548000 x-0.351546 y0.420380 +r0.546000 x-0.306699 y0.451721 +r0.544000 x-0.259117 y0.478325 +r0.542000 x-0.209297 y0.499959 +r0.540000 x-0.157755 y0.516443 +r0.538000 x-0.105018 y0.527651 +r0.536000 x-0.051624 y0.533508 +r0.534000 x0.001889 y0.533997 +r0.532000 x0.054984 y0.529151 +r0.530001 x0.107132 y0.519060 +r0.528000 x0.157818 y0.503863 +r0.526000 x0.206547 y0.483750 +r0.524000 x0.252844 y0.458962 +r0.522000 x0.296266 y0.429780 +r0.520000 x0.336398 y0.396530 +r0.518000 x0.372865 y0.359577 +r0.516000 x0.405329 y0.319319 +r0.514000 x0.433496 y0.276184 +r0.512000 x0.457117 y0.230626 +r0.510000 x0.475991 y0.183120 +r0.508000 x0.489965 y0.134157 +r0.506000 x0.498939 y0.084239 +r0.504000 x0.502860 y0.033873 +r0.502000 x0.501731 y-0.016433 +r0.500000 x0.495601 y-0.066176 +r0.498000 x0.484573 y-0.114862 +r0.496000 x0.468795 y-0.162011 +r0.494000 x0.448463 y-0.207164 +r0.492000 x0.423818 y-0.249885 +r0.490000 x0.395141 y-0.289765 +r0.488000 x0.362752 y-0.326428 +r0.486000 x0.327005 y-0.359532 +r0.484000 x0.288287 y-0.388776 +r0.482000 x0.247009 y-0.413897 +r0.480000 x0.203606 y-0.434678 +r0.478000 x0.158530 y-0.450946 +r0.476000 x0.112247 y-0.462576 +r0.474000 x0.065230 y-0.469490 +r0.472000 x0.017958 y-0.471658 +r0.470000 x-0.029095 y-0.469099 +r0.467999 x-0.075459 y-0.461876 +r0.466000 x-0.120675 y-0.450104 +r0.464000 x-0.164300 y-0.433937 +r0.462000 x-0.205909 y-0.413577 +r0.460000 x-0.245103 y-0.389261 +r0.458000 x-0.281511 y-0.361270 +r0.456000 x-0.314790 y-0.329914 +r0.454000 x-0.344636 y-0.295537 +r0.452000 x-0.370778 y-0.258510 +r0.450000 x-0.392987 y-0.219229 +r0.448000 x-0.411075 y-0.178105 +r0.446000 x-0.424897 y-0.135568 +r0.444000 x-0.434352 y-0.092057 +r0.442000 x-0.439384 y-0.048017 +r0.440000 x-0.439983 y-0.003895 +r0.438000 x-0.436182 y0.039868 +r0.436000 x-0.428059 y0.082834 +r0.434000 x-0.415735 y0.124581 +r0.432000 x-0.399372 y0.164700 +r0.430000 x-0.379170 y0.202805 +r0.428000 x-0.355369 y0.238531 +r0.426000 x-0.328239 y0.271542 +r0.424000 x-0.298084 y0.301532 +r0.422000 x-0.265235 y0.328229 +r0.420000 x-0.230046 y0.351395 +r0.418000 x-0.192893 y0.370832 +r0.416000 x-0.154167 y0.386379 +r0.414000 x-0.114271 y0.397917 +r0.412000 x-0.073617 y0.405370 +r0.410000 x-0.032621 y0.408700 +r0.408000 x0.008303 y0.407916 +r0.406000 x0.048745 y0.403063 +r0.404000 x0.088304 y0.394231 +r0.402000 x0.126590 y0.381548 +r0.400000 x0.163233 y0.365178 +r0.398000 x0.197880 y0.345322 +r0.396000 x0.230203 y0.322215 +r0.394000 x0.259902 y0.296120 +r0.392000 x0.286703 y0.267330 +r0.390000 x0.310368 y0.236161 +r0.388000 x0.330689 y0.202950 +r0.386000 x0.347498 y0.168051 +r0.384000 x0.360661 y0.131833 +r0.382001 x0.370083 y0.094673 +r0.380000 x0.375708 y0.056953 +r0.378000 x0.377519 y0.019060 +r0.376000 x0.375538 y-0.018625 +r0.374000 x0.369825 y-0.055726 +r0.372000 x0.360476 y-0.091874 +r0.370000 x0.347624 y-0.126718 +r0.368000 x0.331436 y-0.159920 +r0.366000 x0.312109 y-0.191165 +r0.364000 x0.289872 y-0.220159 +r0.362000 x0.264981 y-0.246636 +r0.360000 x0.237714 y-0.270355 +r0.358000 x0.208372 y-0.291110 +r0.356000 x0.177272 y-0.308724 +r0.354000 x0.144748 y-0.323054 +r0.352000 x0.111142 y-0.333993 +r0.350000 x0.076804 y-0.341469 +r0.347999 x0.042088 y-0.345445 +r0.346000 x0.007349 y-0.345922 +r0.344000 x-0.027065 y-0.342934 +r0.342000 x-0.060811 y-0.336550 +r0.340000 x-0.093556 y-0.326875 +r0.338000 x-0.124982 y-0.314044 +r0.336000 x-0.154788 y-0.298223 +r0.334000 x-0.182693 y-0.279605 +r0.332000 x-0.208439 y-0.258413 +r0.330000 x-0.231791 y-0.234889 +r0.328000 x-0.252543 y-0.209299 +r0.326000 x-0.270517 y-0.181925 +r0.324000 x-0.285565 y-0.153065 +r0.322000 x-0.297571 y-0.123027 +r0.320000 x-0.306451 y-0.092129 +r0.318000 x-0.312154 y-0.060693 +r0.316000 x-0.314663 y-0.029043 +r0.314000 x-0.313990 y0.002500 +r0.312000 x-0.310183 y0.033619 +r0.310000 x-0.303321 y0.064005 +r0.307999 x-0.293509 y0.093360 +r0.306000 x-0.280887 y0.121403 +r0.304000 x-0.265616 y0.147865 +r0.302000 x-0.247886 y0.172501 +r0.299999 x-0.227906 y0.195086 +r0.298000 x-0.205910 y0.215419 +r0.296000 x-0.182144 y0.233323 +r0.294000 x-0.156874 y0.248650 +r0.292000 x-0.130374 y0.261279 +r0.290000 x-0.102928 y0.271120 +r0.287999 x-0.074827 y0.278109 +r0.286000 x-0.046365 y0.282217 +r0.284000 x-0.017833 y0.283440 +r0.282000 x0.010479 y0.281805 +r0.280000 x0.038286 y0.277370 +r0.278000 x0.065316 y0.270218 +r0.276000 x0.091305 y0.260460 +r0.274001 x0.116005 y0.248232 +r0.272000 x0.139183 y0.233692 +r0.270000 x0.160629 y0.217022 +r0.268000 x0.180148 y0.198421 +r0.266000 x0.197571 y0.178106 +r0.263999 x0.212753 y0.156307 +r0.262000 x0.225573 y0.133269 +r0.260000 x0.235936 y0.109243 +r0.258000 x0.243774 y0.084488 +r0.256000 x0.249045 y0.059267 +r0.254000 x0.251736 y0.033841 +r0.252000 x0.251858 y0.008473 +r0.250000 x0.249450 y-0.016580 +r0.248000 x0.244576 y-0.041070 +r0.246000 x0.237324 y-0.064755 +r0.244000 x0.227807 y-0.087408 +r0.242000 x0.216156 y-0.108815 +r0.240000 x0.202525 y-0.128778 +r0.238000 x0.187085 y-0.147117 +r0.236000 x0.170022 y-0.163672 +r0.234000 x0.151538 y-0.178304 +r0.232000 x0.131843 y-0.190896 +r0.230000 x0.111160 y-0.201354 +r0.228000 x0.089716 y-0.209607 +r0.226000 x0.067742 y-0.215608 +r0.224000 x0.045473 y-0.219336 +r0.222000 x0.023140 y-0.220791 +r0.220000 x0.000974 y-0.219998 +r0.218000 x-0.020803 y-0.217005 +r0.216000 x-0.041975 y-0.211882 +r0.214000 x-0.062336 y-0.204720 +r0.212000 x-0.081692 y-0.195628 +r0.210000 x-0.099863 y-0.184736 +r0.208000 x-0.116685 y-0.172188 +r0.206000 x-0.132010 y-0.158143 +r0.204000 x-0.145710 y-0.142774 +r0.202000 x-0.157675 y-0.126264 +r0.200000 x-0.167814 y-0.108804 +r0.198000 x-0.176060 y-0.090592 +r0.196000 x-0.182364 y-0.071830 +r0.194000 x-0.186699 y-0.052722 +r0.192000 x-0.189060 y-0.033471 +r0.190000 x-0.189463 y-0.014279 +r0.188000 x-0.187942 y0.004658 +r0.186000 x-0.184554 y0.023149 +r0.184000 x-0.179371 y0.041012 +r0.182000 x-0.172485 y0.058076 +r0.179999 x-0.164003 y0.074181 +r0.178000 x-0.154047 y0.089182 +r0.175999 x-0.142752 y0.102945 +r0.174001 x-0.130265 y0.115357 +r0.172000 x-0.116740 y0.126316 +r0.170000 x-0.102342 y0.135743 +r0.168000 x-0.087240 y0.143573 +r0.166001 x-0.071609 y0.149761 +r0.164000 x-0.055621 y0.154280 +r0.162000 x-0.039454 y0.157122 +r0.160000 x-0.023280 y0.158297 +r0.158000 x-0.007268 y0.157833 +r0.156000 x0.008417 y0.155773 +r0.154000 x0.023620 y0.152178 +r0.152000 x0.038191 y0.147124 +r0.150000 x0.051995 y0.140700 +r0.148000 x0.064905 y0.133009 +r0.146000 x0.076807 y0.124164 +r0.144000 x0.087603 y0.114288 +r0.142001 x0.097206 y0.103514 +r0.140000 x0.105546 y0.091978 +r0.138000 x0.112570 y0.079825 +r0.136000 x0.118238 y0.067199 +r0.134000 x0.122527 y0.054250 +r0.132000 x0.125431 y0.041123 +r0.130000 x0.126956 y0.027966 +r0.128000 x0.127128 y0.014918 +r0.126000 x0.125982 y0.002119 +r0.124000 x0.123571 y-0.010303 +r0.122000 x0.119959 y-0.022224 +r0.120000 x0.115220 y-0.033530 +r0.117999 x0.109442 y-0.044117 +r0.116000 x0.102720 y-0.053894 +r0.114000 x0.095157 y-0.062778 +r0.112000 x0.086863 y-0.070702 +r0.110000 x0.077954 y-0.077609 +r0.108000 x0.068547 y-0.083459 +r0.106000 x0.058764 y-0.088220 +r0.104000 x0.048726 y-0.091879 +r0.102000 x0.038554 y-0.094433 +r0.100000 x0.028366 y-0.095892 +r0.098000 x0.018278 y-0.096280 +r0.096000 x0.008400 y-0.095632 +r0.094000 x-0.001165 y-0.093993 +r0.092000 x-0.010318 y-0.091420 +r0.090000 x-0.018972 y-0.087978 +r0.088000 x-0.027045 y-0.083741 +r0.086000 x-0.034469 y-0.078790 +r0.084000 x-0.041182 y-0.073212 +r0.082000 x-0.047136 y-0.067099 +r0.080000 x-0.052291 y-0.060544 +r0.078000 x-0.056623 y-0.053646 +r0.076000 x-0.060114 y-0.046501 +r0.074000 x-0.062759 y-0.039208 +r0.072000 x-0.064567 y-0.031861 +r0.070000 x-0.065552 y-0.024555 +r0.068000 x-0.065742 y-0.017377 +r0.066000 x-0.065174 y-0.010411 +r0.064000 x-0.063891 y-0.003736 +r0.062000 x-0.061946 y0.002578 +r0.060000 x-0.059400 y0.008467 +r0.058000 x-0.056316 y0.013876 +r0.055999 x-0.052764 y0.018759 +r0.054000 x-0.048820 y0.023079 +r0.052000 x-0.044558 y0.026806 +r0.050000 x-0.040057 y0.029924 +r0.048000 x-0.035395 y0.032422 +r0.046000 x-0.030649 y0.034302 +r0.044000 x-0.025894 y0.035574 +r0.042000 x-0.021204 y0.036255 +r0.040000 x-0.016646 y0.036372 +r0.038000 x-0.012285 y0.035959 +r0.036000 x-0.008179 y0.035059 +r0.034000 x-0.004381 y0.033717 +r0.032000 x-0.000934 y0.031986 +r0.030000 x0.002122 y0.029925 +r0.028000 x0.004759 y0.027593 +r0.026000 x0.006955 y0.025053 +r0.024000 x0.008697 y0.022369 +r0.022000 x0.009979 y0.019607 +r0.020000 x0.010806 y0.016829 +r0.018000 x0.011189 y0.014100 +r0.016000 x0.011147 y0.011478 +r0.014000 x0.010708 y0.009019 +r0.012000 x0.009904 y0.006776 +r0.010000 x0.008776 y0.004794 +r0.007999 x0.007368 y0.003115 +r0.006000 x0.005732 y0.001773 +r0.004000 x0.003920 y0.000795 +r0.002000 x0.001990 y0.000200 +g0z1 +m2 diff --git a/wasm-port/vendor/linuxcnc/nc_files/factorial.ngc b/wasm-port/vendor/linuxcnc/nc_files/factorial.ngc new file mode 100644 index 0000000..255f575 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/nc_files/factorial.ngc @@ -0,0 +1,11 @@ +; recursive function example +; factorial +o sub +o if [[#1] EQ 0] +o return [1] +o else +o call [[#1] - 1] +o return [#<_value> * #1] +o endif +o endsub +m2 diff --git a/wasm-port/vendor/linuxcnc/nc_files/hole-circle.ngc b/wasm-port/vendor/linuxcnc/nc_files/hole-circle.ngc new file mode 100644 index 0000000..f2820d5 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/nc_files/hole-circle.ngc @@ -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 diff --git a/wasm-port/vendor/linuxcnc/nc_files/m6demo.ngc b/wasm-port/vendor/linuxcnc/nc_files/m6demo.ngc new file mode 100644 index 0000000..4553ed5 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/nc_files/m6demo.ngc @@ -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=ocall +; +; 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 sub +; +(DEBUG, executing M6 O-word sub, tool-in-spindle=#1 prepared=#2 pocket=#3) +; +M66 P2 L0 +;(debug, digital-input-02=#5399) + +# = 0 +# = 0 +# = 0 + +; number of seconds to wait for 'tool-changed' equivalent +# = 9999 +; +O if [# EQ 0] + M5 +O endif + +O if [# NE 0] + G0 G53 Z0 +O endif + +O if [# NE 0] + G30 +O 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# +; +; if we waited too long, fail change and abort. +; +O if [#5399 EQ -1] + (DEBUG, timeout waiting for digital-in-01 to become true - failing change ) + O return [-1] +O 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 if [#5399 EQ 1] + (DEBUG, returning -1 to fail change) + O return [-1] +O else + (debug, change ok, returning +1 to commit change) + ; a positive return value commits the tool change + O return [1] +O 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 ()" +; +O endsub +m2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/README b/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/README new file mode 100644 index 0000000..5832ae5 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/README @@ -0,0 +1,8 @@ +exercise the (ABORT,) hot comment: + +numbered, named and INI parameter substitution in message +case preservation +unwind from oword flow + + + diff --git a/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/expected b/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/expected new file mode 100644 index 0000000..9029b2a --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/expected @@ -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=# INI=#<_ini[a]value>) + 7 N..... ON_RESET() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.ini b/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.ini new file mode 100644 index 0000000..0080767 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.ini @@ -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 + diff --git a/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.ngc new file mode 100644 index 0000000..cfcebd6 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.ngc @@ -0,0 +1,10 @@ +#42 = 0 +# = 4711 +o100 while [#42 lt 100] +o200 if [#42 eq 20] + (abort, MixedCase param42=#42 named=# INI=#<_ini[a]value>) +o200 endif +#42 = [#42 + 1] +o100 endwhile + +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.sh new file mode 100755 index 0000000..20f233c --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment/test.sh @@ -0,0 +1,5 @@ +#!/bin/bash +export PYTHONUNBUFFERED=1 +rs274 -n 2 -i test.ini -g test.ngc 2>&1 +exit 0 + diff --git a/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/README b/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/README new file mode 100644 index 0000000..3e470ca --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/README @@ -0,0 +1,3 @@ +Tests for bug 3420655 (http://sourceforge.net/tracker/?func=detail&atid=106744&aid=3420655&group_id=6744) + + diff --git a/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/bug.ngc b/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/bug.ngc new file mode 100644 index 0000000..466943a --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/bug.ngc @@ -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 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/expected b/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/expected new file mode 100644 index 0000000..8ce53a9 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/expected @@ -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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/test.ngc new file mode 100644 index 0000000..8691567 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/test.ngc @@ -0,0 +1,30 @@ + +# = 0 + +o100 do + (debug,must-execute-outer) + # = [# + 1] + # = 0 + o200 do + (debug,must-execute-nested) + # = [# + 1] + # = 0 + o300 do + (debug,must-execute-inner) + # = [# + 1] + o300 break + (debug,do-not-execute-inner) + o300 while [# LT 3] + (debug,post-inner-while) + + o200 break + (debug,do-not-execute-nested) + o200 while [# LT 3] + (debug,post-nested-while) + +o100 break + (debug,do-not-execute-outer) +o100 while [# LT 3] +(debug,post-outer-while) + +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/do-while-break/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/exists/README b/wasm-port/vendor/linuxcnc/tests/interp/exists/README new file mode 100644 index 0000000..e167139 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/exists/README @@ -0,0 +1 @@ +Test that EXISTS[] works as desired diff --git a/wasm-port/vendor/linuxcnc/tests/interp/exists/expected b/wasm-port/vendor/linuxcnc/tests/interp/exists/expected new file mode 100644 index 0000000..4dd8b23 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/exists/expected @@ -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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/exists/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/exists/test.ngc new file mode 100644 index 0000000..c7746a9 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/exists/test.ngc @@ -0,0 +1,7 @@ +#=999 +G0 X EXISTS[#1] Y EXISTS[#99999] Z EXISTS[#] A EXISTS[#] ; comment + +#1=2 +#2=99999 +G0 X EXISTS[##1] Y EXISTS[##2] Z EXISTS[###1] (comment) +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/exists/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/exists/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/exists/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/README b/wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/README new file mode 100644 index 0000000..95c5438 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/README @@ -0,0 +1 @@ +Test that line numbers like Ndddd.ddd are accepted too diff --git a/wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/expected b/wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/expected new file mode 100644 index 0000000..1cd93de --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/expected @@ -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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/test.ngc new file mode 100644 index 0000000..00a28ef --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/test.ngc @@ -0,0 +1,4 @@ +S300 +N1234 S600 +N4567.789 S1200 +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/g6164/expected b/wasm-port/vendor/linuxcnc/tests/interp/g6164/expected new file mode 100644 index 0000000..061d73a --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/g6164/expected @@ -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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/g6164/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/g6164/test.ngc new file mode 100644 index 0000000..54ba829 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/g6164/test.ngc @@ -0,0 +1,6 @@ +G64 +G64P1 +G64P1Q2 +G61 +G61.1 +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/g6164/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/g6164/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/g6164/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/README b/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/README new file mode 100644 index 0000000..8335ba5 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/README @@ -0,0 +1,3 @@ +assigning to an inifile variable reference must fail: + +#<_ini[section]name> = diff --git a/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/expected b/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/expected new file mode 100644 index 0000000..72bc002 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/expected @@ -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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.ini b/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.ini new file mode 100644 index 0000000..03ec962 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.ini @@ -0,0 +1,9 @@ +[EMC] +DEBUG=0 +LOG_LEVEL=0 + +[RS274NGC] +INI_VARS = 1 + +[VARS] +TOOLCHANGE_X = 10 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.ngc new file mode 100644 index 0000000..6db802a --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.ngc @@ -0,0 +1,3 @@ +#<_ini[vars]toolchange_x> = 3.1415 +(debug, notreached: #<_ini[vars]toolchange_x>) +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.sh new file mode 100755 index 0000000..9ebfc82 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign/test.sh @@ -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 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/iniparam/README b/wasm-port/vendor/linuxcnc/tests/interp/iniparam/README new file mode 100644 index 0000000..8217699 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/iniparam/README @@ -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> diff --git a/wasm-port/vendor/linuxcnc/tests/interp/iniparam/expected b/wasm-port/vendor/linuxcnc/tests/interp/iniparam/expected new file mode 100644 index 0000000..11c5e30 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/iniparam/expected @@ -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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.ini b/wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.ini new file mode 100644 index 0000000..9993e39 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.ini @@ -0,0 +1,12 @@ +[EMC] +DEBUG=0 +LOG_LEVEL=0 + +[RS274NGC] +INI_VARS = 1 + + +[VARS] +TOOLCHANGE_X = 10 +TOOLCHANGE_Y = 20 +TOOLCHANGE_Z = 30 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.ngc new file mode 100644 index 0000000..b7bbd94 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.ngc @@ -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 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.sh new file mode 100755 index 0000000..d6b8240 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/iniparam/test.sh @@ -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 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m19/README b/wasm-port/vendor/linuxcnc/tests/interp/m19/README new file mode 100644 index 0000000..737aeac --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m19/README @@ -0,0 +1,2 @@ +exercise M19 and possible parameters + diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m19/expected b/wasm-port/vendor/linuxcnc/tests/interp/m19/expected new file mode 100644 index 0000000..f0386c4 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m19/expected @@ -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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m19/test.ini b/wasm-port/vendor/linuxcnc/tests/interp/m19/test.ini new file mode 100644 index 0000000..abe8751 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m19/test.ini @@ -0,0 +1,2 @@ +[RS274NGC] +ORIENT_OFFSET = 42.0 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m19/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/m19/test.ngc new file mode 100644 index 0000000..c33de48 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m19/test.ngc @@ -0,0 +1,8 @@ +M19 +M19 R45 Q2 +M19 P1 +M19 R90 P0 +M19 R90 P1 +M19 Q1 + +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m19/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/m19/test.sh new file mode 100644 index 0000000..22f60fd --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m19/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -n 0 -i test.ini -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/expected b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/expected new file mode 100644 index 0000000..aed7e43 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/expected @@ -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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/test.ngc new file mode 100644 index 0000000..1d62d77 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/test.ngc @@ -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 +% diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/test.sh new file mode 100755 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/01-basics/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/02-variables/expected b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/02-variables/expected new file mode 100644 index 0000000..144f7e5 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/02-variables/expected @@ -0,0 +1,25 @@ + 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("Fanuc params have global scope; rs274ngc params #1..#30 have local scope ") + MAIN/FANUC: PRE-M98: 1=42.010000; 30=42.300000; 31=42.310000 + O1: START: 1=42.010000; 30=42.300000; 31=42.310000 + O1: END: 1=13.010000; 30=13.300000; 31=13.310000 + MAIN/FANUC: POST-M98: 1=13.010000; 30=13.300000; 31=13.310000 + MAIN/RS274NGC: PRE-O-CALL: 1=42.010000; 30=42.300000; 31=42.310000 + O2: START: 1=0.000000; 30=0.000000; 31=42.310000 + O2: END: 1=13.010000; 30=13.300000; 31=13.310000 + MAIN/RS274NGC: POST-O-CALL: 1=42.010000; 30=42.300000; 31=13.310000 + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/02-variables/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/02-variables/test.ngc new file mode 100644 index 0000000..3e0172d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/02-variables/test.ngc @@ -0,0 +1,37 @@ +% +( Fanuc params have global scope; rs274ngc params #1..#30 have local scope ) + +; Fanuc-style: Test that all params are globally changed +#1 = 42.01 +#30 = 42.30 +#31 = 42.31 +(PRINT,Q MAIN/FANUC: PRE-M98: 1=#1; 30=#30; 31=#31) +M98 P1 +(PRINT,Q MAIN/FANUC: POST-M98: 1=#1; 30=#30; 31=#31) + +; RS274NGC-style: Test that params #1..#30 are not globally changed +#1 = 42.01 +#30 = 42.30 +#31 = 42.31 +(PRINT,Q MAIN/RS274NGC: PRE-O-CALL: 1=#1; 30=#30; 31=#31) +O2 call +(PRINT,Q MAIN/RS274NGC: POST-O-CALL: 1=#1; 30=#30; 31=#31) +M30 + +O1 ; Fanuc-style +(PRINT,Q O1: START: 1=#1; 30=#30; 31=#31) +#1 = 13.01 +#30 = 13.30 +#31 = 13.31 +(PRINT,Q O1: END: 1=#1; 30=#30; 31=#31) +M99 + +O2 sub ; rs274ngc-style +(PRINT,Q O2: START: 1=#1; 30=#30; 31=#31) +#1 = 13.01 +#30 = 13.30 +#31 = 13.31 +(PRINT,Q O2: END: 1=#1; 30=#30; 31=#31) +O2 endsub + +% diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/02-variables/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/02-variables/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/02-variables/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/07-nested-subs/expected b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/07-nested-subs/expected new file mode 100644 index 0000000..b88b4e9 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/07-nested-subs/expected @@ -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 nested Fanuc subroutine example ") + MAIN BEGIN: 1=0.000000 + >>>> LOOP [O2.O1]: 0.100000 + >>>> LOOP [O2.O1]: 0.200000 + >>>> LOOP [O2.O1]: 0.300000 + >>>> LOOP [O2.O1]: 0.400000 + >>>> LOOP [O2.O1]: 0.500000 + O2 END: 1=1.000000 + >>>> LOOP [O2.O1]: 1.100000 + >>>> LOOP [O2.O1]: 1.200000 + >>>> LOOP [O2.O1]: 1.300000 + >>>> LOOP [O2.O1]: 1.400000 + >>>> LOOP [O2.O1]: 1.500000 + O2 END: 1=2.000000 + >>>> LOOP [O2.O1]: 2.100000 + >>>> LOOP [O2.O1]: 2.200000 + >>>> LOOP [O2.O1]: 2.300000 + >>>> LOOP [O2.O1]: 2.400000 + >>>> LOOP [O2.O1]: 2.500000 + O2 END: 1=3.000000 + >>>> LOOP [O2.O1]: 3.100000 + >>>> LOOP [O2.O1]: 3.200000 + >>>> LOOP [O2.O1]: 3.300000 + >>>> LOOP [O2.O1]: 3.400000 + >>>> LOOP [O2.O1]: 3.500000 + O2 END: 1=4.000000 + >>>> LOOP [O2.O1]: 4.100000 + >>>> LOOP [O2.O1]: 4.200000 + >>>> LOOP [O2.O1]: 4.300000 + >>>> LOOP [O2.O1]: 4.400000 + >>>> LOOP [O2.O1]: 4.500000 + O2 END: 1=5.000000 + MAIN END: 1=5.000000 + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/07-nested-subs/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/07-nested-subs/test.ngc new file mode 100644 index 0000000..54847ec --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/07-nested-subs/test.ngc @@ -0,0 +1,20 @@ +% +( A nested Fanuc subroutine example ) + +#1 = 0 +(PRINT,X MAIN BEGIN: 1=#1) +M98 P2 L5 +(PRINT,X MAIN END: 1=#1) +M30 + +O2 +M98 P1 L5 +#1 = [FIX[#1] + 1] +(PRINT,X O2 END: 1=#1) +M99 + +O1 +#1 = [#1 + 0.1] +(PRINT,X >>>> LOOP [O2.O1]: #1) +M99 +% diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/07-nested-subs/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/07-nested-subs/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/07-nested-subs/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/08-sub-follows-main/expected b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/08-sub-follows-main/expected new file mode 100644 index 0000000..18e9f92 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/08-sub-follows-main/expected @@ -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..... COMMENT("Fanuc-style subs may follow main program ") + IN O1 + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/08-sub-follows-main/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/08-sub-follows-main/test.ngc new file mode 100644 index 0000000..26635be --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/08-sub-follows-main/test.ngc @@ -0,0 +1,10 @@ +% +( Fanuc-style subs may follow main program ) + +M98 P1 +M30 + +O1 +(PRINT,X IN O1) +M99 +% diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/08-sub-follows-main/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/08-sub-follows-main/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/08-sub-follows-main/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/10-M98-P001/expected b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/10-M98-P001/expected new file mode 100644 index 0000000..024dd38 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/10-M98-P001/expected @@ -0,0 +1,19 @@ + 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("main program") + got here + N..... COMMENT("end") + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/10-M98-P001/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/10-M98-P001/test.ngc new file mode 100644 index 0000000..e2b4747 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/10-M98-P001/test.ngc @@ -0,0 +1,14 @@ +% +(main program) +M98 P0002 +M30 (end) + +O0002 (O-word begins with '0') +(PRINT,x got here) +M99 + +O2 (O-word does not begin with '0') +(PRINT,x ERROR: should not get here) +M99 + +% diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/10-M98-P001/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/10-M98-P001/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/10-M98-P001/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/13-named-program/expected b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/13-named-program/expected new file mode 100644 index 0000000..874c16e --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/13-named-program/expected @@ -0,0 +1,36 @@ + 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..... COMMENT("test-named.ngc: Test named programs") + 8 N..... COMMENT("...program body") + 9 N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 10 N..... SET_XY_ROTATION(0.0000) + 11 N..... SET_FEED_MODE(0, 0) + 12 N..... SET_FEED_RATE(0.0000) + 13 N..... STOP_SPINDLE_TURNING(0) + 14 N..... SET_SPINDLE_MODE(0 0.0000) + 15 N..... PALLET_SHUTTLE() + 16 N..... PROGRAM_END() + 17 N..... ON_RESET() + 18 N..... ON_RESET() + 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..... COMMENT("test-numbered.ngc: Test numbered programs") + 8 N..... COMMENT("...program body") + 9 N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 10 N..... SET_XY_ROTATION(0.0000) + 11 N..... SET_FEED_MODE(0, 0) + 12 N..... SET_FEED_RATE(0.0000) + 13 N..... STOP_SPINDLE_TURNING(0) + 14 N..... SET_SPINDLE_MODE(0 0.0000) + 15 N..... PALLET_SHUTTLE() + 16 N..... PROGRAM_END() + 17 N..... ON_RESET() + 18 N..... ON_RESET() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/13-named-program/test-named.ngc b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/13-named-program/test-named.ngc new file mode 100644 index 0000000..1c26f15 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/13-named-program/test-named.ngc @@ -0,0 +1,6 @@ +% +(test-named.ngc: Test named programs) +O +(...program body) +M30 +% diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/13-named-program/test-numbered.ngc b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/13-named-program/test-numbered.ngc new file mode 100644 index 0000000..3100110 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/13-named-program/test-numbered.ngc @@ -0,0 +1,6 @@ +% +(test-numbered.ngc: Test numbered programs) +O42 +(...program body) +M30 +% diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/13-named-program/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/13-named-program/test.sh new file mode 100644 index 0000000..5dde08a --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/13-named-program/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash -e +rs274 -g test-named.ngc +rs274 -g test-numbered.ngc diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/14-o-expression-call/expected b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/14-o-expression-call/expected new file mode 100644 index 0000000..3b91c6b --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/14-o-expression-call/expected @@ -0,0 +1,18 @@ + 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() +In sub 100 +In sub 200 + 7 N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 8 N..... SET_XY_ROTATION(0.0000) + 9 N..... SET_FEED_MODE(0, 0) + 10 N..... SET_FEED_RATE(0.0000) + 11 N..... STOP_SPINDLE_TURNING(0) + 12 N..... SET_SPINDLE_MODE(0 0.0000) + 13 N..... PALLET_SHUTTLE() + 14 N..... PROGRAM_END() + 15 N..... ON_RESET() + 16 N..... ON_RESET() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/14-o-expression-call/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/14-o-expression-call/test.ngc new file mode 100644 index 0000000..ad3a375 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/14-o-expression-call/test.ngc @@ -0,0 +1,21 @@ +% +; test calling subprograms with expressions + +; call sub O100: use variable in expression with rs274ngc O-sub +#2 = 10 +O[#2 * 10] call + +; call sub O200: use expression in M98 P-word +M98 P[5 * 5 * 2 * 2 + 100] + +M30 + +O100 sub ; rs274ngc subroutine +(print,In sub 100) +O100 endsub + +O200 ; numbered subprogram +(print,In sub 200) +M99 + +% diff --git a/wasm-port/vendor/linuxcnc/tests/interp/m98m99/14-o-expression-call/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/14-o-expression-call/test.sh new file mode 100644 index 0000000..4ed78b4 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/m98m99/14-o-expression-call/test.sh @@ -0,0 +1,2 @@ +#!/bin/bash -e +rs274 -g test.ngc diff --git a/wasm-port/vendor/linuxcnc/tests/interp/magic_comments/param_format_printing/expected b/wasm-port/vendor/linuxcnc/tests/interp/magic_comments/param_format_printing/expected new file mode 100644 index 0000000..36b31bf --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/magic_comments/param_format_printing/expected @@ -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..... MESSAGE(" native value = 1.123457") + N..... MESSAGE(" Test round to integer: 1") + N..... MESSAGE(" Test round to 4 decimals: 1.1235") + N..... MESSAGE(" Test format separate from param: The value is: 1.1235") + N..... MESSAGE(" Test round to 7 decimals: 1.1234568") + N..... MESSAGE(" native value2 = 2.345679") + N..... MESSAGE(" Test2 round all params in line to 4 decimals: The values are: 1.1235, 2.3457") + N..... MESSAGE(" Test2 only round last value to integer: The values are: 1.123457, 2") + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/magic_comments/param_format_printing/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/magic_comments/param_format_printing/test.ngc new file mode 100644 index 0000000..9823788 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/magic_comments/param_format_printing/test.ngc @@ -0,0 +1,13 @@ +# = 1.123456789 + +(DEBUG, native value = #) +(DEBUG, Test round to integer: %d#) +(DEBUG, Test round to 4 decimals: %f#) +(DEBUG, Test format separate from param: %f The value is: #) +(DEBUG, Test round to 7 decimals: %.7f#) + +# = 2.3456789 +(DEBUG, native value2 = #) +(DEBUG, Test2 round all params in line to 4 decimals: %f The values are: #, #) +(DEBUG, Test2 only round last value to integer: The values are: #, %d#) +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/magic_comments/param_format_printing/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/magic_comments/param_format_printing/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/magic_comments/param_format_printing/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424/README b/wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424/README new file mode 100644 index 0000000..c98f867 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424/README @@ -0,0 +1 @@ +test for http://sourceforge.net/p/emc/bugs/424/ diff --git a/wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424/expected b/wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424/expected new file mode 100644 index 0000000..ffd5f8a --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424/expected @@ -0,0 +1,17 @@ + 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..... USE_LENGTH_UNITS(CANON_UNITS_INCHES) + N..... STRAIGHT_TRAVERSE(2.0000, 3.0000, 4.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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424/test.ngc new file mode 100644 index 0000000..94183d4 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424/test.ngc @@ -0,0 +1,6 @@ +g20 +#=2 +#atan[1]/[1]=3 +#3=4 +g0 x# y#45 z#3 +m2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/expected b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/expected new file mode 100644 index 0000000..0478e9f --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/expected @@ -0,0 +1,8 @@ + 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..... COMMENT("Test: nested sub definition inside named sub should error") + 8 N..... ON_RESET() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/subs/nested.ngc b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/subs/nested.ngc new file mode 100644 index 0000000..d24f36e --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/subs/nested.ngc @@ -0,0 +1,7 @@ +o sub +o100 sub +(DEBUG, inner o100: #1 #2 #3) +o100 endsub +o100 call [4] [5] [6] +o endsub +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/test.ini b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/test.ini new file mode 100644 index 0000000..594bb67 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/test.ini @@ -0,0 +1,2 @@ +[RS274NGC] +SUBROUTINE_PATH=subs diff --git a/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/test.ngc new file mode 100644 index 0000000..b1203ad --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/test.ngc @@ -0,0 +1,3 @@ +(Test: nested sub definition inside named sub should error) +o call [7] [8] [9] +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/test.sh new file mode 100644 index 0000000..b16f69e --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error/test.sh @@ -0,0 +1,4 @@ +#!/bin/bash -e +# Nested sub definition inside a called named sub must produce an error. +# Regression test for LinuxCNC/linuxcnc#3880. +! rs274 -g -i test.ini test.ngc diff --git a/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/expected b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/expected new file mode 100644 index 0000000..931f0d1 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/expected @@ -0,0 +1,9 @@ + 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..... COMMENT("Test: numbered sub after named endsub in same file should error") + 8 N..... MESSAGE(" sequential main: 7.000000 8.000000 9.000000") + 9 N..... ON_RESET() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/subs/sequential.ngc b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/subs/sequential.ngc new file mode 100644 index 0000000..e9fa72c --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/subs/sequential.ngc @@ -0,0 +1,9 @@ +o sub +(DEBUG, sequential main: #1 #2 #3) +o200 call [4] [5] [6] +o endsub + +o200 sub +(DEBUG, o200 helper: #1 #2 #3) +o200 endsub +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/test.ini b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/test.ini new file mode 100644 index 0000000..594bb67 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/test.ini @@ -0,0 +1,2 @@ +[RS274NGC] +SUBROUTINE_PATH=subs diff --git a/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/test.ngc new file mode 100644 index 0000000..e97cbb4 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/test.ngc @@ -0,0 +1,3 @@ +(Test: numbered sub after named endsub in same file should error) +o call [7] [8] [9] +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/test.sh new file mode 100644 index 0000000..cd42174 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error/test.sh @@ -0,0 +1,5 @@ +#!/bin/bash -e +# Numbered sub called from within a named sub file, where no matching +# file exists, must produce an error (forward-seek blocked). +# Regression test for LinuxCNC/linuxcnc#3880. +! rs274 -g -i test.ini test.ngc diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2/README b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2/README new file mode 100644 index 0000000..cdb07a7 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2/README @@ -0,0 +1 @@ +test for http://sourceforge.net/p/emc/bugs/315/, first case diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2/expected b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2/expected new file mode 100644 index 0000000..76a943f --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2/expected @@ -0,0 +1,17 @@ + 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(2.0000, 2.0000, 2.0000, 0.0000, 0.0000, 0.0000) + N..... MESSAGE("executing this one") + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2/test.ngc new file mode 100644 index 0000000..688d379 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2/test.ngc @@ -0,0 +1,18 @@ +o1 sub +g0 x1y1z1 +(debug,not executing this one) +o1 endsub + +o2 sub +g0 x2y2z2 +(debug,executing this one) +o2 endsub + +o sub +# = 2 +o# call +o endsub + +o call + +m2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315/README b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315/README new file mode 100644 index 0000000..cdb07a7 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315/README @@ -0,0 +1 @@ +test for http://sourceforge.net/p/emc/bugs/315/, first case diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315/expected b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315/expected new file mode 100644 index 0000000..fba23a9 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315/expected @@ -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..... MESSAGE("running sub") + N..... MESSAGE("breaking out of sub") + N..... MESSAGE("done") + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315/test.ngc new file mode 100644 index 0000000..136ab34 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315/test.ngc @@ -0,0 +1,14 @@ +o123 sub +o200 if [5 le 0.01] +o123 return +o200 endif +o124 while [1] +(debug,breaking out of sub) +o124 break +o124 endwhile +o123 endsub + +(debug,running sub) +o123 call +(debug,done) +m02 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-bug315/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/README b/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/README new file mode 100644 index 0000000..9c1b38f --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/README @@ -0,0 +1 @@ +Tests for proper unwind in a failed external o-word procedure. diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/expected b/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/expected new file mode 100644 index 0000000..81d3c6f --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/expected @@ -0,0 +1,16 @@ + 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(" pre divide-by-zero") + N..... MESSAGE(" pre divide-by-zero") + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/fail.ngc b/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/fail.ngc new file mode 100644 index 0000000..73dc76c --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/fail.ngc @@ -0,0 +1,9 @@ +(debug, pre ) +o sub +(debug, pre divide-by-zero) +#100 = [1/0] +(debug, post divide-by-zero) +o endsub +(debug, post ) +m2 + diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/test.ini b/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/test.ini new file mode 100644 index 0000000..5d1f5d4 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/test.ini @@ -0,0 +1,4 @@ +[RS274NGC] +SUBROUTINE_PATH=. + + diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/test.ngc new file mode 100644 index 0000000..d0d8018 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/test.ngc @@ -0,0 +1,3 @@ +o call +o call +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/test.sh new file mode 100644 index 0000000..22f60fd --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/oword-unwind/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -n 0 -i test.ini -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/return-value/expected b/wasm-port/vendor/linuxcnc/tests/interp/return-value/expected new file mode 100644 index 0000000..db7bc53 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/return-value/expected @@ -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..... MESSAGE("line 6.000000: _value: - expected 0.000000, got 0.000000") + N..... MESSAGE("line 28.000000: call with arg1=2.000000 expect 246.000000, got 246.000000") + N..... MESSAGE("line 37.000000: call with arg1=-1.000000 expect 0.000000, got 0.000000") + N..... MESSAGE("line 47.000000: call with arg1=0.000000 expect 4712.000000, got 4712.000000") + N..... MESSAGE("line 53.000000: _value=4712.000000 - expected 4712.000000") + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/return-value/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/return-value/test.ngc new file mode 100644 index 0000000..9f206e3 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/return-value/test.ngc @@ -0,0 +1,55 @@ +; test that #<_value> is accessible and is 0 + +; test for proper initialization of #<_value> if program is re-run +; see note at end of program +# = 0 +(debug,line #<_line>: _value: - expected #, got #<_value>) +o200 if [#<_value> NE 0] + (debug, fail: _value=#<_value> - expecting 0) +o200 endif + + +o1000 sub +o1010 if [#1 GT 0] +o1010 return [123*[#1]] +o1010 endif + +o1020 if [#1 LT 0] +o1020 return +o1020 endif + +o1000 endsub [4712] + + +; test returning value via 'return' +# = 2 +# = 246 +o1000 call [#] +(debug,line #<_line>: call with arg1=# expect #, got #<_value>) +o3000 if [#<_value> NE #] + (debug,line #<_line>: 'return' return value=#<_value> - expected #) +o3000 endif + +; test returning no value at all - plain old style 'return' +# = -1 +# = 0 +o1000 call [#] +(debug,line #<_line>: call with arg1=# expect #, got #<_value>) +o4000 if [#<_value> NE #] + (debug,line #<_line>: 'plain return' return value=#<_value> - expected #) +o4000 endif + + +; test returning value via 'endsub' +# = 0 +# = 4712 +o1000 call [#] +(debug,line #<_line>: call with arg1=# expect #, got #<_value>) +o2000 if [#<_value> NE #] + (debug,line #<_line>: 'endsub' return value=#<_value> - expected #) +o2000 endif + +; note #<_value> is 4712 at this point. +(debug,line #<_line>: _value=#<_value> - expected #) + +m2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/return-value/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/return-value/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/return-value/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/rotation/abs-pts/expected b/wasm-port/vendor/linuxcnc/tests/interp/rotation/abs-pts/expected new file mode 100644 index 0000000..5131a8c --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/rotation/abs-pts/expected @@ -0,0 +1,28 @@ + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") + N..... MESSAGE("0.000000 0.000000 0.000000") + N..... MESSAGE("1.000000 2.000000 3.000000") diff --git a/wasm-port/vendor/linuxcnc/tests/interp/rotation/abs-pts/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/rotation/abs-pts/test.ngc new file mode 100644 index 0000000..29a0e31 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/rotation/abs-pts/test.ngc @@ -0,0 +1,48 @@ +; Repeatedly move to 0,0,0 and 1,2,3 in machine coordinates, +; but with different offsets in effect; check that in each case, +; the values in #544x match the just-commanded g53 move +o sub +g53g0x0y0z0 +(debug,#<_abs_x> #<_abs_y> #<_abs_z>) +g53g0x1y2z3 +(debug,#<_abs_x> #<_abs_y> #<_abs_z>) +o endsub + +o sub +g54 +g92.2 +g10l2p1x0y0z0r0 +o call + +g10l2p1x3y7z0r0 +o call + +g10l2p1x0y0r45 +o call + +g10l2p1x3y7z0r45 +o call + +g10l2p1x0y0z0r0 +g92x3y7 +o call +g92.2 + +g10l2p1x3y7z0r0 +g92x3y7 +o call +g92.2 + +g10l2p1x3y7z0r45 +g92x3y7 +o call +g92.2 +o endsub + +g20 +o call + +g21 +o call + +m2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/rotation/abs-pts/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/rotation/abs-pts/test.sh new file mode 100644 index 0000000..53e9013 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/rotation/abs-pts/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc -t test.tbl | awk '/MESSAGE/ {$1=""; print}' | sed 's/-0\.0000/0.0000/g' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/rotation/abs-pts/test.tbl b/wasm-port/vendor/linuxcnc/tests/interp/rotation/abs-pts/test.tbl new file mode 100644 index 0000000..36b4d8f --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/rotation/abs-pts/test.tbl @@ -0,0 +1 @@ +t1 p1 x0 y0 z0 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/rotation/g28/expected b/wasm-port/vendor/linuxcnc/tests/interp/rotation/g28/expected new file mode 100644 index 0000000..61234cd --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/rotation/g28/expected @@ -0,0 +1,27 @@ + 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..... COMMENT("interpreter: setting coordinate system origin") + 8 N..... COMMENT("interpreter: setting coordinate system origin") + 9 N..... SET_G5X_OFFSET(2, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 10 N..... SET_G92_OFFSET(0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 11 N..... SET_XY_ROTATION(45.0000) + 12 N..... COMMENT("G55 10,10") + 13 N..... STRAIGHT_TRAVERSE(10.0000, 10.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 14 N..... COMMENT("G55 G28") + 15 N..... STRAIGHT_TRAVERSE(10.0000, 10.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 16 N..... STRAIGHT_TRAVERSE(10.0000, 10.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 17 N..... SET_G5X_OFFSET(3, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 18 N..... SET_G92_OFFSET(0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 19 N..... SET_XY_ROTATION(0.0000) + 20 N..... COMMENT("G56 cp") + 21 N..... STRAIGHT_TRAVERSE(0.0000, 14.1421, 0.0000, 1.0000, 0.0000, 0.0000) + 22 N..... COMMENT("G56 G28") + 23 N..... STRAIGHT_TRAVERSE(0.0000, 14.1421, 0.0000, 1.0000, 0.0000, 0.0000) + 24 N..... STRAIGHT_TRAVERSE(0.0000, 14.1421, 0.0000, 0.0000, 0.0000, 0.0000) + 25 N..... FINISH() + 26 N..... ON_RESET() + 27 N..... ON_RESET() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/rotation/g28/g28.ngc b/wasm-port/vendor/linuxcnc/tests/interp/rotation/g28/g28.ngc new file mode 100644 index 0000000..5edeaf4 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/rotation/g28/g28.ngc @@ -0,0 +1,15 @@ +% +G10 L2 P2 X0 Y0 R45; G55 +G10 L2 P3 X0 Y0; G56 +G55 +(G55 10,10) +G0 x10 y10 +G28.1 +(G55 G28) +G28 +G56 +(G56 cp) +G0 a1 +(G56 G28) +G28 +% diff --git a/wasm-port/vendor/linuxcnc/tests/interp/rotation/g28/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/rotation/g28/test.sh new file mode 100755 index 0000000..998595e --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/rotation/g28/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g g28.ngc | sed 's/-0\.0000/0.0000/g' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/rotation/g53/expected b/wasm-port/vendor/linuxcnc/tests/interp/rotation/g53/expected new file mode 100644 index 0000000..b9c5f28 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/rotation/g53/expected @@ -0,0 +1,30 @@ + 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..... COMMENT("interpreter: setting coordinate system origin") + 8 N..... COMMENT("interpreter: setting coordinate system origin") + 9 N..... SET_G5X_OFFSET(2, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 10 N..... SET_G92_OFFSET(0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 11 N..... SET_XY_ROTATION(45.0000) + 12 N..... COMMENT("g55 to 1,1") + 13 N..... STRAIGHT_TRAVERSE(1.0000, 1.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 14 N..... COMMENT("g53 + g55 to 1,1") + 15 N..... STRAIGHT_TRAVERSE(1.4142, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 16 N..... SET_G92_OFFSET(1.4142, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 17 N..... COMMENT("g55 + g92 to 1,1") + 18 N..... STRAIGHT_TRAVERSE(1.0000, 1.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 19 N..... COMMENT("g53 + g55 + g92 to 1,1") + 20 N..... STRAIGHT_TRAVERSE(0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 21 N..... SET_G5X_OFFSET(3, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 22 N..... SET_G92_OFFSET(1.4142, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 23 N..... SET_XY_ROTATION(0.0000) + 24 N..... COMMENT("g56 + g92 to cp") + 25 N..... STRAIGHT_TRAVERSE(-0.4142, 1.0000, 0.0000, 1.0000, 0.0000, 0.0000) + 26 N..... COMMENT("g53 + g56 + g92 to 1,1") + 27 N..... STRAIGHT_TRAVERSE(-0.4142, 1.0000, 0.0000, 1.0000, 0.0000, 0.0000) + 28 N..... FINISH() + 29 N..... ON_RESET() + 30 N..... ON_RESET() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/rotation/g53/g53.ngc b/wasm-port/vendor/linuxcnc/tests/interp/rotation/g53/g53.ngc new file mode 100644 index 0000000..aedc0e8 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/rotation/g53/g53.ngc @@ -0,0 +1,19 @@ +% +g10 l2 p2 x0 y0 z0 r45; g55 +g10 l2 p3 x0 y0 z0 r0; g56 +g55 +(g55 to 1,1) +g0 x1 y1 +(g53 + g55 to 1,1) +g53 x1 y1 +g92 x0 y0 +(g55 + g92 to 1,1) +g0 x1 y1 +(g53 + g55 + g92 to 1,1) +g53 g0 x1 y1 +g56 +(g56 + g92 to cp) +g0 a1 +(g53 + g56 + g92 to 1,1) +g53 g0 x1 y1 +% diff --git a/wasm-port/vendor/linuxcnc/tests/interp/rotation/g53/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/rotation/g53/test.sh new file mode 100755 index 0000000..8ced2f7 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/rotation/g53/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g g53.ngc | sed 's/-0\.0000/0.0000/g' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/README b/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/README new file mode 100644 index 0000000..c892f8c --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/README @@ -0,0 +1 @@ +Test that line numbers in external subs are correct diff --git a/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/expected b/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/expected new file mode 100644 index 0000000..8dbe5df --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/expected @@ -0,0 +1,17 @@ + 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..... MESSAGE("main: line=7.000000 - expect 7") + 8 N..... MESSAGE(" in rm400.ngc line=2.000000 - expect 2") + 9 N..... MESSAGE("main: line=9.000000 - expect 9") + 10 N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 11 N..... SET_XY_ROTATION(0.0000) + 12 N..... SET_FEED_MODE(0, 0) + 13 N..... SET_FEED_RATE(0.0000) + 14 N..... STOP_SPINDLE_TURNING(0) + 15 N..... SET_SPINDLE_MODE(0 0.0000) + 16 N..... PROGRAM_END() + 17 N..... ON_RESET() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/rm400.ngc b/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/rm400.ngc new file mode 100644 index 0000000..4e2a2d6 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/rm400.ngc @@ -0,0 +1,5 @@ +o sub +(debug, in rm400.ngc line=#<_line> - expect 2) +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/test.ini b/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/test.ini new file mode 100644 index 0000000..539c5e7 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/test.ini @@ -0,0 +1,2 @@ +[RS274NGC] +SUBROUTINE_PATH=. diff --git a/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/test.ngc new file mode 100644 index 0000000..8555ded --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/test.ngc @@ -0,0 +1,10 @@ + + + + + + +(debug,main: line=#<_line> - expect 7) +ocall +(debug,main: line=#<_line> - expect 9) +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/test.sh new file mode 100644 index 0000000..6b3fe6d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/sequence-number/test.sh @@ -0,0 +1,2 @@ +#!/bin/bash +exec rs274 -n 0 -i test.ini -g test.ngc diff --git a/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/expected b/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/expected new file mode 100644 index 0000000..dc9e741 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/expected @@ -0,0 +1,17 @@ + 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("Test: calling a sub from within another sub is valid") + caller: 1.000000 2.000000 3.000000 + helper: 4.000000 5.000000 6.000000 + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/subs/caller.ngc b/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/subs/caller.ngc new file mode 100644 index 0000000..bcf652a --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/subs/caller.ngc @@ -0,0 +1,5 @@ +o sub +(PRINT,X caller: #1 #2 #3) +o call [4] [5] [6] +o endsub +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/subs/helper.ngc b/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/subs/helper.ngc new file mode 100644 index 0000000..d4cbee0 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/subs/helper.ngc @@ -0,0 +1,4 @@ +o sub +(PRINT,X helper: #1 #2 #3) +o endsub +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/test.ini b/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/test.ini new file mode 100644 index 0000000..594bb67 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/test.ini @@ -0,0 +1,2 @@ +[RS274NGC] +SUBROUTINE_PATH=subs diff --git a/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/test.ngc new file mode 100644 index 0000000..1e57774 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/test.ngc @@ -0,0 +1,3 @@ +(Test: calling a sub from within another sub is valid) +o call [1] [2] [3] +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/test.sh new file mode 100644 index 0000000..a186370 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub/test.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Calling a sub from within another sub must work. +# This verifies that the nested definition check does not +# incorrectly block valid nested calls. +# Regression test for LinuxCNC/linuxcnc#3880. +rs274 -g -i test.ini test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/interp/subs-follow-main/expected b/wasm-port/vendor/linuxcnc/tests/interp/subs-follow-main/expected new file mode 100644 index 0000000..218840f --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/subs-follow-main/expected @@ -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..... COMMENT("Subs may follow main program ") + IN O1 + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/interp/subs-follow-main/test.ngc b/wasm-port/vendor/linuxcnc/tests/interp/subs-follow-main/test.ngc new file mode 100644 index 0000000..2ce80ff --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/subs-follow-main/test.ngc @@ -0,0 +1,10 @@ +% +( Subs may follow main program ) + +O1 call +M30 + +O1 sub +(PRINT,X IN O1) +O1 endsub +% diff --git a/wasm-port/vendor/linuxcnc/tests/interp/subs-follow-main/test.sh b/wasm-port/vendor/linuxcnc/tests/interp/subs-follow-main/test.sh new file mode 100644 index 0000000..2afa80d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/interp/subs-follow-main/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/README b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/README new file mode 100644 index 0000000..1cd6d7d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/README @@ -0,0 +1,14 @@ +This tests for a specific interpreter regression where in very +specific circumstances involving remapped functions, +`_setup.sequence_number` is reset, which triggers the "duplicate +O-word label" sanity check. + +This test triggers the regression by calling a remap twice. In the first +call, before the problem O-word, it calls a second-level remap that +returns with a reset `_setup.sequence_number`, so the following O-word +is recorded with an incorrect position. + +In the second call, the second-level remap is not invoked, so the +following O-word appears at the correct `_setup.sequence_number`; the +differing positions then triggers the "duplicate O-word label" sanity +check and the program exits with an error. diff --git a/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/expected b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/expected new file mode 100644 index 0000000..ce21d35 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/expected @@ -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..... MESSAGE(" executing m207: run remapped m208 before o") + N..... MESSAGE(" rm207 executing problem if") + N..... MESSAGE(" rm207 within problem if") + N..... MESSAGE(" rm207 done executing problem if") + N..... MESSAGE(" executing m207: do NOT run remapped m208 before o") + N..... MESSAGE(" rm207 running remapped m208") + N..... MESSAGE(" rm208 starting and done") + N..... MESSAGE(" rm207 executing problem if") + N..... MESSAGE(" rm207 within problem if") + N..... MESSAGE(" rm207 done executing problem if") + N..... FINISH() + N..... ON_RESET() diff --git a/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/rm207.ngc b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/rm207.ngc new file mode 100644 index 0000000..2c8fcc1 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/rm207.ngc @@ -0,0 +1,11 @@ +o sub +o if [#<_killme> GT 0] + (debug, rm207 running remapped m208) + m208 +o endif +(debug, rm207 executing problem if) +o if [6] + (debug, rm207 within problem if) +o endif +(debug, rm207 done executing problem if) +o endsub diff --git a/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/rm208.ngc b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/rm208.ngc new file mode 100644 index 0000000..d9a978b --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/rm208.ngc @@ -0,0 +1,3 @@ +o sub +(debug, rm208 starting and done) +o endsub diff --git a/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/test.ini b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/test.ini new file mode 100644 index 0000000..a9571ca --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/test.ini @@ -0,0 +1,12 @@ +[EMC] +DEBUG=65535 +LOG_LEVEL=5000 + +[RS274NGC] +DEBUG=65535 +LOG_LEVEL=5000 + +SUBROUTINE_PATH = . + +REMAP=M207 modalgroup=10 ngc=rm207 +REMAP=M208 modalgroup=10 ngc=rm208 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/test.ngc b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/test.ngc new file mode 100644 index 0000000..21d77f2 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/test.ngc @@ -0,0 +1,8 @@ +% +(debug, executing m207: run remapped m208 before o) +#<_killme> = 0 +m207 +(debug, executing m207: do NOT run remapped m208 before o) +#<_killme> = 1 +m207 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/test.sh b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/test.sh new file mode 100755 index 0000000..99269de --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word/test.sh @@ -0,0 +1,4 @@ +#!/bin/bash +export INI_FILE_NAME=test.ini +rs274 -i "$INI_FILE_NAME" -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/README b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/README new file mode 100644 index 0000000..51718c2 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/README @@ -0,0 +1 @@ +Exercise parameter passing to user-defined code diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/expected b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/expected new file mode 100644 index 0000000..91a6aed --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/expected @@ -0,0 +1,17 @@ + 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(" M400 call_level= 1.000000 remap_level=1.000000") + N..... MESSAGE(" P word set: 47.110000") + N..... MESSAGE(" Q word set: 8.150000") + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/rm400.ngc b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/rm400.ngc new file mode 100644 index 0000000..a1186c2 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/rm400.ngc @@ -0,0 +1,18 @@ +o sub +(debug, M400 call_level= #<_call_level> remap_level=#<_remap_level>) + +o100 if [EXISTS[#

]] + (debug, P word set: #

) +o100 else + (debug, P word missing) +o100 endif + +o120 if [EXISTS[#]] + (debug, Q word set: #) +o120 else + (debug, Q word missing) +o120 endif + +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/test.ini b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/test.ini new file mode 100644 index 0000000..094a262 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/test.ini @@ -0,0 +1,9 @@ +[EMC] +DEBUG=0 +LOG_LEVEL=0 + +[RS274NGC] +SUBROUTINE_PATH = . + +# M405 requires P- Q- and does NOT permit any other words in this block +REMAP=M400 modalgroup=5 argspec=PQ ngc=rm400 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/test.ngc b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/test.ngc new file mode 100644 index 0000000..e44e5b1 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/test.ngc @@ -0,0 +1,2 @@ +M400 P47.11 Q8.15 +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/test.sh b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/test.sh new file mode 100755 index 0000000..bb2a78e --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.0/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -i test.ini -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/README b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/README new file mode 100644 index 0000000..a4da547 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/README @@ -0,0 +1,3 @@ +Exercise failed parameter passing to user-defined code + +The required Q parameter is missing diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/expected b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/expected new file mode 100644 index 0000000..44c03f6 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/expected @@ -0,0 +1,17 @@ +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() +user-defined M400: missing: Q +O call + 7 N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 8 N..... SET_XY_ROTATION(0.0000) + 9 N..... SET_FEED_MODE(0, 0) + 10 N..... SET_FEED_RATE(0.0000) + 11 N..... STOP_SPINDLE_TURNING(0) + 12 N..... SET_SPINDLE_MODE(0 0.0000) + 13 N..... PROGRAM_END() + 14 N..... ON_RESET() diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/rm400.ngc b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/rm400.ngc new file mode 100644 index 0000000..a1186c2 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/rm400.ngc @@ -0,0 +1,18 @@ +o sub +(debug, M400 call_level= #<_call_level> remap_level=#<_remap_level>) + +o100 if [EXISTS[#

]] + (debug, P word set: #

) +o100 else + (debug, P word missing) +o100 endif + +o120 if [EXISTS[#]] + (debug, Q word set: #) +o120 else + (debug, Q word missing) +o120 endif + +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/test.ini b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/test.ini new file mode 100644 index 0000000..094a262 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/test.ini @@ -0,0 +1,9 @@ +[EMC] +DEBUG=0 +LOG_LEVEL=0 + +[RS274NGC] +SUBROUTINE_PATH = . + +# M405 requires P- Q- and does NOT permit any other words in this block +REMAP=M400 modalgroup=5 argspec=PQ ngc=rm400 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/test.ngc b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/test.ngc new file mode 100644 index 0000000..33c038b --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/test.ngc @@ -0,0 +1,2 @@ +M400 P47.11 +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/test.sh b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/test.sh new file mode 100755 index 0000000..974f697 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.1/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -i test.ini -n 0 -g test.ngc 2>&1 +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/README b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/README new file mode 100644 index 0000000..a4da547 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/README @@ -0,0 +1,3 @@ +Exercise failed parameter passing to user-defined code + +The required Q parameter is missing diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/expected b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/expected new file mode 100644 index 0000000..b9133bf --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/expected @@ -0,0 +1,17 @@ +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() +user-defined M400: missing: P,Q +O call + 7 N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 8 N..... SET_XY_ROTATION(0.0000) + 9 N..... SET_FEED_MODE(0, 0) + 10 N..... SET_FEED_RATE(0.0000) + 11 N..... STOP_SPINDLE_TURNING(0) + 12 N..... SET_SPINDLE_MODE(0 0.0000) + 13 N..... PROGRAM_END() + 14 N..... ON_RESET() diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/rm400.ngc b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/rm400.ngc new file mode 100644 index 0000000..a1186c2 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/rm400.ngc @@ -0,0 +1,18 @@ +o sub +(debug, M400 call_level= #<_call_level> remap_level=#<_remap_level>) + +o100 if [EXISTS[#

]] + (debug, P word set: #

) +o100 else + (debug, P word missing) +o100 endif + +o120 if [EXISTS[#]] + (debug, Q word set: #) +o120 else + (debug, Q word missing) +o120 endif + +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/test.ini b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/test.ini new file mode 100644 index 0000000..094a262 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/test.ini @@ -0,0 +1,9 @@ +[EMC] +DEBUG=0 +LOG_LEVEL=0 + +[RS274NGC] +SUBROUTINE_PATH = . + +# M405 requires P- Q- and does NOT permit any other words in this block +REMAP=M400 modalgroup=5 argspec=PQ ngc=rm400 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/test.ngc b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/test.ngc new file mode 100644 index 0000000..f1627af --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/test.ngc @@ -0,0 +1,2 @@ +M400 R122.25 +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/test.sh b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/test.sh new file mode 100755 index 0000000..974f697 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/args.2/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -i test.ini -n 0 -g test.ngc 2>&1 +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/README b/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/README new file mode 100644 index 0000000..c28025f --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/README @@ -0,0 +1 @@ +Exercise failed remap NGC procedure - must properly return to top level diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/expected b/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/expected new file mode 100644 index 0000000..dc6b997 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/expected @@ -0,0 +1,20 @@ +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..... MESSAGE(" before M400: call_level= 0.000000 remap_level=0.000000") + 8 N..... MESSAGE(" in rm400: call_level= 1.000000 remap_level=1.000000") +Attempt to divide by zero +#100 = [1/0] + 9 N..... MESSAGE(" after failed M400: call_level= 0.000000 remap_level=0.000000") + 10 N..... SET_G5X_OFFSET(1, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000) + 11 N..... SET_XY_ROTATION(0.0000) + 12 N..... SET_FEED_MODE(0, 0) + 13 N..... SET_FEED_RATE(0.0000) + 14 N..... STOP_SPINDLE_TURNING(0) + 15 N..... SET_SPINDLE_MODE(0 0.0000) + 16 N..... PROGRAM_END() + 17 N..... ON_RESET() diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/rm400.ngc b/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/rm400.ngc new file mode 100644 index 0000000..1ffac1c --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/rm400.ngc @@ -0,0 +1,6 @@ +o sub +(debug, in rm400: call_level= #<_call_level> remap_level=#<_remap_level>) +#100 = [1/0] +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/test.ini b/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/test.ini new file mode 100644 index 0000000..9662bfb --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/test.ini @@ -0,0 +1,9 @@ +[EMC] +DEBUG=0 +LOG_LEVEL=0 + +[RS274NGC] +SUBROUTINE_PATH = . + +REMAP=M400 modalgroup=5 ngc=rm400 + diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/test.ngc b/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/test.ngc new file mode 100644 index 0000000..138d7f4 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/test.ngc @@ -0,0 +1,4 @@ +(debug, before M400: call_level= #<_call_level> remap_level=#<_remap_level>) +M400 +(debug, after failed M400: call_level= #<_call_level> remap_level=#<_remap_level>) +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/test.sh b/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/test.sh new file mode 100755 index 0000000..974f697 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -i test.ini -n 0 -g test.ngc 2>&1 +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/README b/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/README new file mode 100644 index 0000000..4dee499 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/README @@ -0,0 +1,2 @@ +M30 and M02 reset the interpreter's `remap_level`. This test checks +for interaction of remapped commands with those M codes. diff --git a/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/expected b/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/expected new file mode 100644 index 0000000..026745e --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/expected @@ -0,0 +1,17 @@ +executing +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("m400 call_level=1.000000 remap_level=1.000000 line=2.000000") +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() diff --git a/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/rm400.ngc b/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/rm400.ngc new file mode 100644 index 0000000..00c59a3 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/rm400.ngc @@ -0,0 +1,5 @@ +o sub +(debug,m400 call_level=#<_call_level> remap_level=#<_remap_level> line=#<_line>) +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/test.ini b/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/test.ini new file mode 100644 index 0000000..889611f --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/test.ini @@ -0,0 +1,8 @@ +[EMC] +DEBUG=0 +LOG_LEVEL=0 + +[RS274NGC] +SUBROUTINE_PATH = . + +REMAP=M400 modalgroup=10 ngc=rm400 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/test.ngc b/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/test.ngc new file mode 100644 index 0000000..3c907bd --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/test.ngc @@ -0,0 +1 @@ +M400 M30 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/test.sh b/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/test.sh new file mode 100755 index 0000000..a3af97b --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/m30-interaction/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -i test.ini -g test.ngc 2>&1 | sed 's/^ *[0-9]* //' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/README b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/README new file mode 100644 index 0000000..71a9a6a --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/README @@ -0,0 +1,8 @@ +Exercise nested remaps - three levels deep + +each invocation bumps both call and remap level +at end of invocation both most be 0 + +also verify correct propagation and restore of sequence numbers + + diff --git a/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/expected b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/expected new file mode 100644 index 0000000..33716f2 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/expected @@ -0,0 +1,18 @@ +executing +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("main call_level=0.000000 remap_level=0.000000 line=2.000000") +N..... MESSAGE("m400 handler pre call_level=1.000000 remap_level=1.000000 line=2.000000") +N..... MESSAGE("m401 handler pre call_level=2.000000 remap_level=2.000000 line=2.000000") +N..... MESSAGE("m402 handler pre call_level=3.000000 remap_level=3.000000 line=2.000000") +N..... MESSAGE("m403 handler pre call_level=4.000000 remap_level=4.000000 line=2.000000") +N..... MESSAGE("m402 handler post call_level=3.000000 remap_level=3.000000 line=4.000000") +N..... MESSAGE("m401 handler post call_level=2.000000 remap_level=2.000000 line=4.000000") +N..... MESSAGE("m400 handler post call_level=1.000000 remap_level=1.000000 line=4.000000") +N..... MESSAGE("main call_level=0.000000 remap_level=0.000000 line=4.000000") +N..... FINISH() +N..... ON_RESET() diff --git a/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/rm400.ngc b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/rm400.ngc new file mode 100644 index 0000000..6121a71 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/rm400.ngc @@ -0,0 +1,7 @@ +o sub +(debug,m400 handler pre call_level=#<_call_level> remap_level=#<_remap_level> line=#<_line>) +m401 +(debug,m400 handler post call_level=#<_call_level> remap_level=#<_remap_level> line=#<_line>) +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/rm401.ngc b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/rm401.ngc new file mode 100644 index 0000000..a7cea06 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/rm401.ngc @@ -0,0 +1,7 @@ +o sub +(debug,m401 handler pre call_level=#<_call_level> remap_level=#<_remap_level> line=#<_line>) +m402 +(debug,m401 handler post call_level=#<_call_level> remap_level=#<_remap_level> line=#<_line>) +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/rm402.ngc b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/rm402.ngc new file mode 100644 index 0000000..3e7e492 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/rm402.ngc @@ -0,0 +1,7 @@ +o sub +(debug,m402 handler pre call_level=#<_call_level> remap_level=#<_remap_level> line=#<_line>) +m403 +(debug,m402 handler post call_level=#<_call_level> remap_level=#<_remap_level> line=#<_line>) +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/rm403.ngc b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/rm403.ngc new file mode 100644 index 0000000..d442228 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/rm403.ngc @@ -0,0 +1,6 @@ +o sub +(debug,m403 handler pre call_level=#<_call_level> remap_level=#<_remap_level> line=#<_line>) +o endsub +(debug,m403 handler post call_level=#<_call_level> remap_level=#<_remap_level> line=#<_line>) +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/test.ini b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/test.ini new file mode 100644 index 0000000..ebba173 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/test.ini @@ -0,0 +1,11 @@ +[EMC] +DEBUG=0 +LOG_LEVEL=0 + +[RS274NGC] +SUBROUTINE_PATH = . + +REMAP=M400 modalgroup=10 ngc=rm400 +REMAP=M401 modalgroup=10 ngc=rm401 +REMAP=M402 modalgroup=10 ngc=rm402 +REMAP=M403 modalgroup=10 ngc=rm403 \ No newline at end of file diff --git a/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/test.ngc b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/test.ngc new file mode 100644 index 0000000..a77aab8 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/test.ngc @@ -0,0 +1,5 @@ +% +(debug,main call_level=#<_call_level> remap_level=#<_remap_level> line=#<_line>) +m400 +(debug,main call_level=#<_call_level> remap_level=#<_remap_level> line=#<_line>) +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/test.sh b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/test.sh new file mode 100755 index 0000000..a3af97b --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -i test.ini -g test.ngc 2>&1 | sed 's/^ *[0-9]* //' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/testsub.ngc b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/testsub.ngc new file mode 100644 index 0000000..64c0fd2 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword/testsub.ngc @@ -0,0 +1,6 @@ +o sub +(debug, call_level=#<_call_level> remap_level=#<_remap_level>) +m401 +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/README b/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/README new file mode 100644 index 0000000..eca4312 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/README @@ -0,0 +1,3 @@ +Exercise passing positional parameters to an NGC remap procedure + +Verify ordering and argument count diff --git a/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/expected b/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/expected new file mode 100644 index 0000000..4092d28 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/expected @@ -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..... MESSAGE(" in rg881: n_args=3.000000 [1.000000] [2.000000] [3.000000] [0.000000] [0.000000]") + N..... MESSAGE(" in rg881: n_args=4.000000 [1.000000] [2.000000] [3.000000] [4.000000] [0.000000]") + N..... MESSAGE(" in rg881: n_args=4.000000 [1.000000] [2.000000] [3.000000] [5.000000] [0.000000]") + N..... MESSAGE(" in rg881: n_args=5.000000 [1.000000] [2.000000] [3.000000] [4.000000] [5.000000]") + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/rg881.ngc b/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/rg881.ngc new file mode 100644 index 0000000..e19cb15 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/rg881.ngc @@ -0,0 +1,5 @@ +o sub +(debug, in rg881: n_args=# [#1] [#2] [#3] [#4] [#5]) +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/test.ini b/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/test.ini new file mode 100644 index 0000000..1a32809 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/test.ini @@ -0,0 +1,9 @@ +[EMC] +DEBUG=0 +LOG_LEVEL=0 + +[RS274NGC] +SUBROUTINE_PATH = . +OWORD_NARGS = 1 + +REMAP=G88.1 modalgroup=1 argspec=@XYZpq ngc=rg881 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/test.ngc b/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/test.ngc new file mode 100644 index 0000000..f0f4e32 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/test.ngc @@ -0,0 +1,7 @@ +G88.1 X1 Y2 Z3 +; NB: with positional argument calling it is impossible to tell which +; one of several optional parameters was passed! +G88.1 X1 Y2 Z3 P4 +G88.1 X1 Y2 Z3 Q5 +G88.1 X1 Y2 Z3 P4 Q5 +M2 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/test.sh b/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/test.sh new file mode 100755 index 0000000..c4f19fb --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/posargs.0/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +rs274 -i test.ini -n 0 -g test.ngc| awk '{$1=""; print}' +exit "${PIPESTATUS[0]}" diff --git a/wasm-port/vendor/linuxcnc/tests/remap/remap-io/README b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/README new file mode 100644 index 0000000..fb136ce --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/README @@ -0,0 +1,16 @@ +This test verifies that M62-M68 can be remapped through both python +and NGC, and that calling the original M-codes is supported in the +remap subroutine. + +It also serves as an example of how to do this, since esp. the M66 +python function is not trivial and must be a generator yielding +`INTERP_EXECUTE_FINISH`. + +The recursive call to the original functions needs supporting code for +mode 5 M-codes in `interp_convert.cc` `convert_m()`, and for M62-M68 +in `rs274ngc_pre.cc`, `find_remappings()`. + +The peculiar M66 needs special handling in the interpreter for +`input_flag`, and to ensure that its result (in param `#5399`) is +available within the remap, `Interp::pycall()` runs `read_inputs()` +before returning control back to the python generator. diff --git a/wasm-port/vendor/linuxcnc/tests/remap/remap-io/expected b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/expected new file mode 100644 index 0000000..9fa9f6f --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/expected @@ -0,0 +1,123 @@ +********** Testing python remaps +----Testing M62/M63 digital output w/motion---- +cmd: "M62 P1" + M62 remapping pre: motion dout0=0; hal d_out=0 + M62 remapping post: motion dout0=1; hal d_out=1 +cmd: "M63 P1" + M63 remapping pre: motion dout0=1; hal d_out=1 + M63 remapping post: motion dout0=0; hal d_out=0 +cmd: "M62 P1" + M62 remapping pre: motion dout0=0; hal d_out=0 + M62 remapping post: motion dout0=1; hal d_out=1 +cmd: "M63 P1" + M63 remapping pre: motion dout0=1; hal d_out=1 + M63 remapping post: motion dout0=0; hal d_out=0 +----Testing M64/M65 digital output, immediate---- +cmd: "M64 P1" + M64 remapping pre: motion dout0=0; hal d_out=0 + M64 remapping post: motion dout0=1; hal d_out=1 +cmd: "M65 P1" + M65 remapping pre: motion dout0=1; hal d_out=1 + M65 remapping post: motion dout0=0; hal d_out=0 +cmd: "M64 P1" + M64 remapping pre: motion dout0=0; hal d_out=0 + M64 remapping post: motion dout0=1; hal d_out=1 +cmd: "M65 P1" + M65 remapping pre: motion dout0=1; hal d_out=1 + M65 remapping post: motion dout0=0; hal d_out=0 +----Testing M66 digital input---- +cmd: "M66 P1"; input: 1.0000 + M66 remapping pre: 5399=0.000000; 100=0.000000; ain0=0.00; din0=0 + M66 remapping post: 5399=1.000000; 100=1.000000; ain0=0.00; din0=1 +cmd: "M66 P1"; input: 0.0000 + M66 remapping pre: 5399=1.000000; 100=1.000000; ain0=0.00; din0=1 + M66 remapping post: 5399=0.000000; 100=0.000000; ain0=0.00; din0=0 +----Testing M66 analog input---- +cmd: "M66 E1 L0"; input: 42.1300 + M66 remapping pre: 5399=0.000000; 100=0.000000; ain0=0.00; din0=0 + M66 remapping post: 5399=42.130000; 100=42.130000; ain0=42.13; din0=0 +cmd: "M66 E1 L0"; input: -13.4200 + M66 remapping pre: 5399=42.130000; 100=42.130000; ain0=42.13; din0=0 + M66 remapping post: 5399=-13.420000; 100=-13.420000; ain0=-13.42; din0=0 +----Testing M67 analog output w/motion---- +cmd: "M67 E1 Q42.13" + M67 remapping pre: motion aout0=0.00; hal a_out=0.00 + M67 remapping post: motion aout0=42.13; hal a_out=42.13 +cmd: "M67 E1 Q-13.42" + M67 remapping pre: motion aout0=42.13; hal a_out=42.13 + M67 remapping post: motion aout0=-13.42; hal a_out=-13.42 +cmd: "M67 E1 Q0.00" + M67 remapping pre: motion aout0=-13.42; hal a_out=-13.42 + M67 remapping post: motion aout0=0.00; hal a_out=0.00 +----Testing M68 analog output, immediate---- +cmd: "M68 E1 Q42.13" + M68 remapping pre: motion aout0=0.00; hal a_out=0.00 + M68 remapping post: motion aout0=42.13; hal a_out=42.13 +cmd: "M68 E1 Q-13.42" + M68 remapping pre: motion aout0=42.13; hal a_out=42.13 + M68 remapping post: motion aout0=-13.42; hal a_out=-13.42 +cmd: "M68 E1 Q0.00" + M68 remapping pre: motion aout0=-13.42; hal a_out=-13.42 + M68 remapping post: motion aout0=0.00; hal a_out=0.00 + +********** Testing ngc remaps +----Testing M62/M63 digital output w/motion---- +cmd: "M62 P1" + M62 remapping pre: motion dout0=0; hal d_out=0 + M62 remapping post: motion dout0=1; hal d_out=1 +cmd: "M63 P1" + M63 remapping pre: motion dout0=1; hal d_out=1 + M63 remapping post: motion dout0=0; hal d_out=0 +cmd: "M62 P1" + M62 remapping pre: motion dout0=0; hal d_out=0 + M62 remapping post: motion dout0=1; hal d_out=1 +cmd: "M63 P1" + M63 remapping pre: motion dout0=1; hal d_out=1 + M63 remapping post: motion dout0=0; hal d_out=0 +----Testing M64/M65 digital output, immediate---- +cmd: "M64 P1" + M64 remapping pre: motion dout0=0; hal d_out=0 + M64 remapping post: motion dout0=1; hal d_out=1 +cmd: "M65 P1" + M65 remapping pre: motion dout0=1; hal d_out=1 + M65 remapping post: motion dout0=0; hal d_out=0 +cmd: "M64 P1" + M64 remapping pre: motion dout0=0; hal d_out=0 + M64 remapping post: motion dout0=1; hal d_out=1 +cmd: "M65 P1" + M65 remapping pre: motion dout0=1; hal d_out=1 + M65 remapping post: motion dout0=0; hal d_out=0 +----Testing M66 digital input---- +cmd: "M66 P1"; input: 1.0000 + M66 remapping pre: 5399=0.000000; 100=0.000000; ain0=0.00; din0=0 + M66 remapping post: 5399=1.000000; 100=1.000000; ain0=0.00; din0=1 +cmd: "M66 P1"; input: 0.0000 + M66 remapping pre: 5399=1.000000; 100=1.000000; ain0=0.00; din0=1 + M66 remapping post: 5399=0.000000; 100=0.000000; ain0=0.00; din0=0 +----Testing M66 analog input---- +cmd: "M66 E1 L0"; input: 42.1300 + M66 remapping pre: 5399=0.000000; 100=0.000000; ain0=0.00; din0=0 + M66 remapping post: 5399=42.130000; 100=42.130000; ain0=42.13; din0=0 +cmd: "M66 E1 L0"; input: -13.4200 + M66 remapping pre: 5399=42.130000; 100=42.130000; ain0=42.13; din0=0 + M66 remapping post: 5399=-13.420000; 100=-13.420000; ain0=-13.42; din0=0 +----Testing M67 analog output w/motion---- +cmd: "M67 E1 Q42.13" + M67 remapping pre: motion aout0=0.00; hal a_out=0.00 + M67 remapping post: motion aout0=42.13; hal a_out=42.13 +cmd: "M67 E1 Q-13.42" + M67 remapping pre: motion aout0=42.13; hal a_out=42.13 + M67 remapping post: motion aout0=-13.42; hal a_out=-13.42 +cmd: "M67 E1 Q0.00" + M67 remapping pre: motion aout0=-13.42; hal a_out=-13.42 + M67 remapping post: motion aout0=0.00; hal a_out=0.00 +----Testing M68 analog output, immediate---- +cmd: "M68 E1 Q42.13" + M68 remapping pre: motion aout0=0.00; hal a_out=0.00 + M68 remapping post: motion aout0=42.13; hal a_out=42.13 +cmd: "M68 E1 Q-13.42" + M68 remapping pre: motion aout0=42.13; hal a_out=42.13 + M68 remapping post: motion aout0=-13.42; hal a_out=-13.42 +cmd: "M68 E1 Q0.00" + M68 remapping pre: motion aout0=-13.42; hal a_out=-13.42 + M68 remapping post: motion aout0=0.00; hal a_out=0.00 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_input_m66.ngc b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_input_m66.ngc new file mode 100644 index 0000000..d7f6dba --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_input_m66.ngc @@ -0,0 +1,13 @@ +o sub +(debug,X io_input_M66 remapping pre: 5399=#5399) +o if [EXISTS[#]] + ; analog input + M66 E0 L0 +o else + ; digital input + M66 P0 L0 +o endif +; Result should be available here after M66; save it for test to check +#100 = #5399 +(debug,X io_input_M66 remapping post: 5399=#5399) +o endsub diff --git a/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m62.ngc b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m62.ngc new file mode 100644 index 0000000..22df6ed --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m62.ngc @@ -0,0 +1,5 @@ +o sub +(debug,X io_output_M62 remapping pre: 5399=#5399) +M62 P0 +(debug,X io_output_M62 remapping post: 5399=#5399) +o endsub diff --git a/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m63.ngc b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m63.ngc new file mode 100644 index 0000000..b3cf4b5 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m63.ngc @@ -0,0 +1,3 @@ +o sub +M63 P0 +o endsub diff --git a/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m64.ngc b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m64.ngc new file mode 100644 index 0000000..068ce8e --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m64.ngc @@ -0,0 +1,3 @@ +o sub +M64 P0 +o endsub diff --git a/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m65.ngc b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m65.ngc new file mode 100644 index 0000000..55ba469 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m65.ngc @@ -0,0 +1,3 @@ +o sub +M65 P0 +o endsub diff --git a/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m67.ngc b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m67.ngc new file mode 100644 index 0000000..7d338e9 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m67.ngc @@ -0,0 +1,3 @@ +o sub +M67 E0 Q# +o endsub diff --git a/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m68.ngc b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m68.ngc new file mode 100644 index 0000000..0df45b4 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/io_output_m68.ngc @@ -0,0 +1,3 @@ +o sub +M68 E0 Q# +o endsub diff --git a/wasm-port/vendor/linuxcnc/tests/remap/remap-io/test-ngc.ini b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/test-ngc.ini new file mode 100644 index 0000000..4ece72c --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/test-ngc.ini @@ -0,0 +1,129 @@ +# This config file was created 2017-05-10 09:59:22.679734 by the update_ini script +# The original config files may be found in the /home/jepler/src/linuxcnc/master/tests/remap/remap-io/test-ngc.old directory + +[EMC] +# The version string for this INI file. +VERSION = 1.1 + +DEBUG = 0x0 + +[DISPLAY] +DISPLAY = ./test-ui.py + +[FILTER] +#No Content + +[RS274NGC] +PARAMETER_FILE = sim.var +SUBROUTINE_PATH = . +REMAP= M62 modalgroup=5 argspec=P ngc=io_output_m62 +REMAP= M63 modalgroup=5 argspec=P ngc=io_output_m63 +REMAP= M64 modalgroup=5 argspec=P ngc=io_output_m64 +REMAP= M65 modalgroup=5 argspec=P ngc=io_output_m65 +REMAP= M66 modalgroup=5 argspec=pelq ngc=io_input_m66 +REMAP= M67 modalgroup=5 argspec=EQ ngc=io_output_m67 +REMAP= M68 modalgroup=5 argspec=EQ ngc=io_output_m68 + +[EMCMOT] +EMCMOT = motmod +COMM_TIMEOUT = 4.0 +BASE_PERIOD = 0 +SERVO_PERIOD = 1000000 + +[TASK] +TASK = milltask +CYCLE_TIME = 0.001 + +[HAL] +HALUI = halui +HALFILE = core_sim.hal + +[HALUI] +#No Content +[TRAJ] + +NO_FORCE_HOMING=1 +AXES = 3 +COORDINATES = X Y Z +HOME = 0 0 0 +LINEAR_UNITS = inch +ANGULAR_UNITS = degree +DEFAULT_LINEAR_VELOCITY = 1.2 +MAX_LINEAR_VELOCITY = 4 + +[EMCIO] +TOOL_TABLE = simpockets.tbl +TOOL_CHANGE_QUILL_UP = 1 +RANDOM_TOOLCHANGER = 0 + + + +[KINS] +KINEMATICS = trivkins +#This is a best-guess at the number of joints, it should be checked +JOINTS = 3 + +[AXIS_X] +MIN_LIMIT = -40.0 +MAX_LIMIT = 40.0 +MAX_VELOCITY = 4 +MAX_ACCELERATION = 1000.0 + +[JOINT_0] + +TYPE = LINEAR +HOME = 0.000 +MAX_VELOCITY = 4 +MAX_ACCELERATION = 1000.0 +BACKLASH = 0.000 +INPUT_SCALE = 4000 +OUTPUT_SCALE = 1.000 +MIN_LIMIT = -40.0 +MAX_LIMIT = 40.0 +FERROR = 0.050 +MIN_FERROR = 0.010 + +[AXIS_Y] +MIN_LIMIT = -40.0 +MAX_LIMIT = 40.0 +MAX_VELOCITY = 4 +MAX_ACCELERATION = 1000.0 + +[JOINT_1] + +TYPE = LINEAR +HOME = 0.000 +MAX_VELOCITY = 4 +MAX_ACCELERATION = 1000.0 +BACKLASH = 0.000 +INPUT_SCALE = 4000 +OUTPUT_SCALE = 1.000 +MIN_LIMIT = -40.0 +MAX_LIMIT = 40.0 +FERROR = 0.050 +MIN_FERROR = 0.010 + +[AXIS_Z] +MIN_LIMIT = -40.0 +MAX_LIMIT = 40.0 +MAX_VELOCITY = 4 +MAX_ACCELERATION = 1000.0 + +[JOINT_2] + +TYPE = LINEAR +HOME = 0.0 +MAX_VELOCITY = 4 +MAX_ACCELERATION = 1000.0 +BACKLASH = 0.000 +INPUT_SCALE = 4000 +OUTPUT_SCALE = 1.000 +MIN_LIMIT = -40.0 +MAX_LIMIT = 40.0 +FERROR = 0.050 +MIN_FERROR = 0.010 + +[PYTHON] + +TOPLEVEL= toplevel.py +PATH_PREPEND= . diff --git a/wasm-port/vendor/linuxcnc/tests/remap/remap-io/test.sh b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/test.sh new file mode 100755 index 0000000..30e17ad --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/remap-io/test.sh @@ -0,0 +1,13 @@ +#!/bin/bash -e +export PYTHONUNBUFFERED=1 +do_test() { + INI="$1" + linuxcnc -r "$INI" | grep -i m6 +} + +echo "********** Testing python remaps" +do_test test-py.ini +echo +echo "********** Testing ngc remaps" +do_test test-ngc.ini + diff --git a/wasm-port/vendor/linuxcnc/tests/remap/sequencing/README b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/README new file mode 100644 index 0000000..6923787 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/README @@ -0,0 +1,4 @@ +Exercise remap sequencing of one G and 4 M-codes per line (MAX_EMS limit) + +regardless of ordering of codes on the line the execution order +must reflect an ascending sequence diff --git a/wasm-port/vendor/linuxcnc/tests/remap/sequencing/expected b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/expected new file mode 100644 index 0000000..5a51c9a --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/expected @@ -0,0 +1,1214 @@ + 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(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=5.000000") + N..... MESSAGE(" seq=6.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + N..... MESSAGE(" seq=1.000000") + N..... MESSAGE(" seq=7.000000") + N..... MESSAGE(" seq=8.000000") + N..... MESSAGE(" seq=9.000000") + N..... MESSAGE(" seq=10.000000 - reset to 1") + 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() diff --git a/wasm-port/vendor/linuxcnc/tests/remap/sequencing/permute.py b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/permute.py new file mode 100644 index 0000000..27f1f94 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/permute.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# This is a component of LinuxCNC +# Copyright 2011 Michael Haberler +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +#http://stackoverflow.com/questions/361/generate-list-of-all-possible-permutations-of-a-string +def nextPermutation(perm): + k0 = None + for i in range(len(perm)-1): + if perm[i] sub +o100 if [[#<_seq>] GT 10] + (debug,G88.1 sequencing error - seq=#<_seq>) +o100 else + (debug, seq=#<_seq> - reset to 1) +o100 endif +#<_seq> = 1 + +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm405.ngc b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm405.ngc new file mode 100644 index 0000000..8a3a111 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm405.ngc @@ -0,0 +1,10 @@ +o sub +o100 if [[#<_seq>] GT 5] + (debug,M405 sequencing error - seq=#<_seq>) +o100 else + (debug, seq=#<_seq>) +o100 endif +#<_seq> = 5 +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm406.ngc b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm406.ngc new file mode 100644 index 0000000..6ee6c82 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm406.ngc @@ -0,0 +1,10 @@ +o sub +o100 if [[#<_seq>] GT 6] + (debug,M406 sequencing error - seq=#<_seq>) +o100 else + (debug, seq=#<_seq>) +o100 endif +#<_seq> = 6 +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm407.ngc b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm407.ngc new file mode 100644 index 0000000..e6bc8b5 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm407.ngc @@ -0,0 +1,10 @@ +o sub +o100 if [[#<_seq>] GT 7] + (debug,M407 sequencing error - seq=#<_seq>) +o100 else + (debug, seq=#<_seq>) +o100 endif +#<_seq> = 7 +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm408.ngc b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm408.ngc new file mode 100644 index 0000000..a6a332d --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm408.ngc @@ -0,0 +1,10 @@ +o sub +o100 if [[#<_seq>] GT 8] + (debug,M408 sequencing error - seq=#<_seq>) +o100 else + (debug, seq=#<_seq>) +o100 endif +#<_seq> = 8 +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm409.ngc b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm409.ngc new file mode 100644 index 0000000..f4386ce --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm409.ngc @@ -0,0 +1,10 @@ +o sub +o100 if [[#<_seq>] GT 9] + (debug,M409 sequencing error - seq=#<_seq>) +o100 else + (debug, seq=#<_seq>) +o100 endif +#<_seq> = 9 +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm410.ngc b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm410.ngc new file mode 100644 index 0000000..a239707 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/rm410.ngc @@ -0,0 +1,10 @@ +o sub +o100 if [[#<_seq>] GT 10] + (debug,M410 sequencing error - seq=#<_seq>) +o100 else + (debug, seq=#<_seq>) +o100 endif +#<_seq> = 10 +o endsub +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/sequencing/test.ini b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/test.ini new file mode 100644 index 0000000..669ce00 --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/test.ini @@ -0,0 +1,16 @@ +[EMC] +DEBUG=0 +LOG_LEVEL=0 + +[RS274NGC] +SUBROUTINE_PATH = . + +REMAP=G88.1 ngc=rg881 + +# one M-code from each modal group +REMAP=M405 modalgroup=5 ngc=rm405 +REMAP=M406 modalgroup=6 ngc=rm406 +REMAP=M407 modalgroup=7 ngc=rm407 +REMAP=M408 modalgroup=8 ngc=rm408 +REMAP=M409 modalgroup=9 ngc=rm409 +REMAP=M410 ngc=rm410 diff --git a/wasm-port/vendor/linuxcnc/tests/remap/sequencing/test.ngc b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/test.ngc new file mode 100644 index 0000000..d56e9cb --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/test.ngc @@ -0,0 +1,245 @@ +; one G, 4 M-codes per line +#<_seq> = 1 +g88.1x1 m405 m406 m407 m408 +g88.1x1 m405 m406 m408 m407 +g88.1x1 m405 m407 m406 m408 +g88.1x1 m405 m407 m408 m406 +g88.1x1 m405 m408 m406 m407 +g88.1x1 m405 m408 m407 m406 +g88.1x1 m406 m405 m407 m408 +g88.1x1 m406 m405 m408 m407 +g88.1x1 m406 m407 m405 m408 +g88.1x1 m406 m407 m408 m405 +g88.1x1 m406 m408 m405 m407 +g88.1x1 m406 m408 m407 m405 +g88.1x1 m407 m405 m406 m408 +g88.1x1 m407 m405 m408 m406 +g88.1x1 m407 m406 m405 m408 +g88.1x1 m407 m406 m408 m405 +g88.1x1 m407 m408 m405 m406 +g88.1x1 m407 m408 m406 m405 +g88.1x1 m408 m405 m406 m407 +g88.1x1 m408 m405 m407 m406 +g88.1x1 m408 m406 m405 m407 +g88.1x1 m408 m406 m407 m405 +g88.1x1 m408 m407 m405 m406 +g88.1x1 m408 m407 m406 m405 +m405 g88.1x1 m406 m407 m408 +m405 g88.1x1 m406 m408 m407 +m405 g88.1x1 m407 m406 m408 +m405 g88.1x1 m407 m408 m406 +m405 g88.1x1 m408 m406 m407 +m405 g88.1x1 m408 m407 m406 +m405 m406 g88.1x1 m407 m408 +m405 m406 g88.1x1 m408 m407 +m405 m406 m407 g88.1x1 m408 +m405 m406 m407 m408 g88.1x1 +m405 m406 m408 g88.1x1 m407 +m405 m406 m408 m407 g88.1x1 +m405 m407 g88.1x1 m406 m408 +m405 m407 g88.1x1 m408 m406 +m405 m407 m406 g88.1x1 m408 +m405 m407 m406 m408 g88.1x1 +m405 m407 m408 g88.1x1 m406 +m405 m407 m408 m406 g88.1x1 +m405 m408 g88.1x1 m406 m407 +m405 m408 g88.1x1 m407 m406 +m405 m408 m406 g88.1x1 m407 +m405 m408 m406 m407 g88.1x1 +m405 m408 m407 g88.1x1 m406 +m405 m408 m407 m406 g88.1x1 +m406 g88.1x1 m405 m407 m408 +m406 g88.1x1 m405 m408 m407 +m406 g88.1x1 m407 m405 m408 +m406 g88.1x1 m407 m408 m405 +m406 g88.1x1 m408 m405 m407 +m406 g88.1x1 m408 m407 m405 +m406 m405 g88.1x1 m407 m408 +m406 m405 g88.1x1 m408 m407 +m406 m405 m407 g88.1x1 m408 +m406 m405 m407 m408 g88.1x1 +m406 m405 m408 g88.1x1 m407 +m406 m405 m408 m407 g88.1x1 +m406 m407 g88.1x1 m405 m408 +m406 m407 g88.1x1 m408 m405 +m406 m407 m405 g88.1x1 m408 +m406 m407 m405 m408 g88.1x1 +m406 m407 m408 g88.1x1 m405 +m406 m407 m408 m405 g88.1x1 +m406 m408 g88.1x1 m405 m407 +m406 m408 g88.1x1 m407 m405 +m406 m408 m405 g88.1x1 m407 +m406 m408 m405 m407 g88.1x1 +m406 m408 m407 g88.1x1 m405 +m406 m408 m407 m405 g88.1x1 +m407 g88.1x1 m405 m406 m408 +m407 g88.1x1 m405 m408 m406 +m407 g88.1x1 m406 m405 m408 +m407 g88.1x1 m406 m408 m405 +m407 g88.1x1 m408 m405 m406 +m407 g88.1x1 m408 m406 m405 +m407 m405 g88.1x1 m406 m408 +m407 m405 g88.1x1 m408 m406 +m407 m405 m406 g88.1x1 m408 +m407 m405 m406 m408 g88.1x1 +m407 m405 m408 g88.1x1 m406 +m407 m405 m408 m406 g88.1x1 +m407 m406 g88.1x1 m405 m408 +m407 m406 g88.1x1 m408 m405 +m407 m406 m405 g88.1x1 m408 +m407 m406 m405 m408 g88.1x1 +m407 m406 m408 g88.1x1 m405 +m407 m406 m408 m405 g88.1x1 +m407 m408 g88.1x1 m405 m406 +m407 m408 g88.1x1 m406 m405 +m407 m408 m405 g88.1x1 m406 +m407 m408 m405 m406 g88.1x1 +m407 m408 m406 g88.1x1 m405 +m407 m408 m406 m405 g88.1x1 +m408 g88.1x1 m405 m406 m407 +m408 g88.1x1 m405 m407 m406 +m408 g88.1x1 m406 m405 m407 +m408 g88.1x1 m406 m407 m405 +m408 g88.1x1 m407 m405 m406 +m408 g88.1x1 m407 m406 m405 +m408 m405 g88.1x1 m406 m407 +m408 m405 g88.1x1 m407 m406 +m408 m405 m406 g88.1x1 m407 +m408 m405 m406 m407 g88.1x1 +m408 m405 m407 g88.1x1 m406 +m408 m405 m407 m406 g88.1x1 +m408 m406 g88.1x1 m405 m407 +m408 m406 g88.1x1 m407 m405 +m408 m406 m405 g88.1x1 m407 +m408 m406 m405 m407 g88.1x1 +m408 m406 m407 g88.1x1 m405 +m408 m406 m407 m405 g88.1x1 +m408 m407 g88.1x1 m405 m406 +m408 m407 g88.1x1 m406 m405 +m408 m407 m405 g88.1x1 m406 +m408 m407 m405 m406 g88.1x1 +m408 m407 m406 g88.1x1 m405 +m408 m407 m406 m405 g88.1x1 +g88.1x1 m407 m408 m409 m410 +g88.1x1 m407 m408 m410 m409 +g88.1x1 m407 m409 m408 m410 +g88.1x1 m407 m409 m410 m408 +g88.1x1 m407 m410 m408 m409 +g88.1x1 m407 m410 m409 m408 +g88.1x1 m408 m407 m409 m410 +g88.1x1 m408 m407 m410 m409 +g88.1x1 m408 m409 m407 m410 +g88.1x1 m408 m409 m410 m407 +g88.1x1 m408 m410 m407 m409 +g88.1x1 m408 m410 m409 m407 +g88.1x1 m409 m407 m408 m410 +g88.1x1 m409 m407 m410 m408 +g88.1x1 m409 m408 m407 m410 +g88.1x1 m409 m408 m410 m407 +g88.1x1 m409 m410 m407 m408 +g88.1x1 m409 m410 m408 m407 +g88.1x1 m410 m407 m408 m409 +g88.1x1 m410 m407 m409 m408 +g88.1x1 m410 m408 m407 m409 +g88.1x1 m410 m408 m409 m407 +g88.1x1 m410 m409 m407 m408 +g88.1x1 m410 m409 m408 m407 +m407 g88.1x1 m408 m409 m410 +m407 g88.1x1 m408 m410 m409 +m407 g88.1x1 m409 m408 m410 +m407 g88.1x1 m409 m410 m408 +m407 g88.1x1 m410 m408 m409 +m407 g88.1x1 m410 m409 m408 +m407 m408 g88.1x1 m409 m410 +m407 m408 g88.1x1 m410 m409 +m407 m408 m409 g88.1x1 m410 +m407 m408 m409 m410 g88.1x1 +m407 m408 m410 g88.1x1 m409 +m407 m408 m410 m409 g88.1x1 +m407 m409 g88.1x1 m408 m410 +m407 m409 g88.1x1 m410 m408 +m407 m409 m408 g88.1x1 m410 +m407 m409 m408 m410 g88.1x1 +m407 m409 m410 g88.1x1 m408 +m407 m409 m410 m408 g88.1x1 +m407 m410 g88.1x1 m408 m409 +m407 m410 g88.1x1 m409 m408 +m407 m410 m408 g88.1x1 m409 +m407 m410 m408 m409 g88.1x1 +m407 m410 m409 g88.1x1 m408 +m407 m410 m409 m408 g88.1x1 +m408 g88.1x1 m407 m409 m410 +m408 g88.1x1 m407 m410 m409 +m408 g88.1x1 m409 m407 m410 +m408 g88.1x1 m409 m410 m407 +m408 g88.1x1 m410 m407 m409 +m408 g88.1x1 m410 m409 m407 +m408 m407 g88.1x1 m409 m410 +m408 m407 g88.1x1 m410 m409 +m408 m407 m409 g88.1x1 m410 +m408 m407 m409 m410 g88.1x1 +m408 m407 m410 g88.1x1 m409 +m408 m407 m410 m409 g88.1x1 +m408 m409 g88.1x1 m407 m410 +m408 m409 g88.1x1 m410 m407 +m408 m409 m407 g88.1x1 m410 +m408 m409 m407 m410 g88.1x1 +m408 m409 m410 g88.1x1 m407 +m408 m409 m410 m407 g88.1x1 +m408 m410 g88.1x1 m407 m409 +m408 m410 g88.1x1 m409 m407 +m408 m410 m407 g88.1x1 m409 +m408 m410 m407 m409 g88.1x1 +m408 m410 m409 g88.1x1 m407 +m408 m410 m409 m407 g88.1x1 +m409 g88.1x1 m407 m408 m410 +m409 g88.1x1 m407 m410 m408 +m409 g88.1x1 m408 m407 m410 +m409 g88.1x1 m408 m410 m407 +m409 g88.1x1 m410 m407 m408 +m409 g88.1x1 m410 m408 m407 +m409 m407 g88.1x1 m408 m410 +m409 m407 g88.1x1 m410 m408 +m409 m407 m408 g88.1x1 m410 +m409 m407 m408 m410 g88.1x1 +m409 m407 m410 g88.1x1 m408 +m409 m407 m410 m408 g88.1x1 +m409 m408 g88.1x1 m407 m410 +m409 m408 g88.1x1 m410 m407 +m409 m408 m407 g88.1x1 m410 +m409 m408 m407 m410 g88.1x1 +m409 m408 m410 g88.1x1 m407 +m409 m408 m410 m407 g88.1x1 +m409 m410 g88.1x1 m407 m408 +m409 m410 g88.1x1 m408 m407 +m409 m410 m407 g88.1x1 m408 +m409 m410 m407 m408 g88.1x1 +m409 m410 m408 g88.1x1 m407 +m409 m410 m408 m407 g88.1x1 +m410 g88.1x1 m407 m408 m409 +m410 g88.1x1 m407 m409 m408 +m410 g88.1x1 m408 m407 m409 +m410 g88.1x1 m408 m409 m407 +m410 g88.1x1 m409 m407 m408 +m410 g88.1x1 m409 m408 m407 +m410 m407 g88.1x1 m408 m409 +m410 m407 g88.1x1 m409 m408 +m410 m407 m408 g88.1x1 m409 +m410 m407 m408 m409 g88.1x1 +m410 m407 m409 g88.1x1 m408 +m410 m407 m409 m408 g88.1x1 +m410 m408 g88.1x1 m407 m409 +m410 m408 g88.1x1 m409 m407 +m410 m408 m407 g88.1x1 m409 +m410 m408 m407 m409 g88.1x1 +m410 m408 m409 g88.1x1 m407 +m410 m408 m409 m407 g88.1x1 +m410 m409 g88.1x1 m407 m408 +m410 m409 g88.1x1 m408 m407 +m410 m409 m407 g88.1x1 m408 +m410 m409 m407 m408 g88.1x1 +m410 m409 m408 g88.1x1 m407 +m410 m409 m408 m407 g88.1x1 + +m2 +% diff --git a/wasm-port/vendor/linuxcnc/tests/remap/sequencing/test.sh b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/test.sh new file mode 100755 index 0000000..99269de --- /dev/null +++ b/wasm-port/vendor/linuxcnc/tests/remap/sequencing/test.sh @@ -0,0 +1,4 @@ +#!/bin/bash +export INI_FILE_NAME=test.ini +rs274 -i "$INI_FILE_NAME" -g test.ngc | awk '{$1=""; print}' +exit "${PIPESTATUS[0]}"