#! /usr/bin/perl

=head1 NAME

bootstrap-perl - Bootstrap Perl inclusive CPAN from git

=head1 ABOUT

The script B<bootstrap-perl> bootstraps Perl installations with
complete CPAN environment, inclusive distroprefs, from git.

It was originally developed to be used by
L<Benchmark::Perl::Formance|Benchmark::Perl::Formance> and now lives
on its own.

It should work for Perl versions from 5.8.6 to blead. Occasionally it
cherry-picks a very few patches to fix some known build issues, like
for 5.8.x.

=head1 SYNOPSIS

Install a threaded 64bit Perl using current "blead"
from git with CPAN config into a path like
C</opt/perl-5.15-thread-64bit-v5.15.5-258-ge7d0a3f>:

  $ bootstrap-perl

=head2 Specify git revisions

=head3 latest "blead"

  $ bootstrap-perl --version blead  # same as default

=head3 tag

  # note the different tag forms before and after Perl 5.10

  $ bootstrap-perl --version perl-5.8.7
  $ bootstrap-perl --version v5.14.1

=head3 branch name

  $ bootstrap-perl --version remotes/origin/smoke-me/cpan
  $ bootstrap-perl --version remotes/origin/zefram/pad_api
  $ bootstrap-perl --version remotes/origin/maint-5.12
  $ bootstrap-perl --version remotes/origin/maint-5.12^
  $ bootstrap-perl --version remotes/origin/maint-5.12~3

=head3 by commit id

  $ bootstrap-perl --version c14f2f9db08de3f50fe2ff7438429153d6ceb9a5
  $ bootstrap-perl --version c14f2f9db08de3f50fe2ff7438429153d6ceb9a5^

=head2 Installation options

=head3 install directory

Install into other install directory than the unified naming schema
(see below for more on this schema):

  $ bootstrap-perl --prefix <PREFIX>

Use the unified naming schema but not under C</opt>:

  $ bootstrap-perl --prefixbase /foo/bar

=head3 install build dependencies

Provide the distro for which to install known build dependencies, like
gcc, git, make, etc.:

 $ bootstrap-perl --installdeps=debian

Currently there is only one: C<debian>. Simply send me a patch for
your preferred distro, it's easy.

=head3 parallel build

Use this many parallel jobs to build:

  $ bootstrap-perl --jobs <n>
  $ bootstrap-perl -j <n>

Default is to use core count + 1.

=head3 test

Run the perl test suite:

  $ bootstrap-perl --test
  $ bootstrap-perl -t

Default is B<not> to run the tests.

=head3 use threads

Build a threaded Perl (C<-Dusethreads>):

  $ bootstrap-perl --usethreads

which is already the default. To build non-threaded Perl use:

  $ bootstrap-perl --nousethreads

=head3 use 64bit

Build a 64bit enabled Perl (C<-Duse64bitall>):

  $ bootstrap-perl --use64bit

which is already the default. To build Perl without 64bit use:

  $ bootstrap-perl --nouse64bit

=head3 configure CPAN and modules

Configure CPAN to use these mirrors:

  $ bootstrap-perl --mirror file:///home/ss5/MINICPAN/
  $ bootstrap-perl -m file:///home/ss5/MINICPAN/ -m ftp://ftp.rub.de/pub/CPAN/
  $ bootstrap-perl -m file:///home/ss5/MINICPAN/,ftp://ftp.rub.de/pub/CPAN/

(Option can be repeated and allow comma separated lists.)

Install these modules from CPAN:

  $ bootstrap-perl --module YAML::Syck
  $ bootstrap-perl -M YAML::Syck -M Digest::SHA1 -M IO::Tty -M LWP
  $ bootstrap-perl -M YAML::Syck,Digest::SHA1 -M IO::Tty,LWP

(Option can be repeated and allow comma separated lists.)

=head3 run scripts

Run these scripts relative to built <PREFIX>/bin/:

  $ bootstrap-perl --run tapper-testsuite-benchmark-perlformance
  $ bootstrap-perl --run tapper-testsuite-benchmark-perlformance --runargs="--plugins=ALL"
  $ bootstrap-perl -r tapper-testsuite-benchmark-perlformance -r primes.pl

(Option can be repeated and allow comma separated lists.)

=head2 Unified installation prefix schema

It uses a unified naming schema for it's installation PREFIX:

  /opt/perl-5.<VERSION>-<(no)?thread>-<(no)?64bit>-<git-describe>

which leads to paths like this:

  /opt/perl-5.10-thread-64bit-v5.10.0
  /opt/perl-5.15-thread-64bit-v5.15.5-258-ge7d0a3f

This naming schema consist of the major version, basic configuration
and I<git-describe>.

=head2 Meta info utilities

To easily provide the raw I<git-describe> a script is put inside each
install

  perl-gitversion

which prints the I<git-describe> of that installation.

Another script

  perl-codespeed-executable

is put inside each install which prints a so called "executable name"
for this built perl used on a codespeed instance like
L<http://speed.perlformance.net|http://speed.perlformance.net>. Although
this is unlikely to be useful for others it is always created.

These two utility scripts B<could> be derived from the install prefix
but also work when you provided your own prefix.

=head1 AUTHOR

Steffen Schwigon, C<< <ss5 at renormalist.net> >>

=head1 COPYRIGHT & LICENSE

Copyright 2011 Steffen Schwigon, all rights reserved.

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=cut

use strict;
use warnings;

use Getopt::Long ":config", "no_ignore_case", "bundling";

my $HOME                = $ENV{HOME};

my $build_path          = "/tmp/bootstrap-perl-build";
my $build_path_perl     = "$build_path/perl";
my $giturl              = "git://github.com/mirrors/perl.git";

my $cpucount             = `cat /proc/cpuinfo | grep bogomips | wc -l`; chomp $cpucount;
my $threadcount          = $cpucount + 1;

# getopt
my $dry;
my $prefix;
my $prefixbase          = "/opt";
my $version             = "blead";
my $installdeps;
my $sourcetgz           = "/var/tmp/perl.tar.gz";
my $usethreads          = 1;
my $bit64               = 1;
my $help                = 0;
my $test                = 0;
my $jobs                = $threadcount;
my @mirrors;
my @modules;
my @runscripts;
my @runargs             = ();

my $DISTROPREFSREPO     = "git://github.com/renormalist/cpanpm-distroprefs.git";
my $DISTROPREFSSRCBASE  = "$build_path";
my $DISTROPREFSSRC1     = "$DISTROPREFSSRCBASE/cpanpm-distroprefs/cpanpm/distroprefs";
my $DISTROPREFSSRC2     = "$DISTROPREFSSRCBASE/cpanpm-distroprefs/renormalist/distroprefs";
my $DISTROPREFSURL      = 'http://cpansearch.perl.org/src/ANDK/CPAN-1.9800/distroprefs/';
my $DISTROPREFSDIR      = $prefixbase."/cpan/prefs"; # TODO: CPAN-Config is hardwired, not yet aware of $prefixbase!

# Perl::Formance modules and some explicit dependencies
my @default_modules = (qw( ));

# http://perlformance.net/CPAN/
my @default_mirrors = (qw(
                         http://rub.de/ftp/pub/CPAN/
                        ));

sub print_and_system {
        my ($cmd) = @_;
        print $cmd."\n";
        system ($cmd);
}

sub print_and_qx {
        my ($cmd) = @_;
        print $cmd."\n";
        qx($cmd);
}

sub _perl_base_name {
        my ($perl_revision, $perl_version, $perl_subversion, $usethreads, $bit64, $gitversion, $exe_suffixes) = @_;
        return join("-",
                    "$perl_revision.$perl_version",
                    ($usethreads ? "" : "no" )."thread",
                    ($bit64      ? "" : "no" )."64bit",
                    @$exe_suffixes,
                   );
}

sub _perl_exe_name {
        my ($perl_revision, $perl_version, $perl_subversion, $usethreads, $bit64, $gitversion, $exe_suffixes) = @_;

        return join("-",
                    "perl",
                    _perl_base_name(@_),
                   );
}

sub _perl_pathprefix {
        my ($perl_revision, $perl_version, $perl_subversion, $usethreads, $bit64, $gitversion, $exe_suffixes) = @_;

        return join("-",
                    $prefixbase."/perl",
                    _perl_base_name(@_),
                    $gitversion,
                   );
}

# ========== getopt ==========

print "\n";
print "============================================================\n";
print "Bootstrap Perl\n";
print "============================================================\n";

my $ok = GetOptions (
                     "prefix=s"     => \$prefix,
                     "prefixbase=s" => \$prefixbase,
                     "version=s"    => \$version,
                     "installdeps=s" => \$installdeps,
                     "sourcetgz=s"  => \$sourcetgz,
                     "usethreads!"  => \$usethreads,
                     "use64bit!"    => \$bit64,
                     "help|h"       => \$help,
                     "jobs|j=i"     => \$jobs,
                     "test|t"       => \$test,
                     'dry|n'        => \$dry,
                     'mirror|m=s@'  => \@mirrors,
                     'module|M=s@'  => \@modules,
                     'run|r=s@'     => \@runscripts,
                     'runargs=s@'   => \@runargs,
                     'giturl=s'     => \$giturl,
                    );

if ($help) {
        print "\nPlease see 'perldoc bootstrap-perl' for help.\n";
        exit 0;
}

# modules/mirros can be comma-separated
my @MODULES     = map { chomp; $_ } map { split(qr/,/, $_) } (@modules ? @modules : @default_modules);
my @CPANMIRRORS = map { chomp; $_ } map { split(qr/,/, $_) } (@mirrors ? @mirrors : @default_mirrors);
my @RUNSCRIPTS  = map { chomp; $_ } map { split(qr/,/, $_) } (@runscripts ? @runscripts : ());

# ========== build dependencies ==========

sub installdeps_debian
{
        my $APTGETOPTIONS ='-o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --yes';
        my $APTGET        = "DEBIAN_FRONTEND=noninteractive; export DEBIAN_FRONTEND ; sudo apt-get $APTGETOPTIONS";
        my @DEPENDECIES   = (qw(make
                                patch
                                makepatch
                                curl
                                wget
                                rsync
                                gcc
                                g++
                                git
                                perl-modules
                                libbz2-1.0
                                libbz2-dev
                                libdb-dev
                                libsqlite3-dev
                                linux-source
                                libgmp3-dev
                              ));
        foreach my $dep (@DEPENDECIES) {
                print_and_system "$APTGET install $dep\n";
        }
}

if ($installdeps) {
        my @SUPPORTED_DISTROS = (qw(debian));
        if (grep { /$installdeps/ } @SUPPORTED_DISTROS) {
                print "Install dependencies for: $installdeps\n";
                eval "installdeps_$installdeps()";
        } else {
                print "Unsupported dependency installation for distro: $installdeps\n";
                print "Allowed distros: ".join(", ", @SUPPORTED_DISTROS), "\n";
                exit 1;
        }
                
}

# ========== prepare ==========

my @EXE_SUFFIXES = sort split /\s+/, $ENV{CODESPEED_EXECUTABLE_SUFFIXES} || "";

print_and_system "mkdir -p $build_path";

if ( not $build_path_perl && -e $build_path_perl ) {
        if (-e $sourcetgz)
        {
                print_and_system "cd $build_path ; tar xzf $sourcetgz";
        } else {
                print_and_system "cd $build_path ; git clone $giturl";
        }
}

chdir "$build_path_perl"; # important, I don't remember for what below
print_and_system "cd $build_path_perl ; rm -f $build_path_perl/.git/index.lock";
print_and_system "cd $build_path_perl ; git reset --hard";
print_and_system "cd $build_path_perl ; git clean -dxf";
print_and_system "cd $build_path_perl ; git checkout blead";
print_and_system "cd $build_path_perl ; git pull";
print_and_system "cd $build_path_perl ; git checkout $version";
print_and_system "cd $build_path_perl ; git pull";

# cherry pick several bugfixes in 5.8.8 that break building
if ($version =~ /5\.8\./ or $version =~ /5\.9\.0/) {
        # use temp branch
	my $localfixes = "bootstrap-perl-local-fixes";
        print_and_system "cd $build_path_perl ; git branch -D $localfixes ; git checkout -b $localfixes";
        # FIX: <command-line>
        print_and_system qq!cd $build_path_perl ; git cherry-pick cf14425e2bd169ce935f76d359f3253b51e441a0!;
        # FIX: rebuild / gcc -g
        print_and_system qq!cd $build_path_perl ; git cherry-pick a3d1be69db4c082c1b9cef14f51a6e7fe4a9dac9!;
        # FIX: makedepend.SH
        print_and_system qq!cd $build_path_perl ; git cherry-pick 96a8704c85b1e14bb3d63195b0b720f2fd5b8182!;
        # FIX: create missing link (5.8.8)
        print_and_system q'sudo ln -sf `find  /usr/src -name page.h | grep arch/x86/include/asm/page.h | tail -1` /usr/include/asm/'  if ! -e "/usr/include/asm/page.h";
}

# ========== prepare paths ==========

my $gitversion           = print_and_qx qq!cd $build_path_perl ; git describe!; chomp $gitversion;
my ($perl_revision, $perl_version, $perl_subversion) = $gitversion =~ m/^\D*(\d+)[._](\d+)(?:[._](\d+))?.*$/g;
$perl_subversion ||= 0;

print "\n";
print "============================================================\n\n";
print "  Bootstrap Perl\n";
print "  --------------\n\n";
print "  version:        $version\n\n";
print "  git-describe:   $gitversion\n\n";
print "  CPAN mirrors:   ".join("\n                  ", @CPANMIRRORS)."\n\n";
print "  modules:        ".join("\n                  ", @MODULES)."\n\n";
print "  scripts:        ".join("\n                  ", map { $_ ." ".join(" ", @runargs) } @RUNSCRIPTS)."\n\n";
print "============================================================\n\n";

unless (defined $perl_revision && defined $perl_version)
{
        no warnings 'uninitialized';
        print "# Bummer! Unrecognized version schema ($gitversion).\n";
        print "# ($perl_revision, $perl_version, $perl_subversion)\n";
        exit 1;
}

my $codespeed_executable =            _perl_exe_name  ($perl_revision, $perl_version, $perl_subversion, $usethreads, $bit64, $gitversion, \@EXE_SUFFIXES);
my $PREFIX               = $prefix || _perl_pathprefix($perl_revision, $perl_version, $perl_subversion, $usethreads, $bit64, $gitversion, \@EXE_SUFFIXES);
my $USETHREADS           = $usethreads ? "-Dusethreads"  : "";
my $BIT64                = $bit64      ? "-Duse64bitall" : "";

$ENV{PERL_AUTOINSTALL} = "--defaultdeps";
$ENV{TEST_JOBS}        = $threadcount;
$ENV{TWMC_TEST_PORT}   = "9876";

my $perl_gitversion = "$PREFIX/bin/perl-gitversion";
my $perl_codespeed = "$PREFIX/bin/perl-codespeed-executable";

my $THREADS = $jobs ? "-j $jobs" : "-j $threadcount";
my $DRY = $dry ? "-n" : "";

# ========== build ==========

if (! -e $perl_gitversion and ! -e $perl_codespeed)
{
        # ========== configure ==========

        print_and_system "cd $build_path_perl; sh Configure -de -Dusedevel $USETHREADS $BIT64 -Dprefix=$PREFIX";


        # ========== make ==========

        print_and_system "cd $build_path_perl; make $THREADS";

        if ($test)
        {
                my $api_version = `cd $build_path_perl; . ./config.sh ; echo \$api_version`;
                chomp $api_version;

                my $TEST = $api_version >= 11 ? "test_harness" : "test"; # only Perl 5.11+
                my $TEST_JOBS = $jobs ? "TEST_JOBS=$jobs" : "TEST_JOBS=$threadcount";
                print_and_system "cd $build_path_perl; $TEST_JOBS make $TEST";
        }


        # ========== install ==========

        print_and_system "cd $build_path_perl; make $DRY install";

}

# ========== perlformance utils ==========

# create a binary that prints git version
if (open my $PERLGITVERSION, ">", $perl_gitversion)
{
        print $PERLGITVERSION sprintf(qq{#! /usr/bin/env perl\n\nprint '%s'."\n";}, $gitversion);
        print_and_system "chmod ugo+x $perl_gitversion";
        close $PERLGITVERSION;
}

# create a binary that prints sensible executable name for codespeed
if (open my $PERLCODESPEED, ">", $perl_codespeed)
{
        print $PERLCODESPEED sprintf(qq{#! /usr/bin/env perl\n\nprint '%s'."\n";}, $codespeed_executable);
        print_and_system "chmod ugo+x $perl_codespeed";
        close $PERLCODESPEED;
}

# binaries
my $CPAN     = print_and_qx qq!ls -drt1 $PREFIX/bin/cpan5.*.*     | tail -1!; chomp $CPAN;
my $PERL     = print_and_qx qq!ls -drt1 $PREFIX/bin/perl5.*.*     | tail -1!; chomp $PERL;
my $PERLDOC  = print_and_qx qq!ls -drt1 $PREFIX/bin/perldoc5.*.*  | tail -1!; chomp $PERLDOC;
my $POD2TEXT = print_and_qx qq!ls -drt1 $PREFIX/bin/pod2text5.*.* | tail -1!; chomp $POD2TEXT;

print "# CPAN:     $CPAN\n";
print "# PERL:     $PERL\n";
print "# PERLDOC:  $PERLDOC\n";
print "# POD2TEXT: $POD2TEXT\n";

# some dists don't find the versioned developer files
print_and_system "ln -sf $PERL     $PREFIX/bin/perl";
print_and_system "ln -sf $CPAN     $PREFIX/bin/cpan";
print_and_system "ln -sf $PERLDOC  $PREFIX/bin/perldoc";
print_and_system "ln -sf $POD2TEXT $PREFIX/bin/pod2text";

# ========== cpan ==========

# distroprefs: get all from git
print_and_system "mkdir -p $DISTROPREFSSRCBASE";
print_and_system "cd $DISTROPREFSSRCBASE ; git clone $DISTROPREFSREPO";
print_and_system "cd $DISTROPREFSSRCBASE/cpanpm-distroprefs ; git pull";
print_and_system "cd $DISTROPREFSSRCBASE/cpanpm-distroprefs ; git submodule update --init --recursive";
print_and_system "cd $DISTROPREFSSRCBASE/cpanpm-distroprefs ; git pull";
# distroprefs: merge our flavour
print_and_system qq!mkdir -p $DISTROPREFSDIR!;
print_and_system qq!rsync -r $DISTROPREFSSRC1/ $DISTROPREFSDIR/!;
print_and_system qq!rsync -r $DISTROPREFSSRC2/ $DISTROPREFSDIR/!;

# Configure CPAN initially
my $CFG = print_and_qx qq!$PERLDOC -l CPAN | sed -e "s/CPAN\.pm/CPAN\\/Config.pm/"!; chomp $CFG;

if (! -e $CFG) {
        my $CPANCFG = do { local $/; <DATA> };
        my $MIRRORSLIST = join(" ", @CPANMIRRORS);
        $CPANCFG =~ s/__DISTROPREFSDIR__/$DISTROPREFSDIR/;
        $CPANCFG =~ s/__MIRRORS__/$MIRRORSLIST/;
        open CPANCFG, ">", $CFG or die "Can not create $CFG";
        print CPANCFG $CPANCFG;
        close CPANCFG;
}

# remove stale cpan lock
my $cpanlock = "$prefixbase/cpan/.lock";
if (-e $cpanlock) {
	my ($pid, $host) = qx!cat $cpanlock!;
	chomp $pid;
	my $exists = kill 0, $pid;
	if (not $exists) {
		print "Remove stale CPAN.pm lock.\n";
		print_and_system qq!rm -f $cpanlock!;
	}
}

# force a CPAN.pm with all features we need
print_and_system qq{if ! $PERL -M"CPAN 1.98" -e1 ; then echo "force install CPAN" | $PERL -MCPAN -e shell ; fi };

# configure
print_and_system qq!echo "o conf auto_commit 1 ; o conf commit"                     | $PERL -MCPAN -e shell!;

# once upon a time the cpan exe missed the executable bit - set it to be sure
print_and_system qq!chmod +x $CPAN!;

# install extended cpan toolchain; contains some "force" where we know they are really required
print_and_system qq! echo "install YAML"                      | $PERL -MCPAN -e shell!;
print_and_system qq{if ! $PERL -MYAML -e1 ;         then echo "force install YAML"         | $PERL -MCPAN -e shell ; fi };
print_and_system qq{if ! $PERL -MIO::Compress::Base -e1 ; then echo "force install IO::Compress::Base" | $PERL -MCPAN -e shell ; fi };
if ($gitversion =~ /perl-5\.8\.0/) {
        # ignore known failing tests
	print_and_system qq! echo "force install Module::Build" | $PERL -MCPAN -e shell!;
}
if ($gitversion =~ /perl-5\.15\./) {
        # ignore known failing tests
	print_and_system qq! echo "force install Devel::Size" | $PERL -MCPAN -e shell!;
}
print_and_system qq! echo "force install version"             | $PERL -MCPAN -e shell!;
print_and_system qq! echo "install CPAN::SQLite"              | $PERL -MCPAN -e shell!;
print_and_system qq! echo "install YAML::Syck"                | $PERL -MCPAN -e shell!;
print_and_system qq! echo "install IO::Tty"                   | $PERL -MCPAN -e shell!;
print_and_system qq! echo "install Expect"                    | $PERL -MCPAN -e shell!;
print_and_system qq! echo "install Bundle::CPAN"              | $PERL -MCPAN -e shell!;
print_and_system qq! echo "install LWP"                       | $PERL -MCPAN -e shell!;

# install modules from CPAN
foreach my $module (@MODULES) {
        print_and_system qq!$CPAN $module!;
}

# Run scripts from inside the just installed Perl
foreach my $runscript (@RUNSCRIPTS) {
        print_and_system qq!$PREFIX/bin/$runscript !.join(" ", @runargs);
}
# print_and_system qq!$PREFIX/bin/tapper-testsuite-benchmark-perlformance!;

__DATA__

# This is CPAN.pm's systemwide configuration file. This file provides
# defaults for users, and the values can be changed in a per-user
# configuration file. The user-config file is being looked for as
# ~/.cpan/CPAN/MyConfig.pm.

$CPAN::Config = {
  'auto_commit' => q[1],
  'build_cache' => q[10],
  'build_dir' => q[/opt/cpan/build],
  'build_dir_reuse' => q[0],
  'build_requires_install_policy' => q[yes],
  'cache_metadata' => q[0],
  'check_sigs' => q[0],
  'colorize_debug' => q[bold cyan],
  'colorize_output' => q[1],
  'colorize_print' => q[bold blue],
  'colorize_warn' => q[bold red],
  'commandnumber_in_prompt' => q[0],
  'connect_to_internet_ok' => q[0],
  'cpan_home' => q[/opt/cpan],
  'dontload_hash' => {  },
  'ftp' => q[/usr/bin/ftp],
  'patch' => q[/usr/bin/patch],
  'ftp_passive' => q[1],
  'ftp_proxy' => q[],
  'getcwd' => q[cwd],
  'gpg' => q[/usr/bin/gpg],
  'gzip' => q[/bin/gzip],
  'halt_on_failure' => q[0],
  'histfile' => q[/opt/cpan/histfile],
  'histsize' => q[100],
  'http_proxy' => q[],
  'inactivity_timeout' => q[0],
  'index_expire' => q[1],
  'inhibit_startup_message' => q[0],
  'keep_source_where' => q[/opt/cpan/sources],
  'load_module_verbosity' => q[v],
  'lynx' => q[],
  'make' => q[/usr/bin/make],
  'make_arg' => q[],
  'make_install_arg' => q[],
  'make_install_make_command' => q[/usr/bin/make],
  'makepl_arg' => q[],
  'mbuild_arg' => q[],
  'mbuild_install_arg' => q[],
  'mbuild_install_build_command' => q[./Build],
  'mbuildpl_arg' => q[],
  'ncftp' => q[],
  'ncftpget' => q[],
  'no_proxy' => q[],
  'pager' => q[/usr/bin/less],
  'perl5lib_verbosity' => q[v],
  'prefer_installer' => q[MB],
  'prefs_dir' => q[__DISTROPREFSDIR__],
  'prerequisites_policy' => q[follow],
  'scan_cache' => q[atstart],
  'shell' => q[/bin/bash],
  'show_upload_date' => q[0],
  'tar' => q[/bin/tar],
  'tar_verbosity' => q[v],
  'term_is_latin' => q[0],
  'term_ornaments' => q[1],
  'test_report' => q[0],
  'trust_test_report_history' => q[0],
  'unzip' => q[],
  'urllist' => [qw[__MIRRORS__]],
  'use_sqlite' => q[1],
  'wget' => q[/usr/bin/wget],
  'yaml_load_code' => q[0],
};
1;
