1 #============================================================================
5 # Perl5 module to read configuration files and use the contents therein
6 # to update variable values in an AppConfig::State object.
8 # Written by Andy Wardley <abw@wardley.org>
10 # Copyright (C) 1997-2007 Andy Wardley. All Rights Reserved.
11 # Copyright (C) 1997,1998 Canon Research Centre Europe Ltd.
13 #============================================================================
15 package AppConfig::File;
20 our $VERSION = '1.65';
23 #------------------------------------------------------------------------
24 # new($state, $file, [$file, ...])
26 # Module constructor. The first, mandatory parameter should be a
27 # reference to an AppConfig::State object to which all actions should
28 # be applied. The remaining parameters are assumed to be file names or
29 # file handles for reading and are passed to parse().
31 # Returns a reference to a newly created AppConfig::File object.
32 #------------------------------------------------------------------------
38 STATE => $state, # AppConfig::State ref
39 DEBUG => $state->_debug(), # store local copy of debug
40 PEDANTIC => $state->_pedantic, # and pedantic flags
45 # call parse(@_) to parse any files specified as further params
46 $self->parse(@_) if @_;
52 #------------------------------------------------------------------------
53 # parse($file, [file, ...])
55 # Reads and parses a config file, updating the contents of the
56 # AppConfig::State referenced by $self->{ STATE } according to the
57 # contents of the file. Multiple files may be specified and are
58 # examined in turn. The method reports any error condition via
59 # $self->{ STATE }->_error() and immediately returns undef if it
60 # encounters a system error (i.e. cannot open one of the files.
61 # Parsing errors such as unknown variables or unvalidated values will
62 # also cause warnings to be raised vi the same _error(), but parsing
63 # continues to the end of the current file and through any subsequent
64 # files. If the PEDANTIC option is set in the $self->{ STATE } object,
65 # the behaviour is overridden and the method returns 0 immediately on
66 # any system or parsing error.
68 # The EXPAND option for each variable determines how the variable
69 # value should be expanded.
71 # Returns undef on system error, 0 if all files were parsed but generated
72 # one or more warnings, 1 if all files parsed without warnings.
73 #------------------------------------------------------------------------
78 my $prefix; # [block] defines $prefix
82 # take a local copy of the state to avoid much hash dereferencing
83 my ($state, $debug, $pedantic) = @$self{ qw( STATE DEBUG PEDANTIC ) };
85 # we want to install a custom error handler into the AppConfig::State
86 # which appends filename and line info to error messages and then
87 # calls the previous handler; we start by taking a copy of the
89 my $errhandler = $state->_ehandler();
91 # ...and if it doesn't exist, we craft a default handler
92 $errhandler = sub { warn(sprintf(shift, @_), "\n") }
93 unless defined $errhandler;
95 # install a closure as a new error handler
98 # modify the error message
102 : " at $file line $.";
104 # chain call to prevous handler
105 &$errhandler($format, @_);
109 # trawl through all files passed as params
110 FILE: while ($file = shift) {
112 # local/lexical vars ensure opened files get closed
116 # if the file is a reference, we assume it's a file handle, if
117 # not, we assume it's a filename and attempt to open it
123 print STDERR "reading from file handle: $file\n" if $debug;
126 # open and read config file
127 open(FH, $file) or do {
128 # restore original error handler and report error
129 $state->_ehandler($errhandler);
130 $state->_error("$file: $!");
137 print STDERR "reading file: $file\n" if $debug;
140 # initialise $prefix to nothing (no [block])
146 # Throw away everything from an unescaped # to EOL
149 # add next line if there is one and this is a continuation
150 if (s/\\$// && !eof($handle)) {
161 # strip leading and trailing whitespace
165 # look for a [block] to set $prefix
166 if (/^\[([^\]]+)\]$/) {
168 print STDERR "Entering [$prefix] block\n" if $debug;
172 # split line up by whitespace (\s+) or "equals" (\s*=\s*)
173 if (/^([^\s=]+)(?:(?:(?:\s*=\s*)|\s+)(.*))?/) {
174 my ($variable, $value) = ($1, $2);
176 if (defined $value) {
178 if ($value =~ /^([^\s=]+\s*=)?\s*<<(['"]?)(\S+)\2$/) { # '<<XX' or 'hashkey =<<XX'
179 my $boundary = "$3\n";
180 $value = defined($1) ? $1 : '';
182 last if $_ eq $boundary;
185 $value =~ s/[\r\n]$//;
187 # strip any quoting from the variable value
188 $value =~ s/^(['"])(.*)\1$/$2/;
192 # strip any leading '+/-' from the variable
193 $variable =~ s/^([\-+]?)//;
196 # $variable gets any $prefix
197 $variable = $prefix . '_' . $variable
200 # if the variable doesn't exist, we call set() to give
201 # AppConfig::State a chance to auto-create it
202 unless ($state->_exists($variable)
203 || $state->set($variable, 1)) {
205 last FILE if $pedantic;
209 my $nargs = $state->_argcount($variable);
211 # variables prefixed '-' are reset to their default values
213 $state->_default($variable);
216 # those prefixed '+' get set to 1
217 elsif ($flag eq '+') {
218 $value = 1 unless defined $value;
221 # determine if any extra arguments were expected
223 if (defined $value && length $value) {
224 # expand any embedded variables, ~uids or
225 # environment variables, testing the return value
226 # for errors; we pass in any variable-specific
228 unless ($self->_expand(\$value,
229 $state->_expand($variable), $prefix)) {
230 print STDERR "expansion of [$value] failed\n"
233 last FILE if $pedantic;
237 $state->_error("$variable expects an argument");
239 last FILE if $pedantic;
245 # default value to 1 unless it is explicitly defined
247 if (defined $value) {
249 $value = 0 if $value =~ /off/i;
251 $value = 1 if $value;
254 # assume 1 unless explicitly defined off/0
257 print STDERR "$variable => $value (no expansion)\n"
261 # set the variable, noting any failure from set()
262 unless ($state->set($variable, $value)) {
264 last FILE if $pedantic;
268 $state->_error("parse error");
274 # restore original error handler
275 $state->_ehandler($errhandler);
277 # return $warnings => 0, $success => 1
278 return $warnings ? 0 : 1;
283 #========================================================================
284 # ----- PRIVATE METHODS -----
285 #========================================================================
287 #------------------------------------------------------------------------
288 # _expand(\$value, $expand, $prefix)
290 # The variable value string, referenced by $value, is examined and any
291 # embedded variables, environment variables or tilde globs (home
292 # directories) are replaced with their respective values, depending on
293 # the value of the second parameter, $expand. The third paramter may
294 # specify the name of the current [block] in which the parser is
295 # parsing. This prefix is prepended to any embedded variable name that
296 # can't otherwise be resolved. This allows the following to work:
300 # html = $define_home/public_html
301 # html = $home/public_html # same as above, 'define' is prefix
303 # Modifications are made directly into the variable referenced by $value.
304 # The method returns 1 on success or 0 if any warnings (undefined
305 # variables) were encountered.
306 #------------------------------------------------------------------------
309 my ($self, $value, $expand, $prefix) = @_;
311 my ($sys, $var, $val);
314 # ensure prefix contains something (nothing!) valid for length()
315 $prefix = "" unless defined $prefix;
317 # take a local copy of the state to avoid much hash dereferencing
318 my ($state, $debug, $pedantic) = @$self{ qw( STATE DEBUG PEDANTIC ) };
320 # bail out if there's nothing to do
321 return 1 unless $expand && defined($$value);
323 # create an AppConfig::Sys instance, or re-use a previous one,
324 # to handle platform dependant functions: getpwnam(), getpwuid()
325 unless ($sys = $self->{ SYS }) {
326 require AppConfig::Sys;
327 $sys = $self->{ SYS } = AppConfig::Sys->new();
330 print STDERR "Expansion of [$$value] " if $debug;
336 # expand $(var) and $var as AppConfig::State variables
338 if ($expand & AppConfig::EXPAND_VAR) {
341 (?<!\\)\$ (?: \((\w+)\) | (\w+) ) # $2 => $(var) | $3 => $var
344 # embedded variable name will be one of $2 or $3
345 $var = defined $1 ? $1 : $2;
347 # expand the variable if defined
348 if ($state->_exists($var)) {
349 $val = $state->get($var);
351 elsif (length $prefix
352 && $state->_exists($prefix . '_' . $var)) {
353 print STDERR "(\$$var => \$${prefix}_$var) "
355 $var = $prefix . '_' . $var;
356 $val = $state->get($var);
359 # raise a warning if EXPAND_WARN set
360 if ($expand & AppConfig::EXPAND_WARN) {
361 $state->_error("$var: no such variable");
365 # replace variable with nothing
369 # $val gets substituted back into the $value string
373 $$value =~ s/\\\$/\$/g;
375 # bail out now if we need to
376 last EXPAND if $warnings && $pedantic;
382 # expand ~uid as home directory (for $< if uid not specified)
384 if ($expand & AppConfig::EXPAND_UID) {
386 ~(\w+)? # $1 => username (optional)
390 # embedded user name may be in $1
391 if (defined ($var = $1)) {
392 # try and get user's home directory
393 if ($sys->can_getpwnam()) {
394 $val = ($sys->getpwnam($var))[7];
397 # determine home directory
401 # catch-all for undefined $dir
402 unless (defined $val) {
403 # raise a warning if EXPAND_WARN set
404 if ($expand & AppConfig::EXPAND_WARN) {
405 $state->_error("cannot determine home directory%s",
406 defined $var ? " for $var" : "");
410 # replace variable with nothing
414 # $val gets substituted back into the $value string
418 # bail out now if we need to
419 last EXPAND if $warnings && $pedantic;
425 # expand ${VAR} as environment variables
427 if ($expand & AppConfig::EXPAND_ENV) {
434 # expand the variable if defined
435 if (exists $ENV{ $var }) {
437 } elsif ( $var eq 'HOME' ) {
438 # In the special case of HOME, if not set
439 # use the internal version
440 $val = $self->{ HOME };
442 # raise a warning if EXPAND_WARN set
443 if ($expand & AppConfig::EXPAND_WARN) {
444 $state->_error("$var: no such environment variable");
448 # replace variable with nothing
451 # $val gets substituted back into the $value string
455 # bail out now if we need to
456 last EXPAND if $warnings && $pedantic;
460 print STDERR "=> [$$value] (EXPAND = $expand)\n" if $debug;
463 return $warnings ? 0 : 1;
468 #------------------------------------------------------------------------
471 # Dumps the contents of the Config object.
472 #------------------------------------------------------------------------
477 foreach my $key (keys %$self) {
478 printf("%-10s => %s\n", $key,
479 defined($self->{ $key }) ? $self->{ $key } : "<undef>");
491 AppConfig::File - Perl5 module for reading configuration files.
497 my $state = AppConfig::State->new(\%cfg1);
498 my $cfgfile = AppConfig::File->new($state, $file);
500 $cfgfile->parse($file); # read config file
504 AppConfig::File is a Perl5 module which reads configuration files and use
505 the contents therein to update variable values in an AppConfig::State
508 AppConfig::File is distributed as part of the AppConfig bundle.
512 =head2 USING THE AppConfig::File MODULE
514 To import and use the AppConfig::File module the following line should appear
519 AppConfig::File is used automatically if you use the AppConfig module
520 and create an AppConfig::File object through the file() method.
522 AppConfig::File is implemented using object-oriented methods. A new
523 AppConfig::File object is created and initialised using the
524 AppConfig::File->new() method. This returns a reference to a new
525 AppConfig::File object. A reference to an AppConfig::State object
526 should be passed in as the first parameter:
528 my $state = AppConfig::State->new();
529 my $cfgfile = AppConfig::File->new($state);
531 This will create and return a reference to a new AppConfig::File object.
533 =head2 READING CONFIGURATION FILES
535 The C<parse()> method is used to read a configuration file and have the
536 contents update the STATE accordingly.
538 $cfgfile->parse($file);
540 Multiple files maye be specified and will be read in turn.
542 $cfgfile->parse($file1, $file2, $file3);
544 The method will return an undef value if it encounters any errors opening
545 the files. It will return immediately without processing any further files.
546 By default, the PEDANTIC option in the AppConfig::State object,
547 $self->{ STATE }, is turned off and any parsing errors (invalid variables,
548 unvalidated values, etc) will generated warnings, but not cause the method
549 to return. Having processed all files, the method will return 1 if all
550 files were processed without warning or 0 if one or more warnings were
551 raised. When the PEDANTIC option is turned on, the method generates a
552 warning and immediately returns a value of 0 as soon as it encounters any
555 Variables values in the configuration files may be expanded depending on
556 the value of their EXPAND option, as determined from the App::State object.
557 See L<AppConfig::State> for more information on variable expansion.
559 =head2 CONFIGURATION FILE FORMAT
561 A configuration file may contain blank lines and comments which are
562 ignored. Comments begin with a '#' as the first character on a line
563 or following one or more whitespace tokens, and continue to the end of
567 foo = bar # so is this
568 url = index.html#hello # this too, but not the '#welcome'
570 Notice how the '#welcome' part of the URL is not treated as a comment
571 because a whitespace character doesn't precede it.
573 Long lines can be continued onto the next line by ending the first
576 callsign = alpha bravo camel delta echo foxtrot golf hipowls \
577 india juliet kilo llama mike november oscar papa \
578 quebec romeo sierra tango umbrella victor whiskey \
581 Variables that are simple flags and do not expect an argument (ARGCOUNT =
582 ARGCOUNT_NONE) can be specified without any value. They will be set with
583 the value 1, with any value explicitly specified (except "0" and "off")
584 being ignored. The variable may also be specified with a "no" prefix to
585 implicitly set the variable to 0.
589 verbose = 0 # off (0)
590 verbose off # off (0)
592 verbose mumble # on (1)
595 Variables that expect an argument (ARGCOUNT = ARGCOUNT_ONE) will be set to
596 whatever follows the variable name, up to the end of the current line. An
597 equals sign may be inserted between the variable and value for clarity.
602 Each subsequent re-definition of the variable value overwrites the previous
605 print $config->room(); # prints "/home/bedroom"
607 Variables may be defined to accept multiple values (ARGCOUNT = ARGCOUNT_LIST).
608 Each subsequent definition of the variable adds the value to the list of
609 previously set values for the variable.
614 A reference to a list of values is returned when the variable is requested.
616 my $beverages = $config->drinks();
617 print join(", ", @$beverages); # prints "coffee, tea"
619 Variables may also be defined as hash lists (ARGCOUNT = ARGCOUNT_HASH).
620 Each subsequent definition creates a new key and value in the hash array.
625 A reference to the hash is returned when the variable is requested.
627 my $aliases = $config->alias();
628 foreach my $k (keys %$aliases) {
629 print "$k => $aliases->{ $k }\n";
632 A large chunk of text can be defined using Perl's "heredoc" quoting
635 scalar = <<BOUNDARY_STRING
637 line 2: Space/linebreaks within a HERE document are kept.
638 line 3: The last linebreak (\n) is stripped.
642 * Quotes (['"]) around the boundary string are simply ignored.
643 * Whether the variables in HERE document are expanded depends on
644 the EXPAND option of the variable or global setting.
647 hash = key2 = <<"_bar_"
648 Text within HERE document are kept as is.
649 # comments are treated as a normal text.
650 The same applies to line continuation. \
653 Note that you cannot use HERE document as a key in a hash or a name
656 The '-' prefix can be used to reset a variable to its default value and
657 the '+' prefix can be used to set it to 1
662 Variable, environment variable and tilde (home directory) expansions
663 Variable values may contain references to other AppConfig variables,
664 environment variables and/or users' home directories. These will be
665 expanded depending on the EXPAND value for each variable or the GLOBAL
668 Three different expansion types may be applied:
670 bin = ~/bin # expand '~' to home dir if EXPAND_UID
671 tmp = ~abw/tmp # as above, but home dir for user 'abw'
673 perl = $bin/perl # expand value of 'bin' variable if EXPAND_VAR
674 ripl = $(bin)/ripl # as above with explicit parens
676 home = ${HOME} # expand HOME environment var if EXPAND_ENV
678 See L<AppConfig::State> for more information on expanding variable values.
680 The configuration files may have variables arranged in blocks. A block
681 header, consisting of the block name in square brackets, introduces a
682 configuration block. The block name and an underscore are then prefixed
683 to the names of all variables subsequently referenced in that block. The
684 block continues until the next block definition or to the end of the current
688 foo = 10 # block1_foo = 10
691 foo = 20 # block2_foo = 20
695 Andy Wardley, E<lt>abw@wardley.orgE<gt>
699 Copyright (C) 1997-2007 Andy Wardley. All Rights Reserved.
701 This module is free software; you can redistribute it and/or modify it
702 under the same terms as Perl itself.
706 AppConfig, AppConfig::State