| #!/usr/bin/perl |
| # <@LICENSE> |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to you under the Apache License, Version 2.0 |
| # (the "License"); you may not use this file except in compliance with |
| # the License. You may obtain a copy of the License at: |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # </@LICENSE> |
| # |
| # This script isn't supposed to be run by hand, it's used by `make` as a pre- |
| # processor. It currently accepts these options on the command line: |
| # |
| # -M<module> Enables <module> |
| # -D<variable>=<value> Defines the <variable> to be <value>; if the value |
| # doesn't contain an equal sign, it is interpreted |
| # as a file and all of its lines containing equal |
| # signs are taken as <variable>=<value> pairs |
| # |
| # and some more to help with non-UNIX platforms, where command-line input |
| # and output redirection are not always available: |
| # |
| # -i<file> Read from input file <file> |
| # -o<file> Write to output file <file> |
| # |
| # -I<dir> Read from input directory <dir> |
| # -O<dir> Write to output directory <dir> |
| # <filename> ... Process named files from -I<dir> to -O<dir> |
| # |
| # -m<perm> Use chmod permissions <perm> for files |
| # |
| # Those modules are currently implemented: |
| # conditional Comments out every line containing the string |
| # REMOVEFORINST |
| # vars Replaces variables: upper case strings surrounded |
| # by double at-signs, eg. @@VERSION@@. The values are |
| # taken from the environment and can be overwritten with |
| # the -D switch. Empty/undefined variables are removed. |
| # sharpbang Does some sharpbang (#!) replacement. Uses PERL_BIN and |
| # PERL_WARN. |
| |
| |
| use strict; |
| use warnings; |
| |
| my %modules = (); |
| my %defines = (); |
| |
| my @infiles = (); |
| my $infile; |
| my $outfile; |
| my $indir; |
| my $outdir; |
| my $mode; |
| |
| |
| # Each environment variable counts as an own defined var for us. |
| foreach (keys %ENV) { |
| $defines{$_} = $ENV{$_}; |
| } |
| |
| foreach (@ARGV) { |
| if (/^-M([a-z]+)$/) { $modules{$1} = 1; } |
| elsif (/^-D([A-Z0-9_]+)=(.*)$/) { $defines{$1} = $2; } |
| elsif (/^-D([^=]+)$/) { read_defs($1); } |
| elsif (/^-i(.+)$/) { $infile = $1; } |
| elsif (/^-o(.+)$/) { $outfile = $1; } |
| elsif (/^-I(.+)$/) { $indir = $1; } |
| elsif (/^-m(.*)$/) { $mode = '0'.$1; } |
| elsif (/^-O(.+)$/) { $outdir = $1; } |
| elsif (/^(.+)$/) { push (@infiles, $1); } |
| } |
| |
| # On Windows, we get -m without an arg. avoid problems with that |
| # by just ignoring that switch. |
| $mode = undef unless $mode; |
| |
| if (defined ($indir) && defined ($outdir) && scalar @infiles > 0) { |
| require File::Spec; |
| my $fname; |
| while ($fname = shift @infiles) { |
| my $in = File::Spec->catfile ($indir, $fname); |
| my $out = File::Spec->catfile ($outdir, $fname); |
| do_file ($in, $out); |
| } |
| } |
| elsif (defined ($infile) && defined($outfile)) { |
| do_file ($infile, $outfile); |
| } |
| else { |
| # just do STDIN/STDOUT . Not recommended for portability as |
| # it requires "<" and ">" for Makefile to do its work. |
| # |
| do_stdin(); |
| } |
| |
| |
| sub read_defs { |
| my ($in) = @_; |
| open (DEFS, "<$in") or die "Cannot open $in: $!"; |
| foreach (<DEFS>) { |
| $_ =~ s/^\s+|\s+$//g; |
| next if /^#/; |
| next unless /=/; |
| my ($var, $val) = split(/\s*=\s*/, $_, 2); |
| $var =~ tr/A-Z_//cd; |
| $defines{$var} = $val; |
| } |
| close (DEFS); |
| } |
| |
| |
| sub do_file { |
| my ($in, $out) = @_; |
| |
| open (FOOIN, "<$in") or die "Cannot open $in: $!"; |
| open (FOOOUT, ">$out") or die "Cannot open $out: $!"; |
| |
| do_it(); |
| |
| close (FOOIN); |
| close (FOOOUT); |
| |
| if (defined $mode) { |
| chmod (oct $mode, $out) or die "Cannot chmod $mode $out: $!"; |
| } |
| } |
| |
| sub do_stdin { |
| open (FOOIN, "<&STDIN") or die "Cannot dup stdin: $!"; |
| open (FOOOUT, ">&STDOUT") or die "Cannot dup stdout: $!"; |
| |
| do_it(); |
| |
| close (FOOIN); |
| close (FOOOUT); |
| } |
| |
| |
| sub do_it { |
| # The perlpath can be overwritten via -DPERL_BIN=<perlpath> |
| my $perl; |
| if($defines{'PERL_BIN'} && ($defines{PERL_BIN} ne 'this')) { |
| $perl = $defines{'PERL_BIN'}; |
| unless(-x $perl) { |
| warn("No such PERL_BIN: $perl"); |
| } |
| } |
| else { |
| # use eval so the module is not loaded unless needed; it's slow |
| eval 'use Config; $perl = $Config{"perlpath"};'; |
| } |
| |
| # Warnings are enabled per default |
| my $perl_warn = ' -w'; |
| # The warnings can be overwritten via -DPERL_WARN=<yes|no> |
| if ($defines{'PERL_WARN'} and $defines{'PERL_WARN'} eq 'no') { |
| $perl_warn = ''; |
| } |
| |
| # Taint mode is enabled per default except on 5.005 |
| my $perl_taint = ' -T'; |
| # The taint mode can be disabled with -DPERL_TAINT=<yes|no> |
| if ($defines{'PERL_TAINT'} and $defines{'PERL_TAINT'} eq 'no') { |
| $perl_taint = ''; |
| } |
| |
| $defines{PERL_MAJOR_VER} = sub { |
| $] =~ /^(\d\.\d\d\d)/ or die "bad perl ver $]"; |
| return $1; |
| }; |
| |
| $defines{PLUGIN_POD} = sub { |
| |
| # Grab active plugin list |
| my @plugin_pod = (); |
| foreach my $pre (<rules/*.pre>) { |
| if (open(INIT, $pre)) { |
| while (<INIT>) { |
| if (/^loadplugin\s+(.*?)\s*$/) { push(@plugin_pod, " $1\n"); } |
| } |
| close(INIT); |
| } |
| } |
| return join('', sort @plugin_pod); |
| }; |
| |
| my $towrite = ''; |
| while (<FOOIN>) { |
| $_ = pack("C0A*", $_); # turn off UTF8-ness |
| |
| # Conditional compiling |
| if ($modules{'conditional'}) { |
| # DELETE lines carrying the REMOVE_ON_BUILD or (deprecated) REMOVEFORINST tag |
| if(/\bREMOVE(?:FORINST|_ON_BUILD)\b/) { |
| next; |
| } |
| } |
| |
| $towrite .= $_; |
| } |
| |
| # Sharpbang (#!) replacement (see also ExtUtils::MY->fixin) |
| if ($modules{'sharpbang'}) { |
| $towrite =~ s/^#![^\n]*perl[^\n]*\n/#!${perl}${perl_taint}${perl_warn}\n/; |
| } |
| |
| # Variable replacement (do in one invocation) |
| if ($modules{'vars'}) { |
| # Replace all @@VARS@@ |
| while ($towrite =~ /\@\@([A-Z][A-Z0-9_]*)\@\@/) { |
| my $what = $1; |
| my $d = $defines{$what} || ''; |
| if (ref($d) =~ /^CODE/) { $d = $d->(); } |
| $towrite =~ s/\@\@${what}\@\@/$d/g; |
| } |
| } |
| |
| print FOOOUT $towrite; |
| } |