diff options
Diffstat (limited to 'lib/Config/Parser')
-rw-r--r-- | lib/Config/Parser/Ini.pm | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/lib/Config/Parser/Ini.pm b/lib/Config/Parser/Ini.pm new file mode 100644 index 0000000..b3a1ef9 --- /dev/null +++ b/lib/Config/Parser/Ini.pm @@ -0,0 +1,96 @@ +package Config::Parser::Ini; +use strict; +use warnings; +use parent 'Config::Parser'; +use Carp; +use Text::ParseWords; + +sub parse { + my $self = shift; + $self->{_filename} = shift // confess "No filename given"; + local %_ = @_; + $self->debug(1, "parsing $self->{_filename}"); + $self->_readconfig($self->{_filename}, %_); + return $self; +} + +sub filename { shift->{_filename} } + +# _readconfig(FILE) +sub _readconfig { + my $self = shift; + my $file = shift; + local %_ = @_; + my $fh = delete $_{fh}; + my $need_close; + + $self->debug(1, "reading file $file"); + unless ($fh) { + open($fh, "<", $file) + or do { + $self->error("can't open configuration file $file: $!"); + $self->{_error_count}++; + return 0; + }; + $need_close = 1; + } + + my $line = delete $_{line} // 0; + my @path; + my $include; + + while (<$fh>) { + ++$line; + chomp; + if (/\\$/) { + chop; + $_ .= <$fh>; + redo; + } + + s/^\s+//; + s/\s+$//; + s/#.*//; + next if ($_ eq ""); + + my $locus = new Config::Tree::Locus($file, $line); + + if (/^\[(.+?)\]$/) { + @path = parse_line('\s+', 0, $1); + if (@path == 1 && $path[0] eq 'include') { + $include = 1; + } else { + $include = 0; + $self->add_node(\@path, + new Config::Tree::Node::Section(locus => $locus)); + } + } elsif (/([\w_-]+)\s*=\s*(.*)/) { + my ($k, $v) = ($1, $2); + $k = lc($k) if $self->{_ci}; #FIXME:private member + + if ($include) { + if ($k eq 'path') { + $self->_readconfig($v); + } elsif ($k eq 'pathopt') { + $self->_readconfig($v) if -f $v; + } elsif ($k eq 'glob') { + foreach my $file (bsd_glob($v, 0)) { + $self->_readconfig($file); + } + } else { + $self->error("keyword \"$k\" is unknown", locus => $locus); + $self->{_error_count}++; + } + } else { + $self->add_value([@path, $k], $v, $locus); + } + } else { + $self->error("malformed line", locus => $locus); + $self->{_error_count}++; + } + } + close $fh if $need_close; +} + +1; + |