You will need to open TWO channels to "modify the content of a file".
1. Open the original file "read access".
2. Open an output file "write access".
As you read the input file line by line, print the modifications to the output file.
If you need to replace the input file with the output file -- end the script with:
> file rename <name_of_output_file> <name_of_input_file>
OTHER SUGGESTIONS:
TCLTEST:
I would recommend looking into tcltest instead of writing your own test flow control program -- especially if what you're describing is something that will control test flow.
https://www.tcl.tk/man/tcl/TclCmd/tcltest.htm
Example Code:
The tcl source directory has tons of examples showing how to use tcltest.
It is an amazing place to ramp up quickly!
BUT WHAT IF I DONT USE TCLTEST?:
If, for whatever reason you want to continue developing your test package, I have two suggestions:
Suggestion 1:
Make data.tcl an array:
./data.tcl
array set test ""
set test(mac) 0
set test(xmac) 1
set test(fea) 0
set test(fea1) 0
If you need to preserver order -- add this:
set test(1,mac) 0
set test(2,xmac) 1
set test(3,fea) 0
set test(4,fea1) 0
Then simply source the file in your run.
> source data.tcl
And this gets you the current values of all variables and can be updated changed as needed.
Then simply write out the data file:
> set o [open data.tcl w]
> foreach arrayName [lsort -dictionary [array names test]] {
puts $o "set test($arrayName) $test($arrayName)"
}
> close $o
WHAT IF I HAVE OTHER CRITERIA?
If the criteria expands for what your assignment is -- like how to handle inserting tests or other features, skip tests, defining pass/fail criteria, etc -- you will quickly start reinventing 'tcltest' package and all of its magic -- so I would recommend going tcltest.
Suggestion 2:
As I look at your code, "I see" what might be a fundamantel question you have (not easy to see but after some thought) -- you might be hung up on automatically figuring out if a test has been added or changed, etc...
If that's the case - the concept you're looking for is: [info vars]
set init_vars [info_vars]
source data.tcl
set final_vars [info vars]
listcomp $final_vars $init_vars
Write yourself a little listcomp procedure (here you go):
./listcomp.tcl
proc listcomp {a b} {
# Be sure to pass the new list first (a) (larger of the two lists)
# followed by reference list (b)...
# because foreach only looks at (a) and if (a) is the smaller of the two lists, items in (b) will not be checked...
# Returns the difference/list
set diff {}
foreach i $a {
if {[lsearch -exact $b $i]==-1} {
lappend diff $i
}
}
return $diff
}
And now you know if/any new variables have been added.
You can also keep a record of old values and new values (enhance the code above), etc...
I think you're going to come back with, but..."what about this" and but..."what about that"...and keep expanding the actual criteria that you 'need' or 'want' -- whatever the case may be. You haven't shared if this is 'homework' or 'work'.
If this is 'work -- definitely go with 'tcltest' package!
But lets go down the rat hole a little more...
Suggestion 3:
Think about doing a csv structure in the data.tcl file instead of what you have now. This way as you loop through the file, it has a fixed structure, you can think about what other fields of information you want to have and have that part of the format and as you modify the file/contents on the fly this becomes easy(er).
FYI: I used the 'info vars' trick shown above to solve a 'big data' problem where I needed to source many tcl files (huge files) and bring that data into memory to work on (restore a design). So I read each file into a separate thread, leveraging tcl ::thread package and then brought the variables back to the main thread using tcl ::tsv (thread save variables).
There is a little bit of code (literally a little bit) that is required to send the variables back to the main/thread depending on if it's an array or scalar variable -- left as an exercise for the user or another post.
Jim