texuser74 has asked for the wisdom of the Perl Monks concerning the following question:

Dear Perl Monks,

I am using perl, v5.6.1 built for MSWin32 by IndigoSTAR.

When I compile(latex compiler) my test.tex file a test.log will be created. When I do another compilation the log file will get updated. So I need to keep on compiling until my .log file gets stabilized. For this I am copying the .log file to old.log file and comparing their texts before each compilation. But my following perl script is not exiting properly even after .log and old.log are same. Please review my script and give me your suggestions.

use strict; my %logHash; my $ctr=0; my $diff=0; sub compare{ my($log, $olog) = @_; open(XR, "$log")||die; while(<XR>){ $logHash{$_}=1; } close(XR); open(OXR, "$olog")||die; while(<OXR>){ $diff=1 unless defined($logHash{$_}); } close(OXR); return $diff; } system('latex test.tex'); system ("copy test.log test-old.log"); system('latex test.tex'); while(compare("test.log","test-old.log")){ system ("copy test.log test-old.log"); system('latex test.tex'); }
Thanks in advance

Replies are listed 'Best First'.
Re: problem with while loop
by GrandFather (Saint) on Aug 01, 2008 at 04:31 UTC

    There is a bunch of stuff you ought to do to tidy up your code. As already mentioned making your variables local to the sub will help the immediate problem. But a little restructuring will help with diagnostics when things go pear shaped. Consider:

    use strict; use warnings; sub compare { my ($log, $olog) = @_; my %logHash; open my $XR, '<', $log || die "Failed to open $log: $!"; $logHash{$_}++ while <$XR>; close $XR; open my $OXR, '<', $olog || die "Failed to open $log: $!"; $logHash{$_}-- while <$OXR>; close $OXR; my $diffs = 0; for my $match (sort keys %logHash) { next unless $logHash{$match}; if ($logHash{$match} > 0) { print "Line missing from $olog: $match\n" if $diffs++ < 10 +; } elsif ($logHash{$match} < 0) { print "Line missing from $log: $match\n" if $diffs++ < 10; } } return $diffs; }

    which uses the three parameter version of open to provide a higher degree of safety. A sensible error message is provided by die so failure is easier to diagnose if an open doesn't work.

    Lines are counted "in" and "out" and the first few per iteration are reported so you can check progress.

    Lexical file handles are used as a matter of good practice.


    Perl reduces RSI - it saves typing
      GrandFather, thanks for tidying up my script. Now it works fine and safely. Thanks for your support.
      #!/usr/bin/perl -- use strict; use warnings; use File::Copy; use File::Compare; my @latex = qw'latex test.tex'; # !!perldoc -f system system(@latex) == 0 or die "system (@latex) failed:( $! ):( $? )"; copy(qw"test.log test-old.log") or die "Copy failed: $!"; system(@latex) == 0 or die "system (@latex) failed:( $! ):( $? )"; while ( compare( "test.log", "test-old.log" ) ) { copy(qw"test.log test-old.log") or die "Copy failed: $!"; system(@latex) == 0 or die "system (@latex) failed:( $! ):( $? )"; } exit 0;
      Note that File::Compare uses 2 arg open
Re: problem with while loop
by CountZero (Bishop) on Aug 01, 2008 at 05:32 UTC
    For a Perl script that does all you want for compiling .tex files (including running the programs to make indexes and bibliographies): latexmk.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: problem with while loop
by Anonymous Monk on Aug 01, 2008 at 04:14 UTC
    Use the core module File::Compare
    use File::Compare; if (compare("file1","file2") == 0) { print "They're equal\n"; }
Re: problem with while loop
by GrandFather (Saint) on Aug 01, 2008 at 04:17 UTC

    Probably the global %logHash is causing you grief. Try moving it inside compare.


    Perl reduces RSI - it saves typing
Re: problem with while loop
by Anonymous Monk on Aug 01, 2008 at 04:18 UTC
    Unless you are using %logHash, $ctr and $diff outside of sub compare, they should be inside it;
      Thank you all perl monks, i moved %logHash, $diff inside my sub compare, now its working fine.
Re: problem with while loop
by Anonymous Monk on Aug 01, 2008 at 04:10 UTC
    you see how you're doing ||die, that's called error checking, and you're missing error checking for every system call