123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- # ------------------------------------------------------------------------------
- # NAME
- # Fcm::CfgLine
- #
- # DESCRIPTION
- # This class is used for grouping the settings in each line of a FCM
- # configuration file.
- #
- # COPYRIGHT
- # (C) Crown copyright Met Office. All rights reserved.
- # For further details please refer to the file COPYRIGHT.txt
- # which you should have received as part of this distribution.
- # ------------------------------------------------------------------------------
- package Fcm::CfgLine;
- @ISA = qw(Fcm::Base);
- # Standard pragma
- use warnings;
- use strict;
- # Standard modules
- use File::Basename;
- # In-house modules
- use Fcm::Base;
- use Fcm::Config;
- use Fcm::Util;
- # List of property methods for this class
- my @scalar_properties = (
- 'bvalue', # line value, in boolean
- 'comment', # (in)line comment
- 'error', # error message for incorrect usage while parsing the line
- 'label', # line label
- 'line', # content of the line
- 'number', # line number in source file
- 'parsed', # has this line been parsed (by the extract/build system)?
- 'prefix', # optional prefix for line label
- 'slabel', # label without the optional prefix
- 'src', # name of source file
- 'value', # line value
- 'warning', # warning message for deprecated usage
- );
- # Useful variables
- our $COMMENT_RULER = '-' x 78;
- # ------------------------------------------------------------------------------
- # SYNOPSIS
- # @cfglines = Fcm::CfgLine->comment_block (@comment);
- #
- # DESCRIPTION
- # This method returns a list of Fcm::CfgLine objects representing a comment
- # block with the comment string @comment.
- # ------------------------------------------------------------------------------
- sub comment_block {
- my @return = (
- Fcm::CfgLine->new (comment => $COMMENT_RULER),
- (map {Fcm::CfgLine->new (comment => $_)} @_),
- Fcm::CfgLine->new (comment => $COMMENT_RULER),
- Fcm::CfgLine->new (),
- );
- return @return;
- }
- # ------------------------------------------------------------------------------
- # SYNOPSIS
- # $obj = Fcm::CfgLine->new (%args);
- #
- # DESCRIPTION
- # This method constructs a new instance of the Fcm::CfgLine class. See above
- # for allowed list of properties. (KEYS should be in uppercase.)
- # ------------------------------------------------------------------------------
- sub new {
- my $this = shift;
- my %args = @_;
- my $class = ref $this || $this;
- my $self = Fcm::Base->new (%args);
- for (@scalar_properties) {
- $self->{$_} = exists $args{uc ($_)} ? $args{uc ($_)} : undef;
- $self->{$_} = $args{$_} if exists $args{$_};
- }
- bless $self, $class;
- return $self;
- }
- # ------------------------------------------------------------------------------
- # SYNOPSIS
- # $value = $obj->X;
- # $obj->X ($value);
- #
- # DESCRIPTION
- # Details of these properties are explained in @scalar_properties.
- # ------------------------------------------------------------------------------
- for my $name (@scalar_properties) {
- no strict 'refs';
- *$name = sub {
- my $self = shift;
- if (@_) {
- $self->{$name} = $_[0];
- if ($name eq 'line' or $name eq 'label') {
- $self->{slabel} = undef;
- } elsif ($name eq 'line' or $name eq 'value') {
- $self->{bvalue} = undef;
- }
- }
- # Default value for property
- if (not defined $self->{$name}) {
- if ($name =~ /^(?:comment|error|label|line|prefix|src|value)$/) {
- # Blank
- $self->{$name} = '';
- } elsif ($name eq 'slabel') {
- if ($self->prefix and $self->label_starts_with ($self->prefix)) {
- $self->{$name} = $self->label_from_field (1);
- } else {
- $self->{$name} = $self->label;
- }
- } elsif ($name eq 'bvalue') {
- if (defined ($self->value)) {
- $self->{$name} = ($self->value =~ /^(\s*|false|no|off|0*)$/i)
- ? 0 : $self->value;
- }
- }
- }
- return $self->{$name};
- }
- }
- # ------------------------------------------------------------------------------
- # SYNOPSIS
- # @fields = $obj->label_fields ();
- # @fields = $obj->slabel_fields ();
- #
- # DESCRIPTION
- # These method returns a list of fields in the (s)label.
- # ------------------------------------------------------------------------------
- for my $name (qw/label slabel/) {
- no strict 'refs';
- my $sub_name = $name . '_fields';
- *$sub_name = sub {
- return (split (/$Fcm::Config::DELIMITER_PATTERN/, $_[0]->$name));
- }
- }
- # ------------------------------------------------------------------------------
- # SYNOPSIS
- # $string = $obj->label_from_field ($index);
- # $string = $obj->slabel_from_field ($index);
- #
- # DESCRIPTION
- # These method returns the (s)label from field $index onwards.
- # ------------------------------------------------------------------------------
- for my $name (qw/label slabel/) {
- no strict 'refs';
- my $sub_name = $name . '_from_field';
- *$sub_name = sub {
- my ($self, $index) = @_;
- my $method = $name . '_fields';
- my @fields = $self->$method;
- return join ($Fcm::Config::DELIMITER, @fields[$index .. $#fields]);
- }
- }
- # ------------------------------------------------------------------------------
- # SYNOPSIS
- # $flag = $obj->label_starts_with (@fields);
- # $flag = $obj->slabel_starts_with (@fields);
- #
- # DESCRIPTION
- # These method returns a true if (s)label starts with the labels in @fields
- # (ignore case).
- # ------------------------------------------------------------------------------
- for my $name (qw/label slabel/) {
- no strict 'refs';
- my $sub_name = $name . '_starts_with';
- *$sub_name = sub {
- my ($self, @fields) = @_;
- my $return = 1;
- my $method = $name . '_fields';
- my @all_fields = $self->$method;
- for my $i (0 .. $#fields) {
- next if lc ($fields[$i]) eq lc ($all_fields[$i] || '');
- $return = 0;
- last;
- }
- return $return;
- }
- }
- # ------------------------------------------------------------------------------
- # SYNOPSIS
- # $flag = $obj->label_starts_with_cfg (@fields);
- # $flag = $obj->slabel_starts_with_cfg (@fields);
- #
- # DESCRIPTION
- # These method returns a true if (s)label starts with the configuration file
- # labels in @fields (ignore case).
- # ------------------------------------------------------------------------------
- for my $name (qw/label slabel/) {
- no strict 'refs';
- my $sub_name = $name . '_starts_with_cfg';
- *$sub_name = sub {
- my ($self, @fields) = @_;
- for my $field (@fields) {
- $field = $self->cfglabel ($field);
- }
- my $method = $name . '_starts_with';
- return $self->$method (@fields);
- }
- }
- # ------------------------------------------------------------------------------
- # SYNOPSIS
- # $mesg = $obj->format_error ();
- #
- # DESCRIPTION
- # This method returns a string containing a formatted error message for
- # anything reported to the current line.
- # ------------------------------------------------------------------------------
- sub format_error {
- my ($self) = @_;
- my $mesg = '';
- $mesg .= $self->format_warning;
- if ($self->error or not $self->parsed) {
- $mesg = 'ERROR: ' . $self->src . ': LINE ' . $self->number . ':' . "\n";
- if ($self->error) {
- $mesg .= ' ' . $self->error;
- } else {
- $mesg .= ' ' . $self->label . ': label not recognised.';
- }
- }
- return $mesg;
- }
- # ------------------------------------------------------------------------------
- # SYNOPSIS
- # $mesg = $obj->format_warning ();
- #
- # DESCRIPTION
- # This method returns a string containing a formatted warning message for
- # any warning reported to the current line.
- # ------------------------------------------------------------------------------
- sub format_warning {
- my ($self) = @_;
- my $mesg = '';
- if ($self->warning) {
- $mesg = 'WARNING: ' . $self->src . ': LINE ' . $self->number . ':' . "\n";
- $mesg .= ' ' . $self->warning;
- }
- return $mesg;
- }
- # ------------------------------------------------------------------------------
- # SYNOPSIS
- # $line = $obj->print_line ([$space]);
- #
- # DESCRIPTION
- # This method returns a configuration line using $self->label, $self->value
- # and $self->comment. The value in $self->line is re-set. If $space is set
- # and is a positive integer, it sets the spacing between the label and the
- # value in the line. The default is 1.
- # ------------------------------------------------------------------------------
- sub print_line {
- my ($self, $space) = @_;
- # Set space between label and value, default to 1 character
- $space = 1 unless $space and $space =~ /^[1-9]\d*$/;
- my $line = '';
- # Add label and value, if label is set
- if ($self->label) {
- $line .= $self->label . ' ' x $space;
- $line .= $self->value if defined $self->value;
- }
- # Add comment if necessary
- my $comment = $self->comment;
- $comment =~ s/^\s*//;
- if ($comment) {
- $comment = '# ' . $comment if $comment !~ /^#/;
- $line .= ' ' if $line;
- $line .= $comment;
- }
- return $self->line ($line);
- }
- # ------------------------------------------------------------------------------
- 1;
- __END__
|