Skip to content

tcl: restore #INCLUDE handling in parse_ini to fix check_config.tcl after 2f57090#3938

Open
is-primary-dev wants to merge 1 commit intoLinuxCNC:masterfrom
is-primary-dev:fix-tcl-parse-ini-include
Open

tcl: restore #INCLUDE handling in parse_ini to fix check_config.tcl after 2f57090#3938
is-primary-dev wants to merge 1 commit intoLinuxCNC:masterfrom
is-primary-dev:fix-tcl-parse-ini-include

Conversation

@is-primary-dev
Copy link
Copy Markdown

Summary

Upstream commit 2f57090 ("ini: Implement a new ini-file parser and adapt the code to use it") added native #INCLUDE support to the new C++ parser in src/emc/ini/inifile.cc and removed the 53-line handle_includes() shell preprocessor from scripts/linuxcnc.in, because the new parser handles #INCLUDE natively for the main launcher flow.

However, lib/hallib/check_config.tcl (called from scripts/linuxcnc during startup to validate the INI) uses the pure-Tcl parse_ini proc in tcl/linuxcnc.tcl, which has no #INCLUDE support. It relied on the shell preprocessor expanding the file before parse_ini ever saw it. After 2f57090, any INI file using #INCLUDE directives fails check_config.tcl's mandatory-items pre-flight check.

Observable symptom

On current upstream master, the shipped sim demo fails validation:

$ tclsh8.6 lib/hallib/check_config.tcl \
      configs/sim/axis/ini_with_includes/includes_demo.ini

check_config:
  Missing [KINS]KINEMATICS=
  Missing [KINS]JOINTS=

check_config validation failed

includes_demo.ini's master file has no [KINS] section — all sections come from .inc files via #INCLUDE directives that the pure-Tcl parser ignores.

Fix

Extend parse_ini in tcl/linuxcnc.tcl.in to recognize #INCLUDE <filename> lines, resolve relative filenames against the including file's directory, and parse the referenced file recursively. Matches the semantics of IniFileContent::parseLine()'s #INCLUDE handling in inifile.cc. Errors during recursive parse (missing file, unreadable) are logged to stderr and the outer parse continues, matching the C parser's non-fatal behavior on bad includes.

Also switches the section-variable upvar from frame 1 (caller) to frame #0 (absolute global), so variables land in the global scope regardless of recursion depth. Behavior-preserving for existing callers (check_config.tcl, twopass.tcl::tp::pass1); only matters for the new recursive calls.

Testing

Verified on upstream master with the same repro above — after the patch, the demo validates cleanly (only the two intentional error-demo directives at the end of includes_demo.ini surface as stderr warnings, matching the #INCLUDE nosuchfile error example the demo was designed to show).

Upstream commit 2f57090 ("ini: Implement a new ini-file parser and
adapt the code to use it") added native #INCLUDE support to the new C++
parser in src/emc/ini/inifile.cc and removed the 53-line
handle_includes() shell preprocessor from scripts/linuxcnc.in, because
the new parser made the preprocessor redundant for the main launcher
flow.

However, lib/hallib/check_config.tcl uses the pure-Tcl parse_ini proc
in tcl/linuxcnc.tcl, which has no #INCLUDE support. It relied on the
shell preprocessor expanding the file before parse_ini ever saw it.
Removing the preprocessor broke check_config.tcl for any INI file using
#INCLUDE directives — including the shipped sim demo at
configs/sim/axis/ini_with_includes/includes_demo.ini, which fails on
current upstream master with:

  $ tclsh8.6 lib/hallib/check_config.tcl \
        configs/sim/axis/ini_with_includes/includes_demo.ini

  check_config:
    Missing [KINS]KINEMATICS=
    Missing [KINS]JOINTS=

  check_config validation failed

Extend parse_ini to recognize '#INCLUDE <filename>' lines and parse the
referenced file recursively, resolving relative filenames against the
including file's directory. This matches the semantics of inifile.cc's
IniFileContent::parseLine() #INCLUDE handling. Errors during recursive
parse (missing file, unreadable, etc.) are logged to stderr and the
outer parse continues — matching the C parser's non-fatal behavior on
bad includes so that mandatory-items checks can still see whatever was
loaded up to the point of failure.

The recursive call uses `uplevel 1` so the included file's sections
land in the same scope as the top-level file's sections. For existing
callers (check_config.tcl from file scope, twopass.tcl::tp::pass1 from
a proc), this preserves the historical single-file upvar 1 semantics
at every recursion depth — the recursive call runs as if it had been
made directly from the original caller, so upvar 1 inside the recursive
parse_ini walks back to the same frame as the top-level call.

After this change, check_config.tcl accepts includes_demo.ini cleanly
(the file has two intentional error-demo directives at the end which
now surface as stderr warnings but no longer abort the check).
@BsAtHome
Copy link
Copy Markdown
Contributor

The TCL ini-parser should be replaced and code should be rewritten in python to use the python ini-file interface that uses the new C++ ini-file parser. The TCL version has more problems like not performing proper string parsing and lacks type checks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants