From 1b96a451758479a8aff79132712bfdfedcd061cd Mon Sep 17 00:00:00 2001 From: Bertho Stultiens Date: Thu, 16 Apr 2026 16:31:03 +0200 Subject: [PATCH] ini: Predigest the INI-file to support Tcl's parse_ini() handling --- .../axis/ini_with_includes/includes_demo.ini | 5 ++- scripts/linuxcnc.in | 37 +++++++++++++++++++ src/emc/usr_intf/halui.cc | 2 +- tcl/linuxcnc.tcl.in | 15 +++++++- tests/.gitignore | 1 + 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/configs/sim/axis/ini_with_includes/includes_demo.ini b/configs/sim/axis/ini_with_includes/includes_demo.ini index f1fc23fe1c6..c09bc4510dd 100644 --- a/configs/sim/axis/ini_with_includes/includes_demo.ini +++ b/configs/sim/axis/ini_with_includes/includes_demo.ini @@ -26,8 +26,9 @@ parm4 = 4 #INCLUDE axis_z.inc # error examples to show prints to stderr: -#INCLUDE -#INCLUDE nosuchfile +# Actual error is disabled because it just stops the program +# INCLUDE +# INCLUDE nosuchfile # final section [EXAMPLE_C] diff --git a/scripts/linuxcnc.in b/scripts/linuxcnc.in index cb6d0da9971..41472dfb483 100644 --- a/scripts/linuxcnc.in +++ b/scripts/linuxcnc.in @@ -356,6 +356,33 @@ if [ -z "$INIFILE" ] ; then exit 0 fi +# There is an INI-reader in the Tcl code (parse_ini in tcl/linuxcnc.tcl), but +# that cannot read or enforce the new INI-file format. The Tcl version does not +# handle includes, strings, continuations and comments. The includes were +# previously handled in here by generating a patched-up INI-file. We now do the +# same, but ensure the enforce the new format. We can generate a predigested +# version of the INI-file using the inivalue program. +# FIXME: This hack should be removed as soon as all the legacy Tcl code using +# INI values has been replaced with python code. +function make_ini_for_tcl() { + inifile="$1" + [ -r "$inifile" ] || { echo "E: Cannot read '$inifile'"; exit 1; } + inidir="$(dirname "$inifile")" + outfile="$inidir/$(basename "$inifile").expanded" + true >|"$outfile" || { echo "E: Could not create expanded inifile '$outfile' for Tcl"; exit 1; } + { + echo "#*** Source: $inifile" + echo "#*** Created: $(date)" + echo "#*** Autogenerated INI-file using linuxcnc for tcl/linuxcnc.tcl:parse_ini()" + echo + } >> "$outfile" + # For all sections, output the variables as parsed + for s in $(inivalue --sections "$inifile"); do + echo "[$s]" >> "$outfile" + inivalue --variables --content --sec "$s" "$inifile" >> "$outfile" + done +} + function split_app_items () { app_name=$1 shift @@ -402,6 +429,16 @@ function run_applications () { done } +# Test whether we have a valid INI-file that can be parsed without error. +# Running inivalue without section/variable filter should return the value of +# the first variable in the first section of the file. If that fails, there is +# a parse error in the file or it is empty. +inivalue "$INIFILE" > /dev/null || { echo "E: The INI-file contains errors that need to be fixed."; exit 1; } + +# The resulting INI-file for Tcl will be called "${INIFILE}.expanded" +# See comment above the function why this is necessary. +make_ini_for_tcl "$INIFILE" + # delete directories from path, save name only INI_NAME="${INIFILE##*/}" INI_DIR="${INIFILE%/*}" diff --git a/src/emc/usr_intf/halui.cc b/src/emc/usr_intf/halui.cc index c63164dc9f2..6e7c4621977 100644 --- a/src/emc/usr_intf/halui.cc +++ b/src/emc/usr_intf/halui.cc @@ -1472,7 +1472,7 @@ static int iniLoad(const char *filename) } } - if (!inifile.isSet("HOME_SEQUENCE", "JOINT_0")) { + if (inifile.isSet("HOME_SEQUENCE", "JOINT_0")) { have_home_all = 1; } diff --git a/tcl/linuxcnc.tcl.in b/tcl/linuxcnc.tcl.in index 9bc498d0975..e10e43ad31e 100644 --- a/tcl/linuxcnc.tcl.in +++ b/tcl/linuxcnc.tcl.in @@ -134,10 +134,23 @@ proc linuxcnc::standard_fixed_font {} { list [standard_fixed_font_family] [standard_font_size] } +# +# FIXME: +# This parse_ini() code should be removed. It is inadequate for the new +# INI-file parser and requires preprocessing. Either it needs to be mapped to +# the new C++ parser or all the Tcl code depending on INI-file entries need to +# be ported to python. +# proc parse_ini {filename} { # create associative arrays for all ini file sections # like: ::EMC(VERSION), ::KINS(JOINTS), ... etc - set f [open $filename] + # The INI-file for this routine has been pre-formatted by the linuxcnc + # startup script to handle includes, strings, comments and continuations. + if [catch {set f [open "${filename}.expanded"]} msg] { + # This is a fallback open. It happens in test twopass-personality. + # When this open is necessary, then a lot of errors are possible. + set f [open "${filename}"] + } while {[gets $f line] >= 0} { set line [string trim $line] diff --git a/tests/.gitignore b/tests/.gitignore index 47c336a2ce7..8c4c9dd8b1d 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -2,3 +2,4 @@ result stderr *.var *.var.bak +*.ini.expanded