Version 2 of Config File Parser

Updated 2002-04-24 15:56:38

Is there a standard/popular parser for .ini style configuration file parsers? If not, here is one that I use. It doesn't write config files, but does read them into arrays named by config file section.

-- Todd Coram

 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] " "]
      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 = [email protected]
 to_addr = [email protected]

 [DEFAULT]
 trace_level = 5

Here 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)