namespace eval cfg { variable version 1.0 variable sections [list DEFAULT] variable cursection DEFAULT variable DEFAULT; # DEFAULT section } proc cfg::sections {} { return $cfg::sections } proc cfg::variables {{section DEFAULT}} { return [array names ::cfg::$section] } proc cfg::add_section {str} { variable sections variable cursection set cursection [string trim $str \[\]] if {[lsearch -exact $sections $cursection] == -1} { lappend sections $cursection variable ::cfg::${cursection} } } proc cfg::setvar {varname value {section DEFAULT}} { variable sections if {[lsearch -exact $sections $section] == -1} { cfg::add_section $section } set ::cfg::${section}($varname) $value } proc cfg::getvar {varname {section DEFAULT}} { variable sections if {[lsearch -exact $sections $section] == -1} { error "No such section: $section" } return [set ::cfg::${section}($varname)] } proc cfg::parse_file {filename} { variable sections variable cursection set line_no 1 set fd [open $filename r] while {![eof $fd]} { set line [string trim [gets $fd] " "] if {$line == ""} continue switch -regexp -- $line { ^#.* { } ^\\[.*\\]$ { cfg::add_section $line } .*=.* { set pair [split $line =] set name [string trim [lindex $pair 0] " "] set value [string trim [lindex $pair 1] " "] cfg::setvar $name $value $cursection } default { error "Error parsing $filename (line: $line_no): $line" } } incr line_no } close $fd }
Given: (startup.ini)
# a DEFAULT attribute # debug=true [EMAIL] from_addr = tcoram@pobox.com to_addr = nobody@maplefish.com [DEFAULT] trace_level = 5Here is how you can use it:
cfg::parse_file startup.ini set dbg $cfg::DEFAULT(debug) set dbg [cfg::getvar debug DEFAULT] puts "email comes from $cfg::EMAIL(from_addr)"
Removed unneeded $ characters and added missing g and " characters to get the script working. -- [George H. Lewis]
There also is an inifile parser in Tcllib. MHo: And another on here: One more inifile parser, including test and documentation.
David Easton 19 Mar 2004 - I had a need for reading and writing config files within a metakit virtual filesystem. Unfortunately the Tcllib inifile parser was not suitable due to the access specifiers used with the config file. I came up with the Snit cfg package to get around these problems.
AMG: Here's another approach: Config file using slave interp