207 lines
4.5 KiB
Perl
207 lines
4.5 KiB
Perl
|
# Copyright (C) 2003-2013 Free Software Foundation, Inc.
|
||
|
|
||
|
# This program is free software; you can redistribute it and/or modify
|
||
|
# it under the terms of the GNU General Public License as published by
|
||
|
# the Free Software Foundation; either version 2, or (at your option)
|
||
|
# any later version.
|
||
|
|
||
|
# This program is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU General Public License for more details.
|
||
|
|
||
|
# You should have received a copy of the GNU General Public License
|
||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
package Automake::Item;
|
||
|
|
||
|
use 5.006;
|
||
|
use strict;
|
||
|
use Carp;
|
||
|
use Automake::ChannelDefs;
|
||
|
use Automake::DisjConditions;
|
||
|
|
||
|
=head1 NAME
|
||
|
|
||
|
Automake::Item - base class for Automake::Variable and Automake::Rule
|
||
|
|
||
|
=head1 DESCRIPTION
|
||
|
|
||
|
=head2 Methods
|
||
|
|
||
|
=over 4
|
||
|
|
||
|
=item C<new Automake::Item $name>
|
||
|
|
||
|
Create and return an empty Item called C<$name>.
|
||
|
|
||
|
=cut
|
||
|
|
||
|
sub new ($$)
|
||
|
{
|
||
|
my ($class, $name) = @_;
|
||
|
my $self = {
|
||
|
name => $name,
|
||
|
defs => {},
|
||
|
conds => {},
|
||
|
};
|
||
|
bless $self, $class;
|
||
|
return $self;
|
||
|
}
|
||
|
|
||
|
=item C<$item-E<gt>name>
|
||
|
|
||
|
Return the name of C<$item>.
|
||
|
|
||
|
=cut
|
||
|
|
||
|
sub name ($)
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
return $self->{'name'};
|
||
|
}
|
||
|
|
||
|
=item C<$item-E<gt>def ($cond)>
|
||
|
|
||
|
Return the definition for this item in condition C<$cond>, if it
|
||
|
exists. Return 0 otherwise.
|
||
|
|
||
|
=cut
|
||
|
|
||
|
sub def ($$)
|
||
|
{
|
||
|
# This method is called very often, so keep it small and fast. We
|
||
|
# don't mind the extra undefined items introduced by lookup failure;
|
||
|
# avoiding this with 'exists' means doing two hash lookup on
|
||
|
# success, and proved worse on benchmark.
|
||
|
my $def = $_[0]->{'defs'}{$_[1]};
|
||
|
return defined $def && $def;
|
||
|
}
|
||
|
|
||
|
=item C<$item-E<gt>rdef ($cond)>
|
||
|
|
||
|
Return the definition for this item in condition C<$cond>. Abort with
|
||
|
an internal error if the item was not defined under this condition.
|
||
|
|
||
|
The I<r> in front of C<def> stands for I<required>. One
|
||
|
should call C<rdef> to assert the conditional definition's existence.
|
||
|
|
||
|
=cut
|
||
|
|
||
|
sub rdef ($$)
|
||
|
{
|
||
|
my ($self, $cond) = @_;
|
||
|
my $d = $self->def ($cond);
|
||
|
prog_error ("undefined condition '" . $cond->human . "' for '"
|
||
|
. $self->name . "'\n" . $self->dump)
|
||
|
unless $d;
|
||
|
return $d;
|
||
|
}
|
||
|
|
||
|
=item C<$item-E<gt>set ($cond, $def)>
|
||
|
|
||
|
Add a new definition to an existing item.
|
||
|
|
||
|
=cut
|
||
|
|
||
|
sub set ($$$)
|
||
|
{
|
||
|
my ($self, $cond, $def) = @_;
|
||
|
$self->{'defs'}{$cond} = $def;
|
||
|
$self->{'conds'}{$cond} = $cond;
|
||
|
}
|
||
|
|
||
|
=item C<$var-E<gt>conditions>
|
||
|
|
||
|
Return an L<Automake::DisjConditions> describing the conditions that
|
||
|
that an item is defined in.
|
||
|
|
||
|
These are all the conditions for which is would be safe to call
|
||
|
C<rdef>.
|
||
|
|
||
|
=cut
|
||
|
|
||
|
sub conditions ($)
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
prog_error ("self is not a reference")
|
||
|
unless ref $self;
|
||
|
return new Automake::DisjConditions (values %{$self->{'conds'}});
|
||
|
}
|
||
|
|
||
|
=item C<@missing_conds = $var-E<gt>not_always_defined_in_cond ($cond)>
|
||
|
|
||
|
Check whether C<$var> is always defined for condition C<$cond>.
|
||
|
Return a list of conditions where the definition is missing.
|
||
|
|
||
|
For instance, given
|
||
|
|
||
|
if COND1
|
||
|
if COND2
|
||
|
A = foo
|
||
|
D = d1
|
||
|
else
|
||
|
A = bar
|
||
|
D = d2
|
||
|
endif
|
||
|
else
|
||
|
D = d3
|
||
|
endif
|
||
|
if COND3
|
||
|
A = baz
|
||
|
B = mumble
|
||
|
endif
|
||
|
C = mumble
|
||
|
|
||
|
we should have (we display result as conditional strings in this
|
||
|
illustration, but we really return DisjConditions objects):
|
||
|
|
||
|
var ('A')->not_always_defined_in_cond ('COND1_TRUE COND2_TRUE')
|
||
|
=> ()
|
||
|
var ('A')->not_always_defined_in_cond ('COND1_TRUE')
|
||
|
=> ()
|
||
|
var ('A')->not_always_defined_in_cond ('TRUE')
|
||
|
=> ("COND1_FALSE COND3_FALSE")
|
||
|
var ('B')->not_always_defined_in_cond ('COND1_TRUE')
|
||
|
=> ("COND1_TRUE COND3_FALSE")
|
||
|
var ('C')->not_always_defined_in_cond ('COND1_TRUE')
|
||
|
=> ()
|
||
|
var ('D')->not_always_defined_in_cond ('TRUE')
|
||
|
=> ()
|
||
|
var ('Z')->not_always_defined_in_cond ('TRUE')
|
||
|
=> ("TRUE")
|
||
|
|
||
|
=cut
|
||
|
|
||
|
sub not_always_defined_in_cond ($$)
|
||
|
{
|
||
|
my ($self, $cond) = @_;
|
||
|
|
||
|
# Compute the subconditions where $var isn't defined.
|
||
|
return
|
||
|
$self->conditions
|
||
|
->sub_conditions ($cond)
|
||
|
->invert
|
||
|
->multiply ($cond);
|
||
|
}
|
||
|
|
||
|
|
||
|
1;
|
||
|
|
||
|
### Setup "GNU" style for perl-mode and cperl-mode.
|
||
|
## Local Variables:
|
||
|
## perl-indent-level: 2
|
||
|
## perl-continued-statement-offset: 2
|
||
|
## perl-continued-brace-offset: 0
|
||
|
## perl-brace-offset: 0
|
||
|
## perl-brace-imaginary-offset: 0
|
||
|
## perl-label-offset: -2
|
||
|
## cperl-indent-level: 2
|
||
|
## cperl-brace-offset: 0
|
||
|
## cperl-continued-brace-offset: 0
|
||
|
## cperl-label-offset: -2
|
||
|
## cperl-extra-newline-before-brace: t
|
||
|
## cperl-merge-trailing-else: nil
|
||
|
## cperl-continued-statement-offset: 2
|
||
|
## End:
|