1: # What makes this one better?  nothing really.  i tried out
   2: # App::Config, but (according to my understanding) one needs
   3: # to state all variables in the configuration before reading
   4: # in the configuration file.  That's useful in some situations,
   5: # i just didn't like it.  i tried Config::IniFile which worked
   6: # alright, but being lazy i don't like a function call in
   7: # between me and my values (i could also tie a hash to it,
   8: # which is useful, but i had a couple minutes so i thought i'd
   9: # do a quick reinvention of the wheel)
  10: #
  11: # What makes mine different is that it's a quick and dirty parser
  12: # that floods the packages namespace (not main's) with the
  13: # variables.  It doesn't handle arrays or hashes (to be handled
  14: # at a later date) just simple name=val (with any number of
  15: # spaces).
  16: #
  17: # The way to call it (in case you're interested) is just:
  18: #
  19: # use ConfFile("conf/file/name_here");
  20: #
  21: # this seems elegant and useful because i can put in one line
  22: # at the top of my code and use all of my configuration
  23: # variables.  It just makes sense to me for some reason.
  24: # Anyway, enough banter, here it is...
  25: 
  26: #!/usr/local/bin/perl -w
  27: 
  28: package ConfFile;
  29: use strict;
  30: use Carp;
  31: 
  32: sub import {
  33:    shift;               # this gets rid of the calling package...
  34:    my ($call) = caller;
  35: 
  36:    # i also changed this: why die cuz there was no file?
  37:    my $filename = $_[0] || return;
  38:    my $symbols  = &readFile;
  39: 
  40:    carp "No values were read in from $filename.\n" unless (keys %$symbols);
  41: 
  42:    # one has to turn off strict 'refs' in order to flood the namespace of
  43:    # the calling package in this way.
  44:    no strict qw(refs);
  45:    foreach (keys %$symbols) {
  46:       *{"${call}::${_}"} = \$symbols->{$_};
  47:    }
  48:    use strict qw(refs);
  49: 
  50:    return;
  51: }
  52: 
  53: sub readFile {
  54:    my $file = shift;
  55:    my (%sym, $key, $val);
  56:    local $_;
  57: 
  58:    open FILE, $file or croak "Couldn't open file $file: $!";
  59: 
  60:    while (<FILE>) {
  61:       next if /^\s*#|;/;
  62:       next if /^$/;
  63:       chomp;
  64: 
  65:       ($key, $val) = /^\s*?(\S+)\s*?=?\s*?(\S+)$/;
  66:       $sym{$key} = $val;
  67:    }
  68:    close FILE;
  69: 
  70:    return (keys %sym) ? \%sym : undef;
  71: }
  72: 
  73: 
  74: 1;
  75: 
  76: # please, please comment on anything done badly, i do hope
  77: # to use this someday soon...
  78: #
  79: # jynx
  80: #
  81: # Update: i used Fastolfe's suggestions so this looks
  82: # a little better...

Replies are listed 'Best First'.
Re: Yet Another Config File Parser Module
by Fastolfe (Vicar) on Dec 05, 2000 at 10:13 UTC
    You should probably use Carp and croak instead of die (and carp instead of warn) within your package like that. That takes the error messages one step "out" and informs the user where in *their* script the error took place (assuming of course that the module is perfect and would never flaw).

    In addition (and I guess this is more personal preference), a simple open(...) or die "..." is sufficient in my opinion, as opposed to testing if the file exists and is readable. The user will get error messages from the open call either way.

Re: Yet Another Config File Parser Module
by btrott (Parson) on Dec 05, 2000 at 07:16 UTC
    Just a quick comment (or a shameless plug, depending on how you see it): you might wish to try my Config::FreeForm module, which lets you define arbitrary configuration data structures in memory then write them to disk using Data::Dumper.

    You can separate config for different applications etc. into different files, and it manages them for you. You pull in the config sets you want like this:

    use Config::FreeForm sets => [ 'Foo', 'Bar' ];
    It aliases the keys in the config hash into the Config::FreeForm namespace.

    Take a look; you might like it.

      oops,

      i should have checked CPAN recently before i posted this. Last time i checked CPAN for a module that did this was earlier than when you posted your module (before Nov 11). Rather than rechecking this script was the result. Thank you for the info, i will definitely look into it...

      jynx

Re: Yet Another Config File Parser Module
by deprecated (Priest) on Dec 20, 2000 at 21:34 UTC
    seems like an awful lot of work to me. i actually wrote one this morning (admittedly not a module, but i dont see it as being necessary!) thats pretty easy to use and fits comfortably on 5 lines. this is actually my first posting so i hope the code turns out okay.
    # %settings = grok ( qq(filename), %settings ); sub grok { my $n = shift; open IN, $n; my @in = <IN>; close IN; my %input = shi +ft; my %hash_to_return; foreach my $setting (keys %input) { my ($p_name, $p) = /^([^\s=]+)\b(?:(?:\s*=\s*)|\s+)(.*)$/; if ($setting eq $p_name) { $hash_to_return{$p_name} = $p } else { next } } return %hash_to_return } # # grok, above, posted earlier, is broken. :) it was actually # an old version (old being > 12 hours in this case) # I had in the wrong directory. Sorry for any confusion. # unfortunately, this one isnt nearly as pretty. # sub grok2 { my $n = shift; if ($n) { open IN, $n or warn "BDU error" } else { warn "BDU error" ; return } @in = <IN>; close IN; my %input = shift; foreach my $item (@in) { my ($p_name, $p) = $item =~ /^([^\s=]+)\b(?:(?:\s*=\s*)|\s+)(.*)$/; foreach my $setting (keys %i +nput) { if ($setting eq $p_name) { $input{$setting} = $p } else { next } } + } return %hash_to_return } # note some checking for files/vars was added for chipmunk. # nyah. :p # de_grok ( qq(filename), %settings ); sub de_grok { my $n = shift; open OUT, $n; my %output = shift; foreach my $line (keys %output) { print OUT $line . ' ' . $output{ $line } } close OUT }
    as i recall, this compiles okay with -w and strict turned on. config file looks like "config_item the rest of the line are the arguments to config_item." since some users are kinda dumb about config files i allowed for a "config_var = params" too. the way i use this is like so:
    my %CONFIG = ( server_name => 'localhost', server_alias => 'opennap', server_ports => '4444 7777 8888', max_user_channels => '5', max_nick_length => '32', ); %CONFIG = grok ( qq(config), %CONFIG );
    i use this code in several applications. all of these focus on my opennap server. i set up my administration client-bots to grok in their config files (several actually) and the server reads its configs when it starts up and writes them to the disk every so often in case it crashes. its extremely versatile in that you can use it for userdb's, channeldb's, mp3 playlists, and so on.

    cheers,
    deprecated
    (server in question is located at macachu.yi.org if you wanna have a looksee at an opennap server being developed in perl)

      deprecated,

      true, that does fit in five lines. i have a general aversion to the copy-paste right-click however so rather than having to paste a function in over a dozen files, i'd rather call a module that has all the functionality instead.

      Have you checked out App::Config? It does exactly what your code does and more. The reason i didn't use it was a couple dozen configuration settings and i didn't want to set them all in every file before reading in the configuration. It's another aversion to redundancy...

      happy coding,
      jynx