Author: particle
Date: Wed Jun 13 07:10:19 2007
New Revision: 18968

Added:
   branches/reconfigure/config/directives/
   branches/reconfigure/config/directives/configure.op
   branches/reconfigure/config/directives/core.op
   branches/reconfigure/config/directives/intro.op
   branches/reconfigure/config/directives/io.op
Modified:
   branches/reconfigure/Configure.pl
   branches/reconfigure/lib/Parrot/Configure.pm

Log:
[config]: refactoring Configure.pl
~ ability to pass in script files to direct configure process
  with more control than command-line options
~ ability to save different configurations (e.g. w/ & w/o icu)
~ this should also help support cross-compilation

Modified: branches/reconfigure/Configure.pl
==============================================================================
--- branches/reconfigure/Configure.pl   (original)
+++ branches/reconfigure/Configure.pl   Wed Jun 13 07:10:19 2007
@@ -281,83 +281,237 @@
 
 =cut
 
-use 5.006_001;
+use 5.008;
 use strict;
 use warnings;
-use Data::Dumper;
-$Data::Dumper::Indent = 1;
+
+use Carp;
+use Data::Dumper; $Data::Dumper::Indent = 1;
+
+use File::Basename qw( basename );
+use File::Spec::Functions qw( catdir catfile );
+use FindBin qw( $Bin );
+
+# used in tasks to find parrot libraries
 use lib 'lib';
 
-use Parrot::BuildUtil;
-use Parrot::Configure;
-use Parrot::Configure::Options qw( process_options );
-use Parrot::Configure::Options::Test;
-use Parrot::Configure::Messages qw(
-    print_introduction
-    print_conclusion
-);
-use Parrot::Configure::Step::List qw( get_steps_list );
-
-my $parrot_version = Parrot::BuildUtil::parrot_version();
-
-$| = 1; # $OUTPUT_AUTOFLUSH = 1;
-
-# Install Option text was taken from:
-#
-# autoconf (GNU Autoconf) 2.59
-# Written by David J. MacKenzie and Akim Demaille.
-#
-# Copyright (C) 2003 Free Software Foundation, Inc.
-# This is free software; see the source for copying conditions.  There is NO
-# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-# from Parrot::Configure::Options
-my $args = process_options( {
-    argv            => [ @ARGV ],
-    script          => $0,
-    parrot_version  => $parrot_version,
-    svnid           => '$Id$',
-} );
-exit unless defined $args;
-
-my $opttest = Parrot::Configure::Options::Test->new($args);
-# configuration tests will only be run if you requested them
-# as command-line option
-$opttest->run_configure_tests();
-
-# from Parrot::Configure::Messages
-print_introduction($parrot_version);
-
-my $conf = Parrot::Configure->new;
-
-# from Parrot::Configure::Step::List
-$conf->add_steps(get_steps_list());
-
-my %args = %{$args};
-# from Parrot::Configure::Data
-$conf->options->set(%args);
-
-if ( exists $args{step} ) {
-    # from Parrot::Configure::Data
-    $conf->data()->slurp();
-    # from Parrot::Configure
-    $conf->runstep( $args{step} );
-    print "\n";
-}
-else {
-    # Run the actual steps
-    # from Parrot::Configure
-    $conf->runsteps or exit(1);
-}
-
-# build tests will only be run if you requested them
-# as command-line option
-$opttest->run_build_tests();
 
-# from Parrot::Configure::Messages
-print_conclusion($conf->data->get('make'));
+main( @ARGV ) unless caller;
+
+
+sub main {
+    ## data store for directory operations
+    my $dirstack= [];
+
+    ## data store
+    ## TODO should this be backed by dbm::deep or something?
+    my $DS= {
+        DIRS       => $dirstack,
+        PARROT     => {
+            argv   => [ @ARGV ],
+            script => $0,
+            svnid  => '$Id$',
+        },
+        user       => {},
+    };
+
+    my $actions= {
+        include      => \&read_config,
+        define       => \&define_config_directive,
+        _DEFAULT_    => \&no_such_directive,
+        DUMP         => sub{ print Dumper [EMAIL PROTECTED] },
+    };
+
+    my $ddir= catdir $Bin, 'config', 'directives';
+
+    ## define io commands, which operate on the directory stack
+    read_config( catfile( $ddir, 'io.op'), $actions, $dirstack );
+
+    ## define commands which operate on the data store
+    for my $f (qw/ core intro /)
+    {
+        read_config( catfile( $ddir, $f . '.op'), $actions, $DS );
+    }
+
+    ## process the list of configure directives
+    ## TODO allow the --script=s option to override this
+    read_config( catfile( $ddir, 'configure.op' ), $actions, $DS );
+}
+
+
+
+exit;
+
+
+
+sub read_config
+{
+    my( $filename, $actions, $userparam )= @_;
+    open my($CF) => $filename
+        or carp $!;
+
+    LINE: while(<$CF>)
+    {
+        chomp;
+        ## skip blank lines and comments
+        next if m/^\s*$/ || m/\s*#/;
+
+        my( $directive, $rest )= split /\s+/ => $_, 2;
+
+        ## deal with heredocs
+        ## heredoc delimeters can be any non-space chars following '<<'
+        ## and optional spaces (eg. '<< %END!' or '<<DESC')
+        $rest= read_heredoc( $CF, $1, $filename )
+            if( $rest && $rest =~ m/^<< \s* (\S*)$/x );
+
+        ## resolve the action
+        ## first try user-defined, otherwise default
+        my $action= $actions->{$directive}
+            || $actions->{_DEFAULT_};
+        if( $action )
+        {
+            $action->( $directive, $rest, $actions, $userparam );
+        }
+        else
+        {
+            die "unrecognized directive '$directive'"
+                . " at line $. of $filename; aborting";
+        }
+    }
+    return 1;
+}
+
+
+sub read_heredoc
+{
+    my( $CF, $marker, $filename )= @_;
+    my $line_num= $.;
+
+    my $rest= '';
+    while( my $buffer= <$CF>)
+    {
+        die "runaway heredoc on line $line_num of $filename; aborting"
+            unless defined $buffer;
+        last if $buffer =~ m/^$marker$/;
+        $rest .= $buffer;
+    }
+    return $rest;
+}
+
+
+sub define_config_directive
+{
+    my( $directive, $rest, $dispatch )= @_;
+    $rest =~ s/^\s+//;
+    my( $new_directive, $def_text )= split /\s+/ => $rest, 2;
+
+    if( exists $dispatch->{$new_directive} )
+    {
+        warn "$new_directive already defined; skipping.\n";
+        return;
+    }
+
+    my $def= eval "sub { $def_text }";
+    if( not defined $def )
+    {
+        warn "could not compile definition for '$new_directive':"
+            . "$@; skipping.\n";
+        return;
+    }
+
+    $dispatch->{$new_directive}= $def;
+}
+
+
+## handles missing directives
+sub no_such_directive
+{
+    my( $directive )= @_;
+    $directive ||= ''; $. ||= 0;
+    warn "unrecognized directive '$directive' at line $.; ignoring.\n";
+}
+
+
+## XXX fix passed arguments processing... it defaults to space-sep which is 
wrong TODO
+sub process_opts
+{
+    require Parrot::Configure::Options;
+
+    my( $var, $val, undef, $stash )= @_;
+    my $args = Parrot::Configure::Options::process_options( {
+        argv            => [ defined $val ? $val : @ARGV ],
+        script          => $0,
+        parrot_version  => $stash->{PARROT}{parrot_version},
+        svnid           => '$Id$',
+    } );
+    # XXX really? just exit? it should give a friendly message
+    exit unless defined $args;
+
+    set_parrot_var( args => $args, undef, $stash );
+}
+
+
+## sets a parrot variable to a value
+sub set_parrot_var
+{
+    my( $var, $val, undef, $stash )= @_;
+    $stash->{PARROT}{$var}= $val;
+}
+
+
+## sets a user variable to a value
+sub set_user_var
+{
+    my( $var, $val, undef, $stash )= @_;
+    $stash->{user}{$var}= $val;
+}
+
+
+## sets a configuration variable to a value
+sub set_conf_var
+{
+    my( $var, $val, undef, $stash )= @_;
+    $stash->{user}{conf}->data->set($var, $val);
+}
+
+
+## gets a parrot variable
+sub get_parrot_var { $_[3]->{PARROT}{$_[0]} }
+
+
+## gets a user variable
+sub get_user_var { $_[3]->{user}{$_[0]} }
+
+
+## gets a value from the configuration
+sub get_conf_var { $_[3]->{user}{conf}->data->get($_[0]) }
+
+
+## resets all parrot variables
+sub reset_parrot_vars
+{
+    my( undef, undef, undef, $stash )= @_;
+    delete $stash->{PARROT};
+    $stash->{PARROT}= {};
+}
+
+
+## resets all user variables
+sub reset_user_vars
+{
+    my( $var, undef, undef, $stash )= @_;
+    delete $stash->{user};
+    $stash->{user}= {};
+}
+
+
+## quit
+sub quit { exit 0 }
+
+
+$_ ^=~ { AUTHOR => 'particle' };
+
 
-exit(0);
 
 ################### DOCUMENTATION ###################
 

Added: branches/reconfigure/config/directives/configure.op
==============================================================================
--- (empty file)
+++ branches/reconfigure/config/directives/configure.op Wed Jun 13 07:10:19 2007
@@ -0,0 +1,84 @@
+## get the parrot version (or override it by passing an optional value)
+parrot_version
+
+## here i'm overriding the command-line vars passed to Configure.pl
+process_opts --test=configure
+
+## that will cause this op to run, since $args{test} eq 'configure'
+test configure
+
+## print the intro
+introduction
+
+## TODO do we really want this here, or should it exist by default?
+configure_new
+configure_set_args
+
+## run the configuration steps
+run init::manifest
+run init::defaults
+run init::install
+run init::miniparrot
+run init::hints
+run init::headers
+run inter::progs
+run inter::make
+run inter::lex
+run inter::yacc
+run auto::gcc
+run auto::msvc
+run init::optimize
+run inter::shlibs
+run inter::libparrot
+run inter::charset
+run inter::encoding
+run inter::types
+run inter::ops
+## pass options to a specific config step
+run inter::pmc --ask
+run auto::alignptrs
+run auto::headers
+run auto::sizes
+run auto::byteorder
+run auto::va_ptr
+run auto::pack
+run auto::format
+run auto::isreg
+run auto::jit
+run gen::cpu
+run auto::funcptr
+run auto::cgoto
+run auto::inline
+run auto::gc
+run auto::memalign
+run auto::signal
+run auto::socklen_t
+run auto::env
+run auto::aio
+run auto::gmp
+run auto::readline
+run auto::gdbm
+run auto::snprintf
+run auto::perldoc
+## look, i can easily disable one or more config steps now
+#run auto::python
+#run auto::m4
+run auto::cpu
+run gen::icu
+run gen::revision
+run gen::config_h
+run gen::core_pmcs
+run gen::parrot_include
+run gen::languages
+run gen::makefiles
+run gen::platform
+run gen::config_pm
+
+
+test build
+
+conclusion
+
+## dump the entire structure at any time for easy debugging
+#DUMP
+

Added: branches/reconfigure/config/directives/core.op
==============================================================================
--- (empty file)
+++ branches/reconfigure/config/directives/core.op      Wed Jun 13 07:10:19 2007
@@ -0,0 +1,118 @@
+## ezcli core commands
+
+# set the parrot version to the value in the VERSION file
+# override the default behavior by passing in a value
+#   e.g. "parrot_version a.b.c"
+define <<PARROT_VERSION
+parrot_version
+    require Parrot::BuildUtil;
+    my( $var, $val, $actions, $stash )= @_;
+    set_parrot_var(
+        parrot_version => $val || scalar &Parrot::BuildUtil::parrot_version(),
+        $actions, $stash
+    );
+PARROT_VERSION
+
+
+# process command-line options
+# this is defined in Configure.pl for now
+# since it's easier to get some variable values there
+define process_opts    &process_opts
+
+
+# create the configure object
+define <<CONFIGURE_NEW
+configure_new
+    require Parrot::Configure;
+    set_user_var( conf => Parrot::Configure->new, @_[2,3] );
+CONFIGURE_NEW
+
+
+# add the command-line options to the configure object
+define <<CONFIGURE_SET_ARGS
+configure_set_args
+    my( $var, $val, undef, $stash )= @_;
+    my $conf = $stash->{user}{conf};
+    $conf->options->set( %{$stash->{PARROT}{args}} );
+CONFIGURE_SET_ARGS
+
+
+# add steps to perform during configure
+# XXX params are space-separated now, make sure this is okay
+# CURRENTLY UNUSED, see 'run'
+define <<ADD_STEP
+add_step
+    my( $var, $val, undef, $stash )= @_;
+    my $conf = $stash->{user}{conf};
+    my( $step, @params )= split /\s+/ => $val;
+    $conf->add_step($step, @params);
+ADD_STEP
+
+
+# add the command-line options to the configure object
+# CURRENTLY UNUSED, see 'run'
+define <<CONFIGURE_RUN
+configure_run
+    my( $var, $val, undef, $stash )= @_;
+    my $conf = $stash->{user}{conf};
+    my $args = $stash->{PARROT}{args};
+    my %args = %$args;
+
+    if ( exists $args{step} ) {
+        # from Parrot::Configure::Data
+        $conf->data()->slurp();
+        # from Parrot::Configure
+        $conf->runstep( $args{step} );
+        print "\n";
+    }
+    else {
+        # Run the actual steps
+        # from Parrot::Configure
+        $conf->runsteps or exit(1);
+    }
+CONFIGURE_RUN
+
+
+# add a step to the configure process and run it
+# XXX params are space-separated now, make sure this is okay
+# XXX it seems --step=foo is broken! TODO
+define <<RUN
+run
+    my( $var, $val, undef, $stash )= @_;
+    my $conf = $stash->{user}{conf};
+    my $args = $stash->{PARROT}{args};
+    my %args = %$args;
+
+    my( $step, @params )= split /\s+/ => $val;
+
+    if( exists $args{step} ) {
+        return unless $args{step} eq $step;
+    }
+
+    $conf->add_step($step, @params);
+#    $conf->data()->slurp();
+    $conf->runstep( $step );
+RUN
+
+
+# testing directives
+define <<TEST
+test
+    require Parrot::Configure::Options::Test;
+    my( $var, $val, undef, $stash )= @_;
+    my $args = $stash->{PARROT}{args};
+    my $opttest = Parrot::Configure::Options::Test->new($args);
+    # tests will only be run if you requested them
+    # as command-line option
+    my $method = 'run_' . $_[1] . '_tests';
+    $opttest->$method();
+TEST
+
+
+# XXX this is for debugging
+define reset_parrot    &reset_parrot_vars
+define reset_user      &reset_user_vars
+
+
+# TODO write a 'script' task to pass in a script to execute
+# this will help support cross-compilation and multiple configurations

Added: branches/reconfigure/config/directives/intro.op
==============================================================================
--- (empty file)
+++ branches/reconfigure/config/directives/intro.op     Wed Jun 13 07:10:19 2007
@@ -0,0 +1,23 @@
+## introduction and conclusion commands
+
+define <<INTRODUCTION
+introduction
+    require Parrot::Configure::Messages;
+    my( $var, $val, undef, $stash )= @_;
+    Parrot::Configure::Messages::print_introduction(
+        $stash->{PARROT}{parrot_version}
+    );
+INTRODUCTION
+
+define <<CONCLUSION
+conclusion
+    require Parrot::Configure::Messages;
+    my( $var, $val, undef, $stash )= @_;
+    my $conf = $stash->{user}{conf};
+    Parrot::Configure::Messages::print_conclusion(
+        $conf->data->get('make')
+    );
+CONCLUSION
+
+
+## vim: expandtab sw=4

Added: branches/reconfigure/config/directives/io.op
==============================================================================
--- (empty file)
+++ branches/reconfigure/config/directives/io.op        Wed Jun 13 07:10:19 2007
@@ -0,0 +1,30 @@
+## io-related commands
+
+## printing
+define say       defined $_[1] ? print STDOUT $_[1], $/ : print $/
+define print     defined $_[1] ? print STDOUT $_[1] : 1
+define printerr  defined $_[1] ? print STDERR $_[1]  : 1
+
+## changing dirs
+define <<PUSHDIR
+pushdir
+    use Cwd; use File::Spec::Functions;
+    push @{$_[3]} => canonpath(cwd);
+    chdir canonpath $_[1]
+PUSHDIR
+define popdir chdir pop @{$_[3]};
+
+## debugging
+define <<DUMP
+dump
+    use Data::Dumper;
+    $Data::Dumper::Indent= 1;
+    print Data::Dumper->Dump( [ $_[3]->{$_[1]} ], [ $_[1] ] );
+DUMP
+
+## XXX - not working
+## quit
+define quit          &quit;
+
+
+## vim: expandtab sw=4

Modified: branches/reconfigure/lib/Parrot/Configure.pm
==============================================================================
--- branches/reconfigure/lib/Parrot/Configure.pm        (original)
+++ branches/reconfigure/lib/Parrot/Configure.pm        Wed Jun 13 07:10:19 2007
@@ -211,7 +211,7 @@
     my ( $verbose, $verbose_step, $ask ) = $self->options->get(qw(verbose 
verbose-step ask));
 
     for my $task ( $self->steps() ) {
-        print STDERR $task->{"Parrot::Configure::Task::step"}, "\n"; 
+#        print STDERR $task->{"Parrot::Configure::Task::step"}, "\n"; 
         if ( $task->{"Parrot::Configure::Task::step"} eq $taskname ) {
             $self->_runstep( $task, $verbose, $verbose_step, $ask, 1 );
         }

Reply via email to