next if m:^#!/bin/sh:;
# Catch CONFIG=true and PATCHLEVEL=n line from Configure.
s/^(\w+)=(true|\d+)\s*$/$1='$2'\n/;
- unless ($in_v or m/^(\w+)='(.*\n)/){
+ # We can delimit things in config.sh with either ' or ".
+ unless ($in_v or m/^(\w+)=(['"])(.*\n)/){
push(@non_v, "#$_"); # not a name='value' line
next;
}
+ $quote = $2;
if ($in_v) { $val .= $_; }
- else { ($name,$val) = ($1,$2); }
- $in_v = $val !~ /'\n/;
+ else { ($name,$val) = ($1,$3); }
+ $in_v = $val !~ /$quote\n/;
next if $in_v;
if ($extensions{$name}) { s,/,::,g }
- if (!$fast{$name}){ push(@v_others, "$name='$val"); next; }
- push(@v_fast,"$name='$val");
+ if (!$fast{$name}){ push(@v_others, "$name=$quote$val"); next; }
+ push(@v_fast,"$name=$quote$val");
}
foreach(@non_v){ print CONFIG $_ }
return $_[0]->{$_[1]} if (exists $_[0]->{$_[1]});
# Search for it in the big string
- my($value, $start, $marker);
- $marker = "$_[1]='";
+ my($value, $start, $marker, $quote_type);
+ $marker = "$_[1]=";
+ $quote_type = "'";
# return undef unless (($value) = $config_sh =~ m/^$_[1]='(.*)'\s*$/m);
- $start = index($config_sh, "\n$marker");
+ # Check for the common case, ' delimeted
+ $start = index($config_sh, "\n$marker$quote_type");
+ # If that failed, check for " delimited
+ if ($start == -1) {
+ $quote_type = '"';
+ $start = index($config_sh, "\n$marker$quote_type");
+ }
return undef if ( ($start == -1) && # in case it's first
(substr($config_sh, 0, length($marker)) ne $marker) );
- if ($start == -1) { $start = length($marker) }
- else { $start += length($marker) + 1 }
+ if ($start == -1) {
+ # It's the very first thing we found. Skip $start forward
+ # and figure out the quote mark after the =.
+ $start = length($marker) + 1;
+ $quote_type = substr($config_sh, $start - 1, 1);
+ }
+ else {
+ $start += length($marker) + 2;
+ }
$value = substr($config_sh, $start,
- index($config_sh, qq('\n), $start) - $start);
+ index($config_sh, "$quote_type\n", $start) - $start);
+ # If we had a double-quote, we'd better eval it so escape
+ # sequences and such can be interpolated. Since the incoming
+ # value is supposed to follow shell rules and not perl rules,
+ # we escape any perl variable markers
+ if ($quote_type eq '"') {
+ $value =~ s/\$/\\\$/g;
+ $value =~ s/\@/\\\@/g;
+ eval "\$value = \"$value\"";
+ }
+ #$value = sprintf($value) if $quote_type eq '"';
$value = undef if $value eq 'undef'; # So we can say "if $Config{'foo'}".
$_[0]->{$_[1]} = $value; # cache it
return $value;
}
sub NEXTKEY {
- my $pos = index($config_sh, qq('\n), $prevpos) + 2;
+ # Find out how the current key's quoted so we can skip to its end.
+ my $quote = substr($config_sh, index($config_sh, "=", $prevpos)+1, 1);
+ my $pos = index($config_sh, qq($quote\n), $prevpos) + 2;
my $len = index($config_sh, "=", $pos) - $pos;
$prevpos = $pos;
$len > 0 ? substr($config_sh, $pos, $len) : undef;
# exists($_[0]->{$_[1]}) or $config_sh =~ m/^$_[1]=/m;
exists($_[0]->{$_[1]}) or
index($config_sh, "\n$_[1]='") != -1 or
- substr($config_sh, 0, length($_[1])+2) eq "$_[1]='";
+ substr($config_sh, 0, length($_[1])+2) eq "$_[1]='" or
+ index($config_sh, "\n$_[1]=\"") != -1 or
+ substr($config_sh, 0, length($_[1])+2) eq "$_[1]=\"";
}
sub STORE { die "\%Config::Config is read-only\n" }
specific library directory ($Config{installarchlib}) and it checks the
perl version number when loaded.
+The values stored in config.sh may be either single-quoted or
+double-quoted. Double-quoted strings are handy for those cases where you
+need to include escape sequences in the strings. To avoid runtime variable
+interpolation, any C<$> and C<@> characters are replaced by C<\$> and
+C<\@>, respectively. This isn't foolproof, of course, so don't embed C<\$>
+or C<\@> in double-quoted strings unless you're willing to deal with the
+consequences. (The slashes will end up escaped and the C<$> or C<@> will
+trigger variable interpolation)
+
=head1 GLOSSARY
Most C<Config> variables are determined by the C<Configure> script