=head1 NAME

CFX5::Config::def - meta module to declare config variables

=head1 SYNOPSIS

  package CFX5::NewModule;
  use CFX5::Config::def CFX5_CCL_LIB =>
    {
      code => sub { join_file($Config{CFX5ROOT},'lib',$Config{CFXBUILDID},'ccl') },
      section => 'ASettings for CFX Command Language',
      nonstdpart => 'CFX Command Language Library %%',
    };
  use CFX5::Config::def CFX5_MYMODULE_HELLO => sub { 'hello' },
                        CXF5_MYMODULE_BYE   => sub { 'bye' };

=head1 DESCRIPTION

This module is used to provide configuration information, in addition
to L<CFX5::DefaultConfig>.  Normal usage is as shown above, and
defines the routine to set the named variable.  Note that, contrary to
expectation, you B<cannot> say
  use CFX5::Config::def CFX5_MYMODULE_HELLO => 'hello';
it must be a subroutine which can be called to calculate the variable
at runtime if necessary.

Alternatively, the definition can be a hash reference, in which case
it can contian the following keys:

=over

=item code

I<Required>  This is the routine used to calculate the variable.

=item section

If included, this is the section in which to show this variable in
L<CFX5::PrintConfig>.

=item nonstdpart

If included, this will mark this variable for checking and warning
about in C<warn_nonstd_parts>.  The value should be a string
describing the setting.  If "C<%%>" is included in the string it will
be replaced by the setting.

=back

The module works by exporting the routine into the
C<CFX5::Config::def::_config> module under the given name;
L<CFX5::CurrentConfig> knows to look in this module for extra
information.

=cut

package CFX5::Config::def::_config;
use strict;

package CFX5::Config::def;
use strict;

use Carp;

=head2 import

  use CFX5::Config::def CFX5_CCL_LIB =>
    {
      code => sub { join_file($Config{CFX5ROOT},'lib',$Config{CFXBUILDID},'ccl') },
      section => 'ASettings for CFX Command Language',
      nonstdpart => 'CFX Command Language Library %%',
    };
			       
This module has a special C<import> method, which exports the routine
under the given name into a special module; see above.  This module
exports no special functions.

=cut

sub import {
  my $class=shift;
  my ($name,$data);

  while (defined ($name=shift) and defined ($data=shift)) {
    my ($sub,$prsect,$nonstd);
    
    if (ref($data) eq 'HASH') {
      croak("code element missing from definition of $name")
	unless exists $data->{code};
      $sub=$data->{code};
      $prsect=$data->{section};
      $nonstd=$data->{nonstdpart};
    } else {
      $sub=$data;
    }

    unless (ref($sub) eq 'CODE') {
      local $Carp::CarpLevel=1;
      croak("Variable $name must be defined by a hash ref or a coderef");
    }

    {
      no strict 'refs';
      carp "Config routine ${name} already defined using $class"
	if defined &{"${class}::_config::${name}"};
      *{"${class}::_config::${name}"} = \&{$sub};
    }
  }

  1;
}

1;
