#!/usr/bin/perl ## Checks entries in the indra/newview/gpu_table.txt file against sample data ## ## Copyright (c) 2011, Linden Research, Inc. ## ## Permission is hereby granted, free of charge, to any person obtaining a copy ## of this software and associated documentation files (the "Software"), to deal ## in the Software without restriction, including without limitation the rights ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ## copies of the Software, and to permit persons to whom the Software is ## furnished to do so, subject to the following conditions: ## ## The above copyright notice and this permission notice shall be included in ## all copies or substantial portions of the Software. ## ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ## THE SOFTWARE. use English; use Getopt::Long; ( $MyName = $0 ) =~ s|.*/||; my $mini_HELP = " $MyName {--gpu-table|-g} <gpu_table.txt> {--table-only|-t} Checks for duplicates and invalid lines in the gpu_table.txt file. $MyName {--gpu-table|-g} <gpu_table.txt> [ <gpu-strings-file> ... ] [{--unmatched|-u}] Tests the recognition of values in the gpu-strings-files (or standard input if no files are given). The results of attempting to match each input line are displayed in report form, showing: - NO MATCH, unsupported, or supported - the class of the GPU - the label for the recognizer line from the gpu_table that it matched If the --unmatched option is specified, then no output is produced for values that are matched. $MyName {--gpu-table|-g} <gpu_table.txt> {--diff|-d} <old_results> [ <gpu-strings-file> ...] With the --diff option, the report compares the current results to <old-results>, which should be the output from a previous run without --diff. The report shows each input value with the old result and the new result if it is different. "; &GetOptions("help" => \$Help ,"unmatched" => \$UnMatchedOnly ,"table-only" => \$TableOnly ,"gpu-table=s" => \$GpuTable ,"diff=s" => \$Diff ) || die "$mini_HELP"; if ($Help) { print $mini_HELP; exit 0; } $ErrorsSeen = 0; $NoMatch = 'NO MATCH'; # constant die "Must specify a --gpu-table <gpu_table.txt> value" unless $GpuTable; open(GPUS, "<$GpuTable") || die "Failed to open gpu table '$GpuTable':\n\t$!\n"; my $FirstLine = <GPUS>; die "First line of gpu table does not begin with '//GPU_TABLE'" unless $FirstLine =~ m|^//GPU_TABLE|; # Parse the GPU table into these tables, indexed by the name my %NameLine; # name -> line number on which a given name was found (catches duplicate names) my %RecognizerLine; # name -> line number on which a given name was found (catches duplicate names) my %Name; # recognizer -> name my %Recognizer; # name -> recognizer my %Class; # recognizer -> class my %Supported; # recognizer -> supported my @InOrder; # lowercased recognizers in file order - these are the ones really used to match my %StatsBased; my %ExpectedOpenGL; $Name{$NoMatch} = $NoMatch; $NameLine{$NoMatch} = '(hard-coded)'; # use this for error messages in table parsing $Class{$NoMatch} = ''; $Supported{$NoMatch} = ''; $StatsBased{$NoMatch} = ''; $ExpectedOpenGL{$NoMatch} = ''; while (<GPUS>) { next if m|^//|; # skip comments next if m|^\s*$|; # skip blank lines chomp; my ($name, $regex, $class, $supported, $stats_based, $expected_opengl, $extra) = split('\t+'); my $errsOnLine = $ErrorsSeen; if (!$name) { print STDERR "No name found on $GpuTable line $INPUT_LINE_NUMBER\n"; $ErrorsSeen++; } elsif ( defined $NameLine{$name} ) { print STDERR "Duplicate name '$name' on $GpuTable lines $NameLine{$name} and $INPUT_LINE_NUMBER:\n"; print STDERR " $NameLine{$name}: /$Recognizer{$name}/ $Supported{$Recognizer{$name}} class $Class{$Recognizer{$name}}\n"; print STDERR " $INPUT_LINE_NUMBER: /$regex/ " . ($supported ? "supported" : "unsupported") . " class $class - ignored\n"; $ErrorsSeen++; } if (!$regex) { print STDERR "No recognizer found on $GpuTable line $INPUT_LINE_NUMBER\n"; $ErrorsSeen++; } elsif ( defined $RecognizerLine{$regex} ) { print STDERR "Duplicate recognizer /$regex/ found on $GpuTable lines $RecognizerLine{$regex} and $INPUT_LINE_NUMBER (ignored)\n"; print STDERR " $RecognizerLine{$regex}: name '$Name{$regex}' $Supported{$regex} class $Class{$regex}\n"; print STDERR " $INPUT_LINE_NUMBER: name '$name' " . ($supported ? "supported" : "unsupported") . " class $class - ignored\n"; $ErrorsSeen++; } if ($class !~ m/[012345]/) { print STDERR "Invalid class value '$class' on $GpuTable line $INPUT_LINE_NUMBER\n"; $ErrorsSeen++; } if ($supported !~ m/[0123]/) { print STDERR "Invalid supported value '$supported' on $GpuTable line $INPUT_LINE_NUMBER\n"; $ErrorsSeen++; } if ($stats_based !~ m/[01]/) { print STDERR "Invalid stats_based value '$stats_based' on $GpuTable line $INPUT_LINE_NUMBER\n"; $ErrorsSeen++; } if ($expected_opengl !~ m/\d+(\.\d+)?/) { print STDERR "Invalid expected_opengl value '$expected_opengl' on $GpuTable line $INPUT_LINE_NUMBER\n"; $ErrorsSeen++; } if ($extra) { print STDERR "Extra data '$extra' on $GpuTable line $INPUT_LINE_NUMBER\n"; $ErrorsSeen++; } if ($errsOnLine == $ErrorsSeen) # no errors found on this line { push @InOrder,$regex; $NameLine{$name} = $INPUT_LINE_NUMBER; $RecognizerLine{$regex} = $INPUT_LINE_NUMBER; $Name{$regex} = $name; $Recognizer{$name} = $regex; $Class{$regex} = $class; $Supported{$regex} = $supported ? "supported" : "unsupported"; $StatsBased{$regex} = $stats_based; $ExpectedOpenGL{$regex} = $expected_opengl; } } close GPUS; print STDERR "\n" if $ErrorsSeen; exit $ErrorsSeen if $TableOnly; # Loop over input lines, find the results for each my %RecognizedBy; while (<>) { chomp; $_ = substr($_,0,100); my $lcInput = lc $_; # the real gpu table parser lowercases the input string my $recognizer; $RecognizedBy{$_} = $NoMatch; foreach $recognizer ( @InOrder ) # note early exit if recognized { my $lcRecognizer = lc $recognizer; # the real gpu table parser lowercases the recognizer if ( $lcInput =~ m/$lcRecognizer/ ) { $RecognizedBy{$_} = $recognizer; last; # exit recognizer loop } } } format STDOUT_TOP = GPU String Supported? Class Stats OpenGL Recognizer ------------------------------------------------------------------------------------------------------ ----------- ----- ----- ------ ------------------------------------ . format STDOUT = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<< @> @> @<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<... $_, $Supported{$RecognizedBy{$_}},$Class{$RecognizedBy{$_}},$StatsBased{$RecognizedBy{$_}},$ExpectedOpenGL{$RecognizedBy{$_}},$Name{$RecognizedBy{$_}} . my $ReportLineTemplate = "A102xxxA12xxxA2xxxxA2xxxxA5A*"; # Used to read a previous report - MUST match the format STDOUT above my ( $oldSupported, $oldClass, $newSupported, $newClass ); format DIFF_TOP = ------------- OLD ------------- ----------- NEW -------------------- GPU String Supported? Class Stats OpenGL Supported? Class Stats OpenGL Line ------------------------------------------------------------------------------------------------------ ----------- ----- ----- ------ ----------- ----- ----- ------ ----- . format DIFF = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<< @> @> @<<<< @<<<<<<<<<< @> @> @<<<< @>>>> $_, $oldSupported, $oldClass, $oldStatsBased, $oldExpectedOpenGL, $newSupported, $newClass, $newStatsBased, $newExpectedOpenGL, $newRecognizedLine . if ( ! $Diff ) { ## Print results of testing each input line and how it was recognized. foreach ( sort keys %RecognizedBy ) { write if ! $UnMatchedOnly || $Name{$RecognizedBy{$_}} eq $NoMatch; $-++; # suppresses pagination } } else { ## Print a comparison of how the recognition this time compared to the results from the $Diff file open OLD, "<$Diff" || die "Failed to open --diff file '$Diff'\n\t$!\n"; my $discard = 2; while ( <OLD> ) { if ( $discard <= 0 ) { my ( $gpu, $supported, $class, $stats, $opengl ) = unpack $ReportLineTemplate; $gpu =~ s/\s*$//; ( $OldSupported{$gpu} = $supported ) =~ s/\s*$//; ( $OldClass{$gpu} = $class ) =~ s/\s*$//; ( $OldStatsBased{$gpu} = $stats ) =~ s/\s*$//; ( $OldExpectedOpenGL{$gpu} = $opengl ) =~ s/\s*$//; } else { $discard--; } } close OLD; $FORMAT_TOP_NAME = 'DIFF_TOP'; $FORMAT_NAME = 'DIFF'; foreach ( sort keys %RecognizedBy ) { $newSupported = $Supported{$RecognizedBy{$_}} || $NoMatch; $newClass = $Class{$RecognizedBy{$_}}; $newStatsBased = $StatsBased{$RecognizedBy{$_}}; $newExpectedOpenGL = $ExpectedOpenGL{$RecognizedBy{$_}}; $newRecognizedLine = $RecognizerLine{$RecognizedBy{$_}}; if ( ! defined $OldSupported{$_} ) { $oldSupported = 'NEW'; $oldClass = '-'; $oldStatsBased = '-'; $oldExpectedOpenGL = '-'; write; $-++; # suppresses pagination } else { $oldSupported = $OldSupported{$_} || $NoMatch; $oldClass = $OldClass{$_}; $oldStatsBased = $OldStatsBased{$_}; $oldExpectedOpenGL = $OldExpectedOpenGL{$_}; if ( ( $oldSupported ne $newSupported ) || ( $oldClass ne $newClass ) || ( $oldStatsBased ne $newStatsBased ) || ( $oldExpectedOpenGL ne $newExpectedOpenGL ) ) { write; $-++; # suppresses pagination } } } } exit $ErrorsSeen;