mirror of
https://github.com/novatiq/packages.git
synced 2026-04-30 15:38:40 +01:00
perl: Switch to split configuration files
This replaces the previously used collection of configuration files for every single architecture in conjunction with hacky overrides, which became an increasing burden to maintain. Fixes a number of outstanding bugs and oddities, with the most important one being the previously wrong signal order(as shown by ext/POSIX/t/sigaction.t). See files/perlconfig.pl's POD and files/README.config for details. Signed-off-by: Marcel Denia <naoir@gmx.net>
This commit is contained in:
@@ -0,0 +1,313 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Copyright 2015 Marcel Denia
|
||||
|
||||
=head1 NAME
|
||||
|
||||
perlconfig.pl
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<perlconfig.pl> [B<-Dsymbol>=I<value>, ...] [B<-dsymbol>=I<value>, ...] I<[files]>
|
||||
|
||||
Generate a configuration file suitable for (cross-)compiling perl 5.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over
|
||||
|
||||
=item B<-Dsymbol=value>
|
||||
|
||||
The symbol identified by I<name> will have the literal value I<value>.
|
||||
When generating the configuration file, it's value will be printed enclosed by
|
||||
single quotation marks(').
|
||||
|
||||
=item B<-dsymbol=value>
|
||||
|
||||
The symbol identified by I<name> will have the literal value I<value>.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<perlconfig.pl> is a program to compile and generate configuration files ready
|
||||
to be used as a "config.sh" file for compiling perl 5. It does so by processing
|
||||
specially-made configuration files(usually called *.config), typically augmented
|
||||
by command-line definitions.
|
||||
|
||||
B<perlconfig.pl>'s intent is to be used in place of perl 5's own Configure
|
||||
script in situations where it can not be run, like cross-compiling.
|
||||
|
||||
=head2 File syntax
|
||||
|
||||
B<perlconfig.pl>'s configuration files a consist of symbol definitions in
|
||||
different variations, each one assigning a specific symbol identified by a name
|
||||
some value, as well as conditional blocks in order to allow for some
|
||||
flexibility.
|
||||
|
||||
=head3 Symbol names
|
||||
|
||||
A symbol name has to consist entirely of alphanumeric characters as well as
|
||||
the underscore(_) character. In addition, symbol names may be prefixed with an
|
||||
all-lowercase string, seperated by a colon(:):
|
||||
|
||||
my:name=value
|
||||
|
||||
Having a zero-length prefix string is also valid:
|
||||
|
||||
:name=value
|
||||
|
||||
Symbols prefixed that way are called private symbols. They act exactly like
|
||||
regular symbols, with the only difference being that they will B<not> be written
|
||||
to the final configuration file.
|
||||
|
||||
=head3 Symbol definitions
|
||||
|
||||
A symbol definition is in the form of a simple name/value pair, seperated by
|
||||
an equals sign(=):
|
||||
|
||||
name=value
|
||||
|
||||
I<value> can be anything really. However, there are 3 notations, with
|
||||
differences in quoting and interpolation:
|
||||
|
||||
=over
|
||||
|
||||
=item name=foo
|
||||
|
||||
The symbol identified by I<name> will have the literal value I<foo>.
|
||||
|
||||
=item name='foo'
|
||||
|
||||
The symbol identified by I<name> will have the literal value I<foo>.
|
||||
When generating the configuration file, it's value will be printed enclosed by
|
||||
single quotation marks(').
|
||||
|
||||
=item name="foo"
|
||||
|
||||
The symbol identified by I<name> will have the value of I<foo>
|
||||
S<B<after interpolation>>(as described in L</Interpolation>).
|
||||
When generating the configuration file, it's value will be printed enclosed by
|
||||
single quotation marks(').
|
||||
|
||||
=back
|
||||
|
||||
=head3 Conditional blocks
|
||||
|
||||
A conditional block is of the form
|
||||
|
||||
(condition) {
|
||||
...
|
||||
}
|
||||
|
||||
B<perlconfig.pl> will execute everything enclosed in the curly braces({ and }),
|
||||
or inside the BLOCK in Perl 5 terms, if I<condition> evaluates to any true
|
||||
value. I<condition> will go through interpolation as described in
|
||||
L</Interpolation>. It may contain any valid Perl 5 expression. Some common
|
||||
examples are:
|
||||
|
||||
=over
|
||||
|
||||
=item $name eq 'foo'
|
||||
|
||||
Evaluates to true if configuration symbol I<name> is literally equal to I<foo>.
|
||||
|
||||
=item $name ne 'foo'
|
||||
|
||||
Evaluates to true if configuration symbol I<name> is B<not> literally equal to
|
||||
I<foo>.
|
||||
|
||||
=item defined($name)
|
||||
|
||||
Evaluates to true if configuration symbol I<name> is defined(has any usable
|
||||
value, see L<perlfunc/defined>).
|
||||
|
||||
=back
|
||||
|
||||
Conditional blocks may be nested inside conditional blocks. Note that the
|
||||
opening curl brace({) has to be on the same line as your condition.
|
||||
|
||||
=head3 Comments
|
||||
|
||||
All lines starting with nothing or any number of whitespaces, followed by a
|
||||
hash sign(#), are considered comments and will be completely ignored by
|
||||
B<perlconfig.pl>.
|
||||
|
||||
=head3 Interpolation
|
||||
|
||||
In certain situations(see above), B<perlconfig.pl> will interpolate strings or
|
||||
constructs in order to allow you to refer to configuration symbols or embed
|
||||
code.
|
||||
|
||||
Interpolated strings are subject to the following rules:
|
||||
|
||||
=over
|
||||
|
||||
=item You may not include any single(') or double(") quotation marks.
|
||||
|
||||
You can use \qq in order to include double quotation marks(") in your string.
|
||||
|
||||
=item $name and ${name} reference configuration symbols
|
||||
|
||||
You can easily refer to existing configuration symbols using the commmon $name
|
||||
or ${name} syntax. In case you want to refer to the perl variable named $name,
|
||||
write \$name. This is useful for embedding code.
|
||||
|
||||
=item Perl 5 interpolation rules apply
|
||||
|
||||
Aside from the above, you may include anything that is also valid for an
|
||||
interpolated(qq//) string in Perl 5. For instance, it's perfectly valid to
|
||||
execute code using the @{[]} construct.
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
As a simple example, consider the following configuration file, named
|
||||
"example.config":
|
||||
|
||||
recommendation='The Perl you want is'
|
||||
($:maturity eq 'stable') {
|
||||
recommendation="$recommendation Perl 5"
|
||||
}
|
||||
($:maturity eq 'experimental') {
|
||||
recommendation="$recommendation Perl 6(try Rakudo!)"
|
||||
}
|
||||
|
||||
Executing it using these command-lines will yield the following results:
|
||||
|
||||
=over
|
||||
|
||||
=item $ perlconfig.pl -D:maturity=stable example.config
|
||||
|
||||
recommendation='The Perl you want is Perl 5'
|
||||
|
||||
=item $ perlconfig.pl -D:maturity=experimental example.config
|
||||
|
||||
recommendation='The Perl you want is Perl 6(try Rakudo!)'
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Marcel Denia <naoir@gmx.net>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright 2015 Marcel Denia
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use List::Util qw/all/;
|
||||
my $symbol_name_prefix_regex = '(?:[a-z]*:)';
|
||||
my $symbol_name_regex = "($symbol_name_prefix_regex?(?:[a-zA-Z0-9_]+))";
|
||||
|
||||
my %config;
|
||||
|
||||
sub interpolate {
|
||||
my $string = shift;
|
||||
my %options = @_;
|
||||
|
||||
# First, convert $foo into ${foo}
|
||||
$string =~ s/(?<!\\)\$$symbol_name_regex/\${$1}/gs;
|
||||
|
||||
# Make ${foo} into $config{'foo'}->{value}
|
||||
$string =~ s/\$\{$symbol_name_regex\}/\$config{\'$1\'}->{value}/g;
|
||||
|
||||
# Un-escape \$foo
|
||||
$string =~ s/\\\$/\$/g;
|
||||
|
||||
# Turn \qq into "
|
||||
$string =~ s/\\qq/\\"/g;
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
# Parse command-line symbol definitions
|
||||
while ($ARGV[0]) {
|
||||
if ($ARGV[0] =~ /^-([D|d])$symbol_name_regex=(.*)$/) {
|
||||
$config{$2} = { value => $3, quoted => $1 eq 'D' };
|
||||
shift(@ARGV);
|
||||
}
|
||||
else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# Process configuration files
|
||||
my @condition_stack = ( 1 );
|
||||
for my $file (@ARGV) {
|
||||
open(my $fh, '<', $file) or die "Can't open $file: $!\n";
|
||||
while (my $line = <$fh>) {
|
||||
chomp($line);
|
||||
|
||||
if ($line =~ /^\s*$symbol_name_regex=(.*)$/) { # A symbol definition
|
||||
if (all {$_ == 1} @condition_stack) {
|
||||
my $symbol = $1;
|
||||
(my $quote_begin, my $value, my $quote_end) = $2 =~ /^(['|"])?([^'"]*)(['|"])?$/;
|
||||
|
||||
$quote_begin = '' unless defined $quote_begin;
|
||||
$quote_end = '' unless defined $quote_end;
|
||||
die "$file:$.: Unmatched quotes in \"$line\"\n" unless $quote_begin eq $quote_end;
|
||||
|
||||
if ($quote_begin eq '"') {
|
||||
$config{$symbol} = { value => eval('"' . interpolate($2) . '"'), quoted => 1 };
|
||||
}
|
||||
else {
|
||||
$config{$symbol} = { value => $2, quoted => $quote_begin eq '\'' };
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ($line =~ /^\s*\((.*)\)\s?{$/) { # A conditional block
|
||||
if (eval(interpolate($1))) {
|
||||
push(@condition_stack, 1);
|
||||
}
|
||||
else {
|
||||
push(@condition_stack, 0);
|
||||
}
|
||||
}
|
||||
elsif ($line =~ /^\s*}$/) { # Closing a conditional block
|
||||
pop(@condition_stack);
|
||||
die "$file:$.: Closing non-existent block\n" unless @condition_stack;
|
||||
}
|
||||
elsif ($line =~ (/^\s*$/) || ($line =~ /^\s*#/)) { # An empty line or comment
|
||||
}
|
||||
else {
|
||||
die "$file:$.: Malformed line: \"$line\"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Output
|
||||
for (sort(keys(%config))) {
|
||||
my $quote = $config{$_}->{quoted} ? '\'' : '';
|
||||
print("$_=$quote$config{$_}->{value}$quote\n") unless $_ =~ /^$symbol_name_prefix_regex/;
|
||||
}
|
||||
Reference in New Issue
Block a user