Subversion Repositories DevTools

Rev

Rev 261 | Rev 335 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

########################################################################
# Copyright (C) 2008 ERG Limited, All rights reserved
#
# Module name   : ToolsetPrinter.pm
# Module type   : Perl Module
# Compiler(s)   : Perl
# Environment(s): jats
#
# Description   : Common toolset utils
#                 Toolset I/O stream for creating makefile rules and recipes
# Usage:
#
#       New         Create a new stream
#
#       Prt         Print a raw line
#
#       PrtLn       Print a raw line and a new line
#
#       Newline     Print a single new line
#
#       Tag         Tagged line print.
#
#       Cmd         Command line print, tagged with meta quoted and terminates.
#
#       SetTag      Set the "tag", default none.
#
#       SetTerm     Set the command line "terminator", default "\\n\n".
#
#       Label       Print generalised label
#
#       StartDef    Create a Definition
#       Def         Accumulate
#       EndDef      Print it out
#
#       ObjList     Generate a object list, using the specified recipe.
#
#       LibList     Generate a library list, using the specified recipe.
#
#       DepRules    Generate library dependency rules
#
###############################################################################

use strict;
use warnings;


package ToolsetPrinter;

sub New
{
    my ($tag, $cmdterm) = @_;

    $tag = "" if ( !defined($tag) );            # default tag
    $cmdterm = "\\n\n"                          # and terminator
        if ( !defined($cmdterm) );

    my ($self) = {
            TAG         => $tag,
            CMDTERM     => $cmdterm
        };
    return bless $self, __PACKAGE__;
}


sub Prt
{
    my ($self) = shift;
    ::MakePrint ("@_");
}

sub PrtLn
{
    my ($self) = shift;
    ::MakePrint ("@_\n");
}

sub Entry
{
    my ($self) = shift;
    ::MakeEntry( @_ );
}


sub Newline
{
    my ($self) = shift;
    ::MakePrint ("\n");
}


sub SetTag
{
    my ($self) = shift;
    my ($tag) = @_;

    $tag = "" if ( !defined($tag) );
    $self->{TAG} = $tag;
}


sub SetTerm
{
    my ($self) = shift;
    my ($cmdterm) = @_;

    $cmdterm = "\\n\n"                          # default terminator
        if ( !defined($cmdterm) );
    $self->{CMDTERM} = $cmdterm;
}


sub Cmd
{
    my ($self) = shift;
    ::MakeQuote ("$self->{TAG}\t+=@_$self->{CMDTERM}");
}


sub Tag
{
    my ($self) = shift;
    ::MakePrint ("$self->{TAG}\t+=@_\n");
}


sub Label
{
    my ($self) = shift;
    my ($desc, $target) = @_;

    $self->Prt( "#.. $desc ($target)\n\n" );
}


sub ObjList
{
    my ($self) = shift;
    my ($target, $objs, $genrecipe, @uargs) = @_;

    foreach (@$objs)
    {
        &$genrecipe( $self, $target, $_, @uargs );
    }
}

sub StartDef
{
    my ($self) = shift;
    my ($tag) = @_;

    $tag = "" if ( !defined($tag) );
    $self->{DEF} = $tag;
    $self->{DEFS} = [];
}

sub Def
{
    my ($self) = shift;
    push @{$self->{DEFS}}, "@_";
}

sub EndDef
{
    my ($self) = shift;
    ::MakeDefEntry ( $self->{DEF}, '=' , $self->{DEFS} );
    delete $self->{DEFS};
}


#private
sub CondParse
{
    my ($target, $cond) = @_;

    if ($cond =~ /^--ifdef=(.*)/) {             # .. ifdef XXX
        $cond = "ifdef $1";

    } elsif ($cond =~ /^--ifndef=(.*)/) {       # .. ifndef XXX
        $cond = "ifndef $1";

    } elsif ($cond =~ /^--ifdebug$/) {          # .. if DEBUG
        $cond = "ifeq \"\$(DEBUG)\" \"1\"";

    } elsif ($cond =~ /^--ifprod$/) {           # .. if PRODUCTION
        $cond = "ifeq \"\$(DEBUG)\" \"0\"";

    } elsif ($cond =~ /^--ifeq=(.*):(.*)$/) {   # .. ifeq XXXX:YYYY
        $cond = "ifeq \"\$($1)\" \"$2\"";

    } elsif ($cond =~ /^--ifneq=(.*):(.*)$/) {  # .. ifneq XXXX:YYYY
        $cond = "ifneq \"\$($1)\" \"$2\"";

    } else {                                    # .. unknown
        ::Error( "$target: unknown conditional construct '$cond'" );
        $cond = "";
    }
    return $cond;
}


#private
sub CondOpen
{
    my ($self) = shift;

    @{$self->{CONDSTACK}} = ();
}


#private
sub CondModify
{
    my ($self) = shift;
    my ($newstack) = @_;
    my ($oldstack) = \@{$self->{CONDSTACK}};
    my ($idx, $cond);

#   Diff the two stacks
#
    $idx = 0;
    while ( $idx <= $#$newstack &&
            $idx <= $#$oldstack &&
            $$newstack[$idx] eq $$oldstack[$idx] ) {
        $idx++;
    }

#   Pop diff
#
    while ($idx <= $#$oldstack) {
        $cond = pop @$oldstack;
        $self->Prt( "  " x ($#$oldstack+1) . "endif\n" );
    }

#   Push diff
#
    while ($idx <= $#$newstack) {
        $self->Prt( "  " x $idx . "$$newstack[$idx]\n" );
        $idx++;
    }

    @{$self->{CONDSTACK}} = @$newstack;
}


#private
sub CondClose
{
    my ($self) = shift;
    my (@newstack) = ();

    $self->CondModify( \@newstack );            # pop any stacked conditionals
}


sub LibList
{
    my ($self) = shift;
    my ($target, $libs, $genrecipe, @uargs) = @_;
    my (@cond, $t_cond) = ();

    $self->CondOpen();                          # open a conditional session

    foreach (@$libs)
    {
        if (/^--if/)                            # inlined conditionals
        {
            push @cond, $t_cond
                if (($t_cond = CondParse( $target, $_ )) ne "");
        }
        elsif (/^--/)                           # arguments
        {
            &$genrecipe( $self, $target, $_, @uargs );
        }
        else                                    # library
        {
            my (@args) = split( "\n\t\t", $_ ); # see makeif.pl
            my ($lib) = shift @args;

            #   Associated conditionals (if any)
            #
            foreach (@args) {
                push @cond, $t_cond
                    if (($t_cond = CondParse( $target, $_ )) ne "");
            }
            $self->CondModify( \@cond );        # modify
            @cond = ();

            #   Generate recipe
            #
            &$genrecipe( $self, $target, $lib, @uargs );
        }
    }
    $self->CondClose();                         # close session
}



sub SHLDDEPEND
{
    my ($self) = shift;
    my ($target, $base, $name, $dir) = @_;

    $self->Label( "Include Shared Library Dependency Rules", $target );
    $dir = "LIBDIR" unless ( defined $dir );

    $self->Prt( "
\$($dir)/${target}.dep:\tSHBASE=${base}
\$($dir)/${target}.dep:\tSHNAME=${name}
\$($dir)/${target}.dep:\t\$(GBE_$dir)
\$($dir)/${target}.dep:\t\$(SCM_MAKEFILE)
        \$(SHLDDEPEND)

ifneq \"\$(findstring \$(IFLAG),23)\" \"\"
-include\t\$($dir)/${target}.dep
endif

" );
}


sub LDDEPEND
{
    my ($self) = shift;
    my ($target, $dir) = @_;

    $self->Label( "Include Library Dependency Rules", $target );
    $dir = "BINDIR" unless ( defined $dir );

    $self->Prt( "
\$($dir)/${target}.dep:\t\$(GBE_$dir)
\$($dir)/${target}.dep:\t\$(SCM_MAKEFILE)
        \$(LDDEPEND)

ifeq \"\$(IFLAG)\" \"3\"
-include\t\$($dir)/${target}.dep
endif

" );
}


sub DepRules
{
    my ($self) = shift;
    my ($target, $libs, $librecipe, @uargs) = @_;

    unless ( $self->{DepRulesHeaderDone}{$target} )
    {
        $self->{DepRulesHeaderDone}{$target} = 1;

        $self->Label( "Dependencies", $target );    # label
                                                    # library depends
        $self->Tag( "\\# DO NOT REMOVE - dependencies\\\\n" );
        $self->Tag( "\\#\\\\n" );
    }

    $self->LibList( $target, $libs, $librecipe, @uargs );
}

1;