The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Module::Build::Functions::DSL;

use strict;
use vars qw( $VERSION );

BEGIN {
	$VERSION = '0.04';

	*inc::Module::Build::Functions::DSL::VERSION = *VERSION;
	@inc::Module::Build::Functions::DSL::ISA     = __PACKAGE__;
}

sub import {
	my $package = shift;

	# Read in the rest of the Makefile.PL
	open 0 or die "Couldn't open $0: $!";
	my $dsl;
    SCOPE: {
		local $/ = undef;
		$dsl = join "", <0>;
	}

	# Change inc::Module::Build::Functions::DSL to the regular one.
	# Remove anything before the use inc::... line.
	$dsl =~ s/.*?^\s*use\s+(?:inc::)?$package(\b[^;]*);\s*\n//sm;

	# Stripping leading prefix
	$package =~ s/^\Qinc\E:://;


	my $code = $package->get_header_code(@_);

	# Execute the header code
	if (ref $code eq 'CODE') {
    	eval { &$code() }
	} else {
	    eval $code
	}
	print STDERR "Failed to execute the generated code: $@" if $@;

	# Add the DSL plugin to the list of packages in /inc
	Module::Build::Functions::copy_package($package);

	# Convert the basic syntax to code
	$code = "package main;\n\n" . dsl2code($dsl) . "\n\nWriteAll();\n";

	# Execute the script
	eval $code;
	print STDERR "Failed to execute the generated code: $@" if $@;

	exit(0);
} ## end sub import


sub get_header_code {
    my ($self, @import_params) = @_;
    

    # Load inc::Module::Build::Functions as we would in a regular Makefile.Pl
	return sub {
        package main;
        
        require inc::Module::Build::Functions;
        inc::Module::Build::Functions->import(@import_params);
	}
}


sub dsl2code {
	my $dsl = shift;

	# Split into lines and strip blanks
	my @lines = grep {/\S/} split /[\012\015]+/, $dsl;

	# Each line represents one command
	my @code = ();
	foreach my $line (@lines) {

		# Split the lines into tokens
		my @tokens = split /\s+/, $line;

		# The first word is the command
		my $command = shift @tokens;
		my @params  = ();
		my @suffix  = ();
		while (@tokens) {
			my $token = shift @tokens;
			my $next_token;
			my $token_quoted;

			if ( $token =~ /^(\'|\")/ ) {
				$token_quoted = 1;

				if ( $token !~ /(\'|\")$/ ) {
					do {
						$next_token = shift @tokens;

						$token .= ' ' . $next_token if $next_token;

					} while ( $next_token && $next_token !~ /(\'|\")$/ );
				}
			} ## end if ( $token =~ /^(\'|\")/)

			if ( $token eq 'if' or $token eq 'unless' ) {

				# This is the beginning of a suffix
				push @suffix, $token;
				push @suffix, @tokens;
				last;
			} else {

				# Convert to a string
				$token =~ s/([\\\'\"])/\\$1/g unless $token_quoted;
				push @params, $token_quoted ? $token : "'$token'";
			}
		} ## end while (@tokens)

		# Merge to create the final line of code
		@tokens =
		  ( $command, @params ? join( ', ', @params ) : (), @suffix );
		push @code, join( ' ', @tokens ) . ";\n";
	} ## end foreach my $line (@lines)

	# Join into the complete code block
	return join( '', @code );
} ## end sub dsl2code

1;