build(utils/makehelp.pl): Introduced awareness for Make variables.
This commit is contained in:
parent
fba71e5e38
commit
cf0bd0211a
@ -4,22 +4,35 @@ use strict;
|
|||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
my %msg = ();
|
my %msg = ();
|
||||||
my @start = ();
|
|
||||||
my %reorder = (help=>-1);
|
my %reorder = (help=>-1);
|
||||||
|
|
||||||
|
# We do not want every Makefile syntax error to break help completely,
|
||||||
|
# so we just disable the kind of features where the syntax error occurs
|
||||||
|
# In that case we store also the error message here
|
||||||
|
my %brokenFeatures = ();
|
||||||
|
|
||||||
|
my @blocks = ();
|
||||||
|
my @plainCode = ();
|
||||||
|
|
||||||
READ: while(<>) {
|
READ: while(<>) {
|
||||||
|
my $lnum = $.;
|
||||||
if(m/^# HELP HEADER START/) {
|
if(m/^# HELP HEADER START/) {
|
||||||
|
my @start = ();
|
||||||
while(<>) {
|
while(<>) {
|
||||||
next READ if m/^# HELP HEADER END/;
|
do {
|
||||||
|
push @blocks, { kind=>'start', text=>\@start, line=>$lnum };
|
||||||
|
next READ
|
||||||
|
} if m/^# HELP HEADER END/;
|
||||||
if(m/# (.*)/) {
|
if(m/# (.*)/) {
|
||||||
push @start, $1
|
push @start, $1
|
||||||
} else {
|
} else {
|
||||||
die "$0: Invalid HELP HEADER section in Makefile!\n";
|
die "$0: Invalid HELP HEADER section in Makefile!\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
push @blocks, { kind=>'start', text=>\@start, line=>$lnum };
|
||||||
next READ
|
next READ
|
||||||
}
|
}
|
||||||
if(m/# HELP((?:\([^\(\)]+\))?):\s*(.*)/) {
|
if(m/^# HELP((?:\((?:[^\(\)]|\([^\(\)]+\))+\))?):\s*(.*)/) {
|
||||||
my ($target, $message) = ($1, $2);
|
my ($target, $message) = ($1, $2);
|
||||||
if($target=~m/\((.*)\)/) {
|
if($target=~m/\((.*)\)/) {
|
||||||
$target = $1;
|
$target = $1;
|
||||||
@ -29,13 +42,125 @@ READ: while(<>) {
|
|||||||
$line=~m/^([^:]+):/ or die "$0: HELP marker expects target but no target found!\n";
|
$line=~m/^([^:]+):/ or die "$0: HELP marker expects target but no target found!\n";
|
||||||
$target = $1
|
$target = $1
|
||||||
}
|
}
|
||||||
$msg{$target} .= $message
|
push @blocks, { kind=>'target', target=>$target, message=>$message, line=>$lnum };
|
||||||
|
next READ
|
||||||
|
}
|
||||||
|
if(m/^# HELPVAR\((.*)\)/) {
|
||||||
|
push @blocks, { kind=>'helpvar', content=>$1, line=>$lnum };
|
||||||
|
next READ;
|
||||||
|
}
|
||||||
|
push @plainCode, [$lnum, $_]
|
||||||
|
}
|
||||||
|
|
||||||
|
my %kindBlocks = ();
|
||||||
|
for(@blocks) {
|
||||||
|
push @{$kindBlocks{$_->{kind}}}, $_
|
||||||
|
}
|
||||||
|
|
||||||
|
my @matchies = ();
|
||||||
|
HELPVARS: {
|
||||||
|
for my $hv(@{$kindBlocks{helpvar}}) {
|
||||||
|
my $reVar = qr((?:\$\((?<name>[A-Z]+)(?:,(?<re>[^\(\)]+))?\)));
|
||||||
|
my $reVarNoGroups = qr((?:\$\((?:[A-Z]+)(?:,(?:[^\(\)]+))?\)));
|
||||||
|
my @parts = split /($reVarNoGroups)/, $hv->{content};
|
||||||
|
my %setvars = ();
|
||||||
|
my @reParts = ();
|
||||||
|
for my $p(@parts) {
|
||||||
|
if($p=~m#^$reVar$#) {
|
||||||
|
my $name = $+{name};
|
||||||
|
my $re = $+{re};
|
||||||
|
if(defined $re) {
|
||||||
|
if(exists $setvars{$name}) {
|
||||||
|
$brokenFeatures{helpvars} = "Makefile line $hv->{line}: Multiple definitions of variable $name found!";
|
||||||
|
last HELPVARS
|
||||||
|
}
|
||||||
|
$setvars{$name} = $re;
|
||||||
|
push @reParts, [1,qr((?<$name>$re))];
|
||||||
|
} else {
|
||||||
|
if(not exists $setvars{$name}) {
|
||||||
|
$brokenFeatures{helpvars} = "Makefile line $hv->{line}: Variable $name used without definition!";
|
||||||
|
last HELPVARS
|
||||||
|
}
|
||||||
|
push @reParts, [0,$name]; #qr((?:\k<$name>)); -- problem: cannot reference variable when not defined
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
push @reParts, [1,qr((?:\Q$p\E))];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
my $reCol = qr((?:));
|
||||||
|
for my $r(@reParts) {
|
||||||
|
my ($isRe, $reg) = @$r;
|
||||||
|
if($isRe) {
|
||||||
|
$reCol = qr((?:$reCol$reg));
|
||||||
|
} else {
|
||||||
|
eval {
|
||||||
|
$reCol = qr((?:$reCol(?:\k<$reg>)));
|
||||||
|
};
|
||||||
|
if($@) {
|
||||||
|
$brokenFeatures{helpvars} = "Makefile line $hv->{line}: Variable $reg caused an internal error ($@)!";
|
||||||
|
last HELPVARS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
push @matchies, $reCol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print "$_\n" for @start;
|
my %helpvars = ();
|
||||||
print "\n" if @start;
|
|
||||||
for my $tar(sort {($reorder{$a}||0) <=> ($reorder{$b}||0) || $a cmp $b } keys %msg) {
|
for my $rowr(@plainCode) {
|
||||||
print "$tar\n $msg{$tar}\n\n"
|
my ($lnum, $row) = @$rowr;
|
||||||
|
my @matches = ();
|
||||||
|
for my $re(@matchies) {
|
||||||
|
if($row=~m#^$re$#) {
|
||||||
|
my %h = %+;
|
||||||
|
push @matches, \%h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(@matches>1) {
|
||||||
|
$brokenFeatures{helpvars} = "Makefile line $lnum: Multiple variable definitions match on row '$row'\n";
|
||||||
|
}
|
||||||
|
if(1==@matches) {
|
||||||
|
my %h = %{$matches[0]};
|
||||||
|
for my $k(keys %h) {
|
||||||
|
push @{$helpvars{$k}}, $h{$k}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my @start = ();
|
||||||
|
@start = @{$kindBlocks{start}} if exists $kindBlocks{start};
|
||||||
|
|
||||||
|
for my $tg(@{$kindBlocks{target}}) {
|
||||||
|
my $tgv = $tg->{target};
|
||||||
|
my @build = ();
|
||||||
|
$tgv=~s#\$\(([A-Z]+)(?:,[^\(\)]*)?\)#push @build, {name=>$1,elm=>$helpvars{$1}}; $1#ge;
|
||||||
|
unshift @build, $tg->{message};
|
||||||
|
$msg{$tgv} = \@build;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub msgprinter {
|
||||||
|
my $el = shift;
|
||||||
|
if('HASH' eq ref $el) {
|
||||||
|
print " Where $el->{name} is one of\n";
|
||||||
|
print " $_\n" for @{$el->{elm}};
|
||||||
|
return
|
||||||
|
}
|
||||||
|
$el =~ s#(.{40,76})\s+#$1\n #g;
|
||||||
|
print " $el\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
for(@start) {
|
||||||
|
print "$_\n" for @{$_->{text}}
|
||||||
|
}
|
||||||
|
print "\n" if @start;
|
||||||
|
for my $tar(sort {($reorder{$a}||0) <=> ($reorder{$b}||0) || $a cmp $b } keys %msg) {
|
||||||
|
print "$tar\n";
|
||||||
|
msgprinter($_) for @{$msg{$tar}};
|
||||||
|
print "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
for my $k(keys %brokenFeatures) {
|
||||||
|
warn "\n!!!!!\nFailed to complete construct the help message from the Makefile.\nFeature '$k' disabled, because: $brokenFeatures{$k}\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user