#!/usr/local/bin/perl -w package Elinfo; sub new { bless { MINLEV => undef, ATAB => {} }, shift; } package main; use English; use Getopt::Long; use XML::Parser; use Config; my $benchFailed=0; format = ------------------------- @<<<<< bench failed $benchFailed . my $help = 0; my $verboseLevel = 0; my $root = $ENV{ROOT}; my $benchDir = $root . '/bench'; my $dataDir = $benchDir . '/data'; my $databaseFile = $dataDir . '/benchDb.xml'; my $os = 'linux'; my $version = '2_4'; my %filter = (); my $maxSlept = 30; my $indentCnt = 0; my $indentInc = 2; my $statusCol = 73; my $lineLength = 0; my $seenEOL = 1; my $isLog = 0; my $isGenerate = 0; $Getopt::Long::ignorecase = 0; die unless GetOptions("args=s" => \$extraArgs, "databaseFile=s" => \$databaseFile, "generate!" => \$isGenerate, "help" => \$help, "indent=i" => \$indentInc, "log!" => \$isLog, "filterName=s" => \$filter{'name'}, "os=s" => \$os, "verbose=i" => \$verboseLevel, "version=s" => \$version); usage() if $help; # Set destination directory: if ($verboseLevel > 1) { printf "OS: $os\n"; } # Severity enumeration: # 0 - stop execution # 1 - # 2 - # 3 - stop bench # 4 - failure # 5 - warning # 6 - information my @errors = ( {'code' => 0, svr => 6, usr => 0, msg => 'Really nothing!'}, {'code' => 1, svr => 0, usr => 0, msg => 'reserved'}, {'code' => 2, svr => 0, usr => 0, msg => 'reserved'}, {'code' => 3, svr => 3, usr => 0, msg => 'reserved'}, {'code' => 4, svr => 3, usr => 0, msg => 'reserved'}, {'code' => 5, svr => 3, usr => 0, msg => 'Time elapsed!'}, {'code' => 6, svr => 3, usr => 0, msg => 'Source file does not exist!'}, {'code' => 7, svr => 3, usr => 0, msg => 'Destination file does not exist!'}, {'code' => 8, svr => 4, usr => 1, msg => 'Snapshot is different than golden!'}, {'code' => 9, svr => 4, usr => 1, msg => 'At least one bench failed!'}, {'code' => 10, svr => 5, usr => 0, msg => 'Cannot read temporary file!'} ); my ($errn, $errt, $ie); my $maxSvr = 10; my $curSvr = $maxSvr; my @Attrs; my %Files = (); my %Clos = (); my $elementRoot; my $subform = ' @<<<<<<<<<<<<<<<<<<<<<<< @>>>>'; $databaseFile =$dataDir . '/' . $databaseFile unless -f $databaseFile; die "Can't find file \"$databaseFile\"" unless -f $databaseFile; doStart(); printEnv(); my $parser = new XML::Parser(ErrorContext => 2, Handlers => {Start => \&start_handler, End => \&end_handler, Char => \&char_handler, CdataStart => \&cdata_start, CdataEnd => \&cdata_end } ); $parser->parsefile($databaseFile); doExit(0); ################ ## End of main ################ # # # sub start_handler { my $xp = shift; my $currentElement = shift; # innermost currently opened element my $element; my $parentEnable = 'true'; my $parentAttrTable = 0; if (defined($xp->current_element)) { $parentAttrTable = $Attrs[$#Attrs]; $parentEnable = $parentAttrTable->{'enable'}; } # Create attributes: $attrTable = {}; # Initialize attributes: if (($currentElement ne 'file') && ($currentElement ne 'clo')) { for $attr (keys %$parentAttrTable) { $attrTable->{$attr} = $parentAttrTable->{$attr}; } $attrTable->{'enable'} = $parentEnable; } push @Attrs, $attrTable; # Update attributes: while (@_) { my $id = shift; my $val = shift; $val = $xp->xml_escape($val, "'"); $attrTable->{$id} = $val; } return if ($currentElement eq 'class'); if ($currentElement eq 'clo') { processStartClo($attrTable); return; } if ($currentElement eq 'file') { processStartFile($attrTable); return; } # Don't process if bench is disable: return if ($attrTable->{'enable'} ne 'true'); # Process 'bench': if ($currentElement eq 'bench') { processStartBench($attrTable); return; } # Disable it, if filter{name} has been specified and there is no match: return if (defined($filter{'name'}) && ($element !~ m/(?:^|\/)$filter{'name'}(?:$|\/)/)); # run the command processStartCmd($currentElement, $attrTable); } # # # sub end_handler { my $xp = shift; my $currentElement = shift; my $element = $currentElement; my $attrTable = pop @Attrs; my $parentAttrTable = 0; $parentAttrTable = $Attrs[$#Attrs] if (defined($xp->current_element)); return if ($currentElement eq 'class'); return if ($currentElement eq 'file'); return if ($currentElement eq 'clo'); return if ($attrTable->{'enable'} ne 'true'); # Process 'bench': if ($currentElement eq 'bench') { processEndBench($parentAttrTable, $attrTable); return; } # Disable it, if filter{name} has been specified and there is no match: return if (defined($filter{'name'}) && ($element !~ m/(?:^|\/)$filter{'name'}(?:$|\/)/)); # Process the command: processEndCmd($currentElement, $parentAttrTable, $attrTable); } # sub char_handler { my ($xp, $data) = @_; } # sub cdata_start { my $xp = shift; } # sub cdata_end { my $xp = shift; } # sub showtab { my ($title, $table, $dosum) = @_; my @list = sort keys %{$table}; if (@list) { print "\n $title:\n"; my $item; my $sum = 0; foreach $item (@list) { my $cnt = $table->{$item}; formline($subform, $item, $cnt); print $ACCUMULATOR, "\n"; $ACCUMULATOR = ''; } if ($dosum and @list > 1) { print " =====\n"; formline($subform, '', $sum); print $ACCUMULATOR, "\n"; $ACCUMULATOR = ''; } } } # sub usage { printf "Usage: MakeHtmlPage [options]\n"; printf " -args \tset additional arguments to bench program -help\t\t\tprint this help message -verbose \tset verbose level to on -databaseFile \tset database xml file to -filterName \tselect bench (and sub benches).\n"; exit(0); } # sub processError { my ($errCode, $errMsg, $attrTable) = @_; if (!$errors[$errCode]{usr} || $verboseLevel > 1) { printInfo("$errMsg", 1) if $errMsg; printInfo("$errors[$errCode]{msg}", 1); } my $svr = $errors[$errCode]{svr}; $attrTable->{'status'} = 'failed' if ($svr <= 4); doExit($errCode) if ($svr == 0); return $svr; } # sub printStatus { my ($attrTable) = @_; printInfo("Bench status", 0) if ($seenEOL); my $statusIndentCnt = $statusCol - $lineLength; my $fmt = '%' . $statusIndentCnt . 's'; my $spacing = sprintf($fmt, ' '); printInfo($spacing . $attrTable->{'status'}, 1); } # sub doStart { print scalar localtime; printf "\n"; } # sub doExit { print scalar localtime; printf "\n"; my $rc = shift; write() if ($verboseLevel > 1 && $benchFailed > 0); exit($rc); } # sub printInfo { my ($line, $endOfLine) = @_; return unless $verboseLevel; if ($seenEOL && $indentCnt) { my $fmt = '%' . $indentCnt . 's'; printf ($fmt, ' '); $lineLength += $indentCnt; } print $line; if ($endOfLine) { printf "\n"; $seenEOL = 1; $lineLength = 0; } else { $seenEOL = 0; $lineLength += length $line; } } # sub processStartClo { my ($attrTable) = @_; printInfo("Adding command-line option $attrTable->{'name'}", 1) if ($verboseLevel > 1); $Clos{$attrTable->{'name'}} = $attrTable; } # sub processStartFile { my ($attrTable) = @_; return if ($curSvr <= 1); printInfo("Adding file $attrTable->{'name'}", 1) if ($verboseLevel > 1); $Files{$attrTable->{'name'}} = $attrTable; } # sub processStartBench { my ($attrTable) = @_; return if ($curSvr <= 1); printInfo("Performing bench", 1); $attrTable->{'status'} = 'passed'; $indentCnt += $indentInc; } # sub processStartCmd { my ($currentElement, $attrTable) = @_; return if ($curSvr <= 3); printInfo("Performing $currentElement ($attrTable->{'file'}) ", 0); $attrTable->{'status'} = 'unknow'; $indentCnt += $indentInc; my $fileAttrTable = $Files{$attrTable->{'file'}}; my $filename = $fileAttrTable->{'name'}; my $command = $currentElement; @args = (); push @args, $command; foreach $clo (keys %Clos) { $cmd = $Clos{$clo}->{'string'}; push @args, $cmd . $fileAttrTable->{$clo} if exists($fileAttrTable->{$clo}); push @args, $cmd . $attrTable->{$clo} if exists($attrTable->{$clo}); } push @args, $extraArgs if defined($extraArgs); push @args, $filename; # print command printInfo("@args", 1) if ($verboseLevel > 1); printInfo('.', 0); printInfo("@args", 1); if (1) { $rc = 0xffff & system @args; print("system(%s) returned %#04x: ", "@args", $rc) if ($verboseLevel > 1); if ($rc == 0) { print("ran with normal exit\n") if ($verboseLevel > 1); } elsif ($rc == 0xff00) { print "command failed : $!\n"; } elsif ($rc > 0x80) { $rc >>= 8; print "ran with non-zero exit status $rc\n"; } else { print "ran with "; if ($rc & 0x80) { $rc &= ~0x80; print "coredump from "; } print "signal $rc\n"; } $attrTable->{'status'} = ($rc == 0) ? 'passed' : 'failed'; } printInfo("", 1) if ($verboseLevel > 1); } # sub updateParentStatus { my ($parentAttrTable, $attrTable) = @_; $parentAttrTable->{'status'} = 'failed' if ($attrTable->{'status'} eq 'failed'); $parentAttrTable->{'status'} = 'unknow' if ($parentAttrTable->{'status'} eq 'passed') && ($attrTable->{'status'} eq 'unknow'); } # sub processEndBench { my ($parentAttrTable, $attrTable) = @_; return if ($curSvr < 1); printInfo("Analyzing bench ", 0) if ($verboseLevel > 2); printStatus($attrTable); updateParentStatus($parentAttrTable, $attrTable) if ($parentAttrTable); $curSvr = $maxSvr; $indentCnt -= $indentInc; } # sub processEndCmd { my ($currentElement, $parentAttrTable, $attrTable) = @_; return if ($curSvr < 3); printInfo("Analyzing $currentElement $attrTable->{'file'}", 1) if ($verboseLevel > 2); if ($attrTable->{'status'} ne 'failed') { # do something } printStatus($attrTable); updateParentStatus($parentAttrTable, $attrTable); $benchFailed++ if ($attrTable->{'status'} eq 'failed'); $indentCnt -= $indentInc; $curSvr = $maxSvr; } sub printEnv { # Compiler # -------- OS_SWITCH: { @infoLines = `cl -? 2>&1`, $compInfo = $infoLines[0], chop $compInfo, $compName = 'cl', last OS_SWITCH if $OSNAME =~ /MSWin32/; $compInfo = `gcc --version`, $compName = 'gcc', last OS_SWITCH if $OSNAME =~ /Linux/i; $compInfo = '', $compName = 'unrecognized'; } printf("COMPILER NAME: $compName\n"); printf("COMPILER INFO: $compInfo\n"); # System # ------ $sysInfo = `uname -a`; printf("OS NAME: $OSNAME\n"); printf("OS INFO: $sysInfo\n"); # Hardware # -------- @cpus = (); $memSize = 'unknown'; $gfxBoard = 'unknown'; if ($OSNAME =~ /MSWin32/i) { } elsif ($OSNAME =~ /IRIX/i) { # Extract the information: @infoLines = `hinv`; # Initialize the fields $numCpus = 0; $cpuSpeed = 'unknown'; $cpuType = 'unknown'; $primDataCache = 'unknown'; $secDataCache = 'unknown'; $instCache = 'unknown'; # Parse: for $record (@infoLines) { if ($record =~ /([^\s])+ ([^\s]+) MHZ ([^\s]+) Processor/) { $numCpus = $1; $cpuSpeed = $2; $cpuType = $3; } elsif ($record =~ /Data cache size:[\s]+([^\n]*)/) { $primDataCache = $1; } elsif ($record =~ /Secondary cache size:[\s]+([^\n]*)/) { $secDataCache = $1; } elsif ($record =~ /Instruction cache size:[\s]+([^\n]*)/) { $instCache = $1; } elsif ($record =~ /Graphics board:[\s]+([^\n]*)/) { $gfxBoard = $1; } elsif ($record =~ /Main memory size:[\s]+([^\n]*)/) { $memSize = $1; } } # Update: for $i (0 .. $numCpus-1) { $cpus[$i]{'cpuSpeed'} = $cpuSpeed; $cpus[$i]{'cpuType'} = $cpuType; $cpus[$i]{'primDataCache'} = $primDataCache; $cpus[$i]{'secDataCache'} = $secDataCache; $cpus[$i]{'instCache'} = $instCache; } } elsif ($OSNAME =~ /linux/i) { open CPUFILE, '/proc/cpuinfo' or die "Can't open file: /proc/cpuinfo\n"; @infoLines = ; close CPUFILE; for $record (@infoLines) { chop $record; if ($record =~ /processor[\s]*:[\s]+([^\s]+)/) { $i = $1; $cpus[$i]{'cpuSpeed'} = 0; $cpus[$i]{'cpuType'} = 0; $cpus[$i]{'primDataCache'} = 0; $cpus[$i]{'secDataCache'} = 0; $cpus[$i]{'instCache'} = 0; } elsif ($record =~ /cpu MHz[\s]*:[\s]+([^\s].*)/) { $cpus[$i]{'cpuSpeed'} = $1 . ' MHz'; } elsif ($record =~ /model name[\s]*:[\s]+([^\s].*)/) { $cpus[$i]{'cpuType'} = $1; } elsif ($record =~ /cache size[\s]*:[\s]+([^\s].*)/) { $cpus[$i]{'primDataCache'} = $1; } } open MEMFILE, '/proc/meminfo' or die "Can't open file: /proc/meminfo\n"; @infoLines = ; close MEMFILE; for $record (@infoLines) { chop $record; if ($record =~ /Mem:[\s]+([^\s]+)/) { $memSize = int($1 / 1048576) . ' MBytes'; } } } elsif ($OSNAME =~ /Solaris/i) { # Processor=`psrinfo -v | sed -n -e '1,4 s/.*The \(.*\) # processor operates at \(.*\),/\2 \1/p'` # Memory size=`prtconf -pv`:Memory.size[\s:]+(.*) # Instruction cache=0x`prtconf -pv`:icache-size Bytes # L1 data cache=0x`prtconf -pv`:dcache-size Bytes # L2 data cache=0x`prtconf -pv`:ecache-size Bytes } for $i (0 .. $#cpus) { print "PROCESSOR: $i\n"; print "CPU SPEED: $cpus[$i]{'cpuSpeed'}\n"; print "CPU TYPE: $cpus[$i]{'cpuType'}\n"; print "PRIMARY DATA CACHE: $cpus[$i]{'primDataCache'}\n"; print "SECONDARY DATA CACHE: $cpus[$i]{'secDataCache'}\n"; print "INSTRUCTION CACHE: $cpus[$i]{'instCache'}\n"; } print "MEM SIZE: $memSize\n"; print "GFX BOARD: $gfxBoard\n"; # CGAL version # ------------ $cgalVersion = 'unknown'; $cgalFile = "$ENV{CGALROOT}/include/CGAL/version.h"; if (open CGALFILE, $cgalFile) { undef $/; # input record separator $_ = ; # whole file if (/#define CGAL_VERSION\s+([^\s]+)/) { $cgalVersion = $1; } } print "CGAL VERSION: $cgalVersion\n"; # LEDA version # ------------ $ledaVersion = 'unknown'; $ledaFile = "$ENV{LEDAROOT}/CHANGES"; $cgalMakeFile = "$ENV{CGAL_MAKEFILE}"; if (open CGALMAKEFILE, $cgalMakeFile) { undef $/; # input record separator $_ = ; # whole file if (/^(.*LEDA)\/incl/) { $ledaFile = $1; } open LEDAFILE, $ledaFile or die "Can't open file: $ledaFile\n"; undef $/; # input record separator $_ = ; # whole file if (/#define __LEDA__\s+([^\s]+)/) { $ledaVersion = $1; } } print "LEDA VERSION: $ledaVersion\n"; # Qt version # ---------- $qtVersion = 'unknown'; $qtFile = "$ENV{QTDIR}/README"; if (open QTFILE, $qtFile) { undef $/; # input record separator $_ = ; # whole file if (/version\s+([^\s]+)/) { $qtVersion = $1; } } print "QT VERSION: $qtVersion\n"; } # Tell Emacs that this is really a perl script # Local Variables: # mode:perl # End: