|  | #!/usr/bin/perl | 
|  | # Copyright 2009 The Go Authors. All rights reserved. | 
|  | # Use of this source code is governed by a BSD-style | 
|  | # license that can be found in the LICENSE file. | 
|  |  | 
|  | # This script checks that the compilers emit the errors which we expect. | 
|  | # Usage: errchk COMPILER [OPTS] SOURCEFILES.  This will run the command | 
|  | # COMPILER [OPTS] SOURCEFILES.  The compilation is expected to fail; if | 
|  | # it succeeds, this script will report an error.  The stderr output of | 
|  | # the compiler will be matched against comments in SOURCEFILES.  For each | 
|  | # line of the source files which should generate an error, there should | 
|  | # be a comment of the form // ERROR "regexp".  If the compiler generates | 
|  | # an error for a line which has no such comment, this script will report | 
|  | # an error.  Likewise if the compiler does not generate an error for a | 
|  | # line which has a comment, or if the error message does not match the | 
|  | # <regexp>.  The <regexp> syntax is Perl but its best to stick to egrep. | 
|  |  | 
|  | use POSIX; | 
|  |  | 
|  | my $exitcode = 1; | 
|  |  | 
|  | if(@ARGV >= 1 && $ARGV[0] eq "-0") { | 
|  | $exitcode = 0; | 
|  | shift; | 
|  | } | 
|  |  | 
|  | if(@ARGV < 1) { | 
|  | print STDERR "Usage: errchk COMPILER [OPTS] SOURCEFILES\n"; | 
|  | exit 1; | 
|  | } | 
|  |  | 
|  | # Grab SOURCEFILES | 
|  | foreach(reverse 0 .. @ARGV-1) { | 
|  | unless($ARGV[$_] =~ /\.go$/) { | 
|  | @file = @ARGV[$_+1 .. @ARGV-1]; | 
|  | last; | 
|  | } | 
|  | } | 
|  |  | 
|  | foreach $file (@file) { | 
|  | open(SRC, $file) || die "BUG: errchk: open $file: $!"; | 
|  | $src{$file} = [<SRC>]; | 
|  | close(SRC); | 
|  | } | 
|  |  | 
|  | # Run command | 
|  | $cmd = join(' ', @ARGV); | 
|  | open(CMD, "exec $cmd </dev/null 2>&1 |") || die "BUG: errchk: run $cmd: $!"; | 
|  |  | 
|  | # 6g error messages continue onto additional lines with leading tabs. | 
|  | # Split the output at the beginning of each line that doesn't begin with a tab. | 
|  | $out = join('', <CMD>); | 
|  | @out = split(/^(?!\t)/m, $out); | 
|  |  | 
|  | close CMD; | 
|  |  | 
|  | if($exitcode != 0 && $? == 0) { | 
|  | print STDERR "BUG: errchk: command succeeded unexpectedly\n"; | 
|  | print STDERR @out; | 
|  | exit 0; | 
|  | } | 
|  |  | 
|  | if($exitcode == 0 && $? != 0) { | 
|  | print STDERR "BUG: errchk: command failed unexpectedly\n"; | 
|  | print STDERR @out; | 
|  | exit 0; | 
|  | } | 
|  |  | 
|  | if(!WIFEXITED($?)) { | 
|  | print STDERR "BUG: errchk: compiler crashed\n"; | 
|  | print STDERR @out, "\n"; | 
|  | exit 0; | 
|  | } | 
|  |  | 
|  | sub bug() { | 
|  | if(!$bug++) { | 
|  | print STDERR "BUG: "; | 
|  | } | 
|  | } | 
|  |  | 
|  | sub chk { | 
|  | my $file = shift; | 
|  | my $line = 0; | 
|  | my $regexp; | 
|  | my @errmsg; | 
|  | my @match; | 
|  | foreach my $src (@{$src{$file}}) { | 
|  | $line++; | 
|  | next if $src =~ m|////|;  # double comment disables ERROR | 
|  | next unless $src =~ m|// (GC_)?ERROR (.*)|; | 
|  | my $all = $2; | 
|  | if($all !~ /^"([^"]*)"/) { | 
|  | print STDERR "$file:$line: malformed regexp\n"; | 
|  | next; | 
|  | } | 
|  | @errmsg = grep { /$file:$line[:[]/ } @out; | 
|  | @out = grep { !/$file:$line[:[]/ } @out; | 
|  | if(@errmsg == 0) { | 
|  | bug(); | 
|  | print STDERR "errchk: $file:$line: missing expected error: '$all'\n"; | 
|  | next; | 
|  | } | 
|  | foreach my $regexp ($all =~ /"([^"]*)"/g) { | 
|  | # Turn relative line number in message into absolute line number. | 
|  | if($regexp =~ /LINE(([+-])([0-9]+))?/) { | 
|  | my $n = $line; | 
|  | if(defined($1)) { | 
|  | if($2 eq "+") { | 
|  | $n += int($3); | 
|  | } else { | 
|  | $n -= int($3); | 
|  | } | 
|  | } | 
|  | $regexp = "$`$file:$n$'"; | 
|  | } | 
|  |  | 
|  | @match = grep { /$regexp/ } @errmsg; | 
|  | if(@match == 0) { | 
|  | bug(); | 
|  | print STDERR "errchk: $file:$line: error messages do not match '$regexp'\n"; | 
|  | next; | 
|  | } | 
|  | @errmsg = grep { !/$regexp/ } @errmsg; | 
|  | } | 
|  | if(@errmsg != 0) { | 
|  | bug(); | 
|  | print STDERR "errchk: $file:$line: unmatched error messages:\n"; | 
|  | foreach my $l (@errmsg) { | 
|  | print STDERR "> $l"; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | foreach $file (@file) { | 
|  | chk($file) | 
|  | } | 
|  |  | 
|  | if(@out != 0) { | 
|  | bug(); | 
|  | print STDERR "errchk: unmatched error messages:\n"; | 
|  | print STDERR "==================================================\n"; | 
|  | print STDERR @out; | 
|  | print STDERR "==================================================\n"; | 
|  | } | 
|  |  | 
|  | exit 0; |