diff --git a/docs/linuxcnc-porting.md b/docs/linuxcnc-porting.md index a199928..1a1b3f8 100644 --- a/docs/linuxcnc-porting.md +++ b/docs/linuxcnc-porting.md @@ -211,7 +211,7 @@ This matrix tracks LinuxCNC feature coverage for the web/WASM simulator. A featu | Coordinate offset Canon events `G10 L2`, `G10 L20`, `G10 P0 active-system targeting`, `G54`-`G59.3` selection, `G52`, `G92/G92.1/G92.2/G92.3` | covered through LinuxCNC native/source backends, including all nine G5X indices | `tests/gcode/linuxcnc_coordinate_offsets.ngc`, `tests/gcode/linuxcnc_coordinate_l20.ngc`, `tests/gcode/linuxcnc_coordinate_p0.ngc`, `tests/gcode/linuxcnc_coordinate_select_all.ngc`, `tests/gcode/linuxcnc_g92_restore.ngc`, `tests/gcode/linuxcnc_g52_offset.ngc` | | Cutter compensation | covered for tool-table `G41/G42 D...` and explicit-radius `G41.1/G42.1/G40` through LinuxCNC native/source backends | `tests/gcode/linuxcnc_cutter_comp.ngc` | | Probe moves `G38.2/G38.3/G38.4/G38.5` | covered as distinct probe events with LinuxCNC `probe_type` preserved through smoke, native, and source-linked paths | `tests/gcode/linuxcnc_probe_no_error.ngc` | -| O-word subroutines, calls, and control flow | covered for numeric and named `O... sub/call/return/endsub` plus `if`/`elseif`/`else`, `while`, `repeat`, `do`/`while`, `break`, and `continue` through LinuxCNC file mode; source-linked read/execution errors cover malformed O-word commands, missing control-expression brackets, duplicate/unmatched labels, out-of-context `return`/`endsub`, too many call parameters, and Fanuc-style `M98` missing `P`; smoke parser also covers named `O` sub/call/return/endsub and loop-control forms | `tests/gcode/smoke_oword_subprogram.ngc`, `tests/gcode/linuxcnc_named_oword_subprogram.ngc`, `tests/gcode/linuxcnc_oword_control_flow.ngc`, `tests/gcode/linuxcnc_oword_unknown_command_error.ngc`, `tests/gcode/linuxcnc_oword_unexpected_trailing_item_error.ngc`, `tests/gcode/linuxcnc_oword_if_missing_bracket_error.ngc`, `tests/gcode/linuxcnc_oword_elseif_missing_bracket_error.ngc`, `tests/gcode/linuxcnc_oword_while_missing_bracket_error.ngc`, `tests/gcode/linuxcnc_oword_repeat_missing_bracket_error.ngc`, `tests/gcode/linuxcnc_oword_too_many_call_parameters_error.ngc`, `tests/gcode/linuxcnc_oword_endsub_without_sub_error.ngc`, `tests/gcode/linuxcnc_oword_return_without_sub_error.ngc`, `tests/gcode/linuxcnc_oword_duplicate_if_label_error.ngc`, `tests/gcode/linuxcnc_oword_elseif_undefined_label_error.ngc`, `tests/gcode/linuxcnc_oword_break_undefined_label_error.ngc`, `tests/gcode/linuxcnc_oword_endrepeat_no_matching_repeat_error.ngc`, `tests/gcode/linuxcnc_m98_missing_p_word_error.ngc` | +| O-word subroutines, calls, and control flow | covered for numeric and named `O... sub/call/return/endsub` plus `if`/`elseif`/`else`, `while`, `repeat`, `do`/`while`, `break`, and `continue` through LinuxCNC file mode; source-linked read/execution errors cover malformed O-word commands, missing control-expression brackets, duplicate/undefined/unmatched labels, out-of-context `return`/`endsub`, wrong subroutine close style, too many call parameters, and Fanuc-style `M98` missing `P`; smoke parser also covers named `O` sub/call/return/endsub and loop-control forms | `tests/gcode/smoke_oword_subprogram.ngc`, `tests/gcode/linuxcnc_named_oword_subprogram.ngc`, `tests/gcode/linuxcnc_oword_control_flow.ngc`, `tests/gcode/linuxcnc_oword_unknown_command_error.ngc`, `tests/gcode/linuxcnc_oword_unexpected_trailing_item_error.ngc`, `tests/gcode/linuxcnc_oword_if_missing_bracket_error.ngc`, `tests/gcode/linuxcnc_oword_elseif_missing_bracket_error.ngc`, `tests/gcode/linuxcnc_oword_while_missing_bracket_error.ngc`, `tests/gcode/linuxcnc_oword_repeat_missing_bracket_error.ngc`, `tests/gcode/linuxcnc_oword_too_many_call_parameters_error.ngc`, `tests/gcode/linuxcnc_oword_endsub_without_sub_error.ngc`, `tests/gcode/linuxcnc_oword_return_without_sub_error.ngc`, `tests/gcode/linuxcnc_oword_duplicate_if_label_error.ngc`, `tests/gcode/linuxcnc_oword_elseif_undefined_label_error.ngc`, `tests/gcode/linuxcnc_oword_else_undefined_label_error.ngc`, `tests/gcode/linuxcnc_oword_endif_undefined_label_error.ngc`, `tests/gcode/linuxcnc_oword_break_undefined_label_error.ngc`, `tests/gcode/linuxcnc_oword_continue_undefined_label_error.ngc`, `tests/gcode/linuxcnc_oword_endwhile_undefined_label_error.ngc`, `tests/gcode/linuxcnc_oword_elseif_no_matching_if_error.ngc`, `tests/gcode/linuxcnc_oword_break_no_matching_loop_error.ngc`, `tests/gcode/linuxcnc_oword_continue_no_matching_loop_error.ngc`, `tests/gcode/linuxcnc_oword_endrepeat_no_matching_repeat_error.ngc`, `tests/gcode/linuxcnc_oword_endif_no_matching_if_error.ngc`, `tests/gcode/linuxcnc_oword_endwhile_no_matching_while_error.ngc`, `tests/gcode/linuxcnc_oword_fanuc_requires_m99_error.ngc`, `tests/gcode/linuxcnc_oword_sub_requires_endsub_error.ngc`, `tests/gcode/linuxcnc_m98_missing_p_word_error.ngc` | | Parameter expressions and operators | covered for parameter references, source-linked `mod`, `**`, logical, and relational operator precedence, plus LinuxCNC parameter-setting syntax, parameter index validation, named-parameter termination, real-number parsing, divide-by-zero, negative sqrt/power, infinity rejection, malformed `ATAN[]/[]`, unary operation syntax, `read_operation_unary()` unknown-word branches, `read_operation()` binary-operation prefix, unknown operation, and unclosed-expression error paths from `interp_read.cc`/`interp_execute.cc` | `tests/gcode/linuxcnc_parameter_expression_assignment.ngc`, `tests/gcode/linuxcnc_parameter_missing_equal_error.ngc`, `tests/gcode/linuxcnc_parameter_missing_value_error.ngc`, `tests/gcode/linuxcnc_parameter_number_out_of_range_error.ngc`, `tests/gcode/linuxcnc_parameter_reference_out_of_range_error.ngc`, `tests/gcode/linuxcnc_non_integer_parameter_index_error.ngc`, `tests/gcode/linuxcnc_named_parameter_not_terminated_error.ngc`, `tests/gcode/linuxcnc_no_real_value_error.ngc`, `tests/gcode/linuxcnc_bad_number_format_error.ngc`, `tests/gcode/linuxcnc_expression_operators.ngc`, `tests/gcode/linuxcnc_negative_sqrt_error.ngc`, `tests/gcode/linuxcnc_divide_by_zero_error.ngc`, `tests/gcode/linuxcnc_negative_power_error.ngc`, `tests/gcode/linuxcnc_infinite_expression_error.ngc`, `tests/gcode/linuxcnc_atan_missing_slash_error.ngc`, `tests/gcode/linuxcnc_atan_missing_bracket_error.ngc`, `tests/gcode/linuxcnc_unary_missing_bracket_error.ngc`, `tests/gcode/linuxcnc_unary_unknown_word_error.ngc`, `tests/gcode/linuxcnc_unary_unknown_c_word_error.ngc`, `tests/gcode/linuxcnc_unary_unknown_e_word_error.ngc`, `tests/gcode/linuxcnc_unary_unknown_f_word_error.ngc`, `tests/gcode/linuxcnc_unary_unknown_l_word_error.ngc`, `tests/gcode/linuxcnc_unary_unknown_r_word_error.ngc`, `tests/gcode/linuxcnc_unary_unknown_s_word_error.ngc`, `tests/gcode/linuxcnc_unary_unknown_t_word_error.ngc`, `tests/gcode/linuxcnc_unary_unknown_default_word_error.ngc`, `tests/gcode/linuxcnc_binary_unknown_a_operation_error.ngc`, `tests/gcode/linuxcnc_binary_unknown_e_operation_error.ngc`, `tests/gcode/linuxcnc_binary_unknown_g_operation_error.ngc`, `tests/gcode/linuxcnc_binary_unknown_l_operation_error.ngc`, `tests/gcode/linuxcnc_binary_unknown_m_operation_error.ngc`, `tests/gcode/linuxcnc_binary_unknown_n_operation_error.ngc`, `tests/gcode/linuxcnc_binary_unknown_o_operation_error.ngc`, `tests/gcode/linuxcnc_binary_unknown_x_operation_error.ngc`, `tests/gcode/linuxcnc_binary_unknown_operation_error.ngc`, `tests/gcode/linuxcnc_unclosed_expression_error.ngc` | | Word reader validation | source-linked LinuxCNC reader errors covered for negative `F/G/H/L/M/S/T` values and repeated `A/B/C/D/E/F/H/I/J/K/L/P/Q/R/S/T/U/V/W/X/Y/Z` words from `interp_read.cc` | `tests/gcode/linuxcnc_negative_f_word_error.ngc`, `tests/gcode/linuxcnc_negative_g_code_error.ngc`, `tests/gcode/linuxcnc_negative_h_word_error.ngc`, `tests/gcode/linuxcnc_negative_l_word_error.ngc`, `tests/gcode/linuxcnc_negative_m_code_error.ngc`, `tests/gcode/linuxcnc_negative_s_word_error.ngc`, `tests/gcode/linuxcnc_negative_t_word_error.ngc`, `tests/gcode/linuxcnc_multiple_a_words_error.ngc`, `tests/gcode/linuxcnc_multiple_b_words_error.ngc`, `tests/gcode/linuxcnc_multiple_c_words_error.ngc`, `tests/gcode/linuxcnc_multiple_d_words_error.ngc`, `tests/gcode/linuxcnc_multiple_e_words_error.ngc`, `tests/gcode/linuxcnc_multiple_f_words_error.ngc`, `tests/gcode/linuxcnc_multiple_h_words_error.ngc`, `tests/gcode/linuxcnc_multiple_i_words_error.ngc`, `tests/gcode/linuxcnc_multiple_j_words_error.ngc`, `tests/gcode/linuxcnc_multiple_k_words_error.ngc`, `tests/gcode/linuxcnc_multiple_l_words_error.ngc`, `tests/gcode/linuxcnc_multiple_p_words_error.ngc`, `tests/gcode/linuxcnc_multiple_q_words_error.ngc`, `tests/gcode/linuxcnc_multiple_r_words_error.ngc`, `tests/gcode/linuxcnc_multiple_s_words_error.ngc`, `tests/gcode/linuxcnc_multiple_t_words_error.ngc`, `tests/gcode/linuxcnc_multiple_u_words_error.ngc`, `tests/gcode/linuxcnc_multiple_v_words_error.ngc`, `tests/gcode/linuxcnc_multiple_w_words_error.ngc`, `tests/gcode/linuxcnc_multiple_x_words_error.ngc`, `tests/gcode/linuxcnc_multiple_y_words_error.ngc`, `tests/gcode/linuxcnc_multiple_z_words_error.ngc` | | G/M reader validation | source-linked LinuxCNC `read_g()`/`read_m()` errors covered for range checks, unknown code tables, and same-modal-group conflicts from `interp_read.cc` and `interp_array.cc` | `tests/gcode/linuxcnc_g_code_out_of_range_error.ngc`, `tests/gcode/linuxcnc_unknown_g_code_error.ngc`, `tests/gcode/linuxcnc_two_g_codes_same_modal_group_error.ngc`, `tests/gcode/linuxcnc_m_code_greater_199_error.ngc`, `tests/gcode/linuxcnc_unknown_m_code_error.ngc`, `tests/gcode/linuxcnc_two_m_codes_same_modal_group_error.ngc` | diff --git a/test-linuxcnc-source-link.sh b/test-linuxcnc-source-link.sh index 55a96f5..f21a405 100755 --- a/test-linuxcnc-source-link.sh +++ b/test-linuxcnc-source-link.sh @@ -901,8 +901,19 @@ oword_execution_error_cases=( "linuxcnc_oword_return_without_sub_error|not in a subroutine definition" "linuxcnc_oword_duplicate_if_label_error|duplicate O-word label" "linuxcnc_oword_elseif_undefined_label_error|undefined O-word label" + "linuxcnc_oword_else_undefined_label_error|undefined O-word label" + "linuxcnc_oword_endif_undefined_label_error|undefined O-word label" "linuxcnc_oword_break_undefined_label_error|undefined O-word label" + "linuxcnc_oword_continue_undefined_label_error|undefined O-word label" + "linuxcnc_oword_endwhile_undefined_label_error|undefined O-word label" + "linuxcnc_oword_elseif_no_matching_if_error|no matching 'if' label" + "linuxcnc_oword_break_no_matching_loop_error|no matching while/do label" + "linuxcnc_oword_continue_no_matching_loop_error|no matching while/do label" "linuxcnc_oword_endrepeat_no_matching_repeat_error|no matching label" + "linuxcnc_oword_endif_no_matching_if_error|no matching label" + "linuxcnc_oword_endwhile_no_matching_while_error|no matching label" + "linuxcnc_oword_fanuc_requires_m99_error|Fanuc 'O....' subroutine definition must end with 'M99'" + "linuxcnc_oword_sub_requires_endsub_error|'O.... endsub' or 'O.... return' must follow 'O.... sub'" ) for case in "${oword_execution_error_cases[@]}"; do fixture=${case%%|*} diff --git a/tests/gcode/linuxcnc_oword_break_no_matching_loop_error.ngc b/tests/gcode/linuxcnc_oword_break_no_matching_loop_error.ngc new file mode 100644 index 0000000..11e93ec --- /dev/null +++ b/tests/gcode/linuxcnc_oword_break_no_matching_loop_error.ngc @@ -0,0 +1,2 @@ +O100 if [1] +O100 break diff --git a/tests/gcode/linuxcnc_oword_continue_no_matching_loop_error.ngc b/tests/gcode/linuxcnc_oword_continue_no_matching_loop_error.ngc new file mode 100644 index 0000000..a155449 --- /dev/null +++ b/tests/gcode/linuxcnc_oword_continue_no_matching_loop_error.ngc @@ -0,0 +1,2 @@ +O100 if [1] +O100 continue diff --git a/tests/gcode/linuxcnc_oword_continue_undefined_label_error.ngc b/tests/gcode/linuxcnc_oword_continue_undefined_label_error.ngc new file mode 100644 index 0000000..e3eff5c --- /dev/null +++ b/tests/gcode/linuxcnc_oword_continue_undefined_label_error.ngc @@ -0,0 +1 @@ +O100 continue diff --git a/tests/gcode/linuxcnc_oword_else_undefined_label_error.ngc b/tests/gcode/linuxcnc_oword_else_undefined_label_error.ngc new file mode 100644 index 0000000..1f66399 --- /dev/null +++ b/tests/gcode/linuxcnc_oword_else_undefined_label_error.ngc @@ -0,0 +1 @@ +O100 else diff --git a/tests/gcode/linuxcnc_oword_elseif_no_matching_if_error.ngc b/tests/gcode/linuxcnc_oword_elseif_no_matching_if_error.ngc new file mode 100644 index 0000000..a64c2c9 --- /dev/null +++ b/tests/gcode/linuxcnc_oword_elseif_no_matching_if_error.ngc @@ -0,0 +1,2 @@ +O100 while [0] +O100 elseif [1] diff --git a/tests/gcode/linuxcnc_oword_endif_no_matching_if_error.ngc b/tests/gcode/linuxcnc_oword_endif_no_matching_if_error.ngc new file mode 100644 index 0000000..7784007 --- /dev/null +++ b/tests/gcode/linuxcnc_oword_endif_no_matching_if_error.ngc @@ -0,0 +1,2 @@ +O100 while [1] +O100 endif diff --git a/tests/gcode/linuxcnc_oword_endif_undefined_label_error.ngc b/tests/gcode/linuxcnc_oword_endif_undefined_label_error.ngc new file mode 100644 index 0000000..d88050b --- /dev/null +++ b/tests/gcode/linuxcnc_oword_endif_undefined_label_error.ngc @@ -0,0 +1 @@ +O100 endif diff --git a/tests/gcode/linuxcnc_oword_endwhile_no_matching_while_error.ngc b/tests/gcode/linuxcnc_oword_endwhile_no_matching_while_error.ngc new file mode 100644 index 0000000..31c5609 --- /dev/null +++ b/tests/gcode/linuxcnc_oword_endwhile_no_matching_while_error.ngc @@ -0,0 +1,2 @@ +O100 if [1] +O100 endwhile diff --git a/tests/gcode/linuxcnc_oword_endwhile_undefined_label_error.ngc b/tests/gcode/linuxcnc_oword_endwhile_undefined_label_error.ngc new file mode 100644 index 0000000..4948098 --- /dev/null +++ b/tests/gcode/linuxcnc_oword_endwhile_undefined_label_error.ngc @@ -0,0 +1 @@ +O100 endwhile diff --git a/tests/gcode/linuxcnc_oword_fanuc_requires_m99_error.ngc b/tests/gcode/linuxcnc_oword_fanuc_requires_m99_error.ngc new file mode 100644 index 0000000..6cd4569 --- /dev/null +++ b/tests/gcode/linuxcnc_oword_fanuc_requires_m99_error.ngc @@ -0,0 +1,4 @@ +M98 P100 +O100 +O100 endsub +M2 diff --git a/tests/gcode/linuxcnc_oword_sub_requires_endsub_error.ngc b/tests/gcode/linuxcnc_oword_sub_requires_endsub_error.ngc new file mode 100644 index 0000000..ed007ba --- /dev/null +++ b/tests/gcode/linuxcnc_oword_sub_requires_endsub_error.ngc @@ -0,0 +1,3 @@ +O100 call +O100 sub +M99