Link to home
Start Free TrialLog in
Avatar of Randall-B
Randall-B

asked on

Perl for Wamp: How to Run Scripts that Require Unix Diff?

I have a working installation of WAMP on XP Pro. I installed the Wamp add-on of ActiveState Perl and it is working fine for simple scripts, but it does not include Diff. I need to use a Perl script that relies on the Unix Diff pod.  Is there a Wamp-compatible replacement for the Unix Diff?  If I install and run Cygwin (http://www.cygwin.com) on Windows, can Wamp's Perl use the Unix-like Diff module in Cygwin?
Avatar of manav_mathur
manav_mathur

Avatar of Randall-B

ASKER

manav_mathur,
    From the description, it looks like that module does not include all the functionality of the Unix diff, but it's worth a try.
    How would I install the .pm module in Wamp's Perl add-on? Do I just copy the .pm file to the C:\wamp\perl\lib folder, or do I have to adjust something to make Perl aware of it?
  How would I adjust a script that currently uses calls to the Unix diff?  For example, my current Unix Perl script has:
        open(DIFF,"diff -f $DiffArgs $OldFile $NewFile |");
(you can see the whole script at http://www.foyastar.com/htmldiff_pl-3.htm).
   Thanks.
Do you have a C:\wamp\perl\bin folder?? If yes, is there an executable by the name of ppm??
manav_mathur,
   Yes, I have ppm.bat .  Is that the one?

Also, I noticed that the "manifest" in the text::diff download file shows some paths including a directory I don't have ( t\ ) and it has a make file. Do I have to compile it?
No. Since you are on windows, you can simply download the zip file corresponding to the module from
http://ppm.activestate.com/PPMPackages/

and follow the instructions in the readme file.
I'm a bit confused by their readme instructions.  It says: "To install this ActiveState PPM package, run the following command in the current directory:  ppm install Text-Diff.ppd ."
    But I don't know which directory they mean by "the current directory."
And I don't know which command line it refers to (the Windows explorer "run" command, the DOS prompt, or some kind of Perl command)?  Please explain. Thanks.
ok
go to the directory where you unxipped the file and issue this command
c:/perl/bin/ppm install Text-Diff.ppd
Do you mean I should open a DOS shell prompt and type that command at the DOS prompt?
OK. From the zip, I copied the following files into c:\wamp\perl\bin where the ppm.bat file is:

1) Text-Diff.ppd
2) MSWin32-x86-multi-thread-5.8
   Then I went to that directory in DOS and issued the command:
C:\wamp\perl\bin>ppm install Text-Diff.ppd
   But these error messages came up:

Bad name after privlibexp' at C:/wamp/perl/lib/Config.pm line 1219.
Compilation failed in require at C:/wamp/perl/lib/DynaLoader.pm line 25.
BEGIN failed--compilation aborted at C:/wamp/perl/lib/DynaLoader.pm line 25.
Compilation failed in require at C:/wamp/perl/site/lib/Win32API/Registry.pm li
 10.
Compilation failed in require at C:/wamp/perl/site/lib/Win32/TieRegistry.pm li
 26.
BEGIN failed--compilation aborted at C:/wamp/perl/site/lib/Win32/TieRegistry.p
line 26.
Compilation failed in require at ppm.bat line 15.
BEGIN failed--compilation aborted at ppm.bat line 15.

I noticed that Algorithm-Diff is mentioned as a dependency in the Text-Diff.ppd file, so I download Algorithm-Diff and tried to install that, but the same errors come up. What could be wrong?
By the way, here is what some of the failed lines say:

Line 1219 of Config.pm says:
    'privlibexp' => 'c:\wamp\perl\\lib',    

Line 25 of C:/wamp/perl/lib/DynaLoader.pm says:  
    Use config;

Line 10 of C:/wamp/perl/site/lib/Win32API/Registry.pm  says:
    require DynaLoader;

Line 26 of  C:/wamp/perl/site/lib/Win32/TieRegistry.pm  says:
    use Win32API::Registry 0.12 qw( :KEY_ :HKEY_ :REG_ );

Line 15 of  bin\ppm.bat  says:
    use Win32::TieRegistry;

Do you see why those would fail?  Thanks.
ASKER CERTIFIED SOLUTION
Avatar of manav_mathur
manav_mathur

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
That double slashes caught my attention, too, but then I noticed the Config.pm file has them all throughout, before the last directory name. So maybe it's supposed to be that way, but I don't know why.

Maybe I'll try gnuWin32 package.  If I can get it installed, do you think my Perl script will need any modifications in order to use it? Thanks.
It doesnt need them as long as its enclosed in single quotes. Atleast thats what I know.
You should try out the functionality of the gnuWin32 diff tool. AFAIK, it should be similar to the GNU diff, although I have never used it.
I got the gnuWin32 installed.  It installs a diff.exe file in C:\Program Files\GnuWin32\bin .  It seems to run OK from the DOS command prompt, like:
       C:\Program Files\GnuWin32\bin> diff C:\wamp\www\old.htm C:\wamp\www\new.htm
   However, I can't get it to run from my Perl script.  I changed this line:
               open(DIFF,"diff -f $DiffArgs $OldFile $NewFile |");
to this:
               open(DIFF,"C:\Program Files\GnuWin32\bin\diff.exe -f $DiffArgs
               $OldFile $NewFile |");
but that did not work.
    Any ideas on how to get this diff to run from Perl?  Thanks.
Avatar of ozo
how about "C:\\Program Files\\GnuWin32\\bin\\diff.exe
No, that doesn't work either.  I'm not getting an error message; but it seems like Perl is ignoring that part of the script (I can tell that it is going past those lines and is just printing the output from lines 262 - 269 (which is supposed to print after the diff output):

262 print $FH "<i>How to read this comparison:</i>
263 <ul>
264  <li>removed old parts are marked as $Style{StartOld}this one$Style{EndOld}
265    <li>new parts are marked as $Style{StartNew}this one$Style{EndOld}
266  </ul>";
267 print $FH "HTML Mode is experimental." unless($TM);
268 print $FH "  <hr>
269 ";

It's strange. The script worked perfectly on a commercial Unix host. What could be wrong here on Wamp?
I just noticed I had commented out the line:
   use Pod::Usage;
when I first tried to run the script on Perl, because that line caused a 500 server error on Wamp (but not on Unix).  I guess the Usage pod is not included with ActiveState Perl on Wamp.
   I wonder if the lack of that "use Pod::Usage" line could be one problem (although it still seems like the diff is not getting called properly from the script, either).  How would I add the Usage pod?
Do you have pod::Usage installed??
you should include

use CGI::Carp qw(fatalsToBrowser warningsToBrowser) ;
warningsToBrowser(1) ;

somewhere at the top of the script, to see the actual errors in your script on the web page instead of the standard 500 error.
No, I didn't have Usage.pm installed.  (I copied the Usage.pm file into the lib directory a few minutes ago and tested with you error handler, and here is the result:

Bad name after privlibexp' at C:/wamp/perl/lib/Config.pm line 1219.

Compilation failed in require at C:/wamp/perl/lib/Pod/Usage.pm line 403.

BEGIN failed--compilation aborted at C:/wamp/perl/lib/Pod/Usage.pm line 403.

Compilation failed in require at C:/wamp/www/cgi-bin/htmldiff-5.cgi line 11 (*that is the line with the "Use Pod::Usage;" statement*) .

BEGIN failed--compilation aborted at C:/wamp/www/cgi-bin/htmldiff-5.cgi line 11.)

I probably didn't install the Usage.pm properly. But the installation package is like the ones that failed yesterday, so I guess I'm stuck.

     By the way, when I comment out line 11 (so I'm not asking it to use the Usage pod), the script does not give any error messages; it runs, but it fails to show the diff results. (Instead of showing the diff results, it simply prints some html that is supposed to print after displaying the diff results.)
Did you simply copy the file, or did you install it using the ppm utility??
The file should be located as
C:/wamp/perl/lib/Pod/Usage.pm
   Oh, I just discovered something:  I had been looking in lib instead of lib/Pod.  When I looked in lib/Pod, I see that it already has Usage.pm installed there as part of the ActiveState package.
   So why would the Use Pod::Usage statement cause an error? Maybe because of the "bad name" error in Config.pm at 1219?
put
use Diagnostics;
at the top of your script....
   Another discovery:  I don't think the script really requires the Usage pod.  I tried removing that line and ran it on a Unix server, and it works fine without it.  I think that line is a vestigage of part of the script that I had deleted (it was used for a "verbose" switch; I removed it because it didn't seem to make any difference). So I think we can ignore the Usage problem and just comment it out.

   When I put "use Diagnostics;", I get a 500 error.  
Here's the error:
Bad name after privlibexp' at C:/wamp/perl/lib/Config.pm line 1219.
Compilation failed in require at C:/wamp/perl/lib/Diagnostics.pm line 176.
BEGIN failed--compilation aborted at C:/wamp/perl/lib/Diagnostics.pm line 176.
Compilation failed in require at C:/wamp/www/cgi-bin/htmldiff-5.cgi line 6.
BEGIN failed--compilation aborted at C:/wamp/www/cgi-bin/htmldiff-5.cgi line 6.
   It all seems to be caused by line 1219 in Config.pm.  
That line says:   1219   'privlibexp' => 'c:\wamp\perl\\lib',
   As a brave soul, I edited that line to have only one backslash, but the script still gives the same error, pointing to the same line.  So it's not the slash, and I went ahead and put it back in.
    At this point, I think the best thing to do is:  comment out the "Use Pod::Usage" line, and then try to get it to use the diff.  I think the real problem is that it is not running diff.  My script line 1209 says:

open(DIFF,"C:\Program Files\GnuWin32\bin\diff.exe -f $DiffArgs $OldFile $NewFile |");

We have tried different variations on that line, and nothing works.  So I'm stumped. Maybe it's just not compatible, although the documentation makes it look like the Unix diff and this win32 diff are almost the same.



- Are you sure some condition is making the opn statement not run??
- Just run a simple
open "echo 'abcde' |"

to see if the problem is in the script or something to do with diff??

The script runs without error messages when I use this line (although it does not show the diffs):

      open(DIFF,"C:\Program Files\GnuWin32\bin\diff.exe -f $DiffArgs $OldFile $NewFile |");

But when I comment out that line, and this this line instead,

        open "echo 'abcde' |"
then I get this error referring to the next line:

syntax error at C:/wamp/www/cgi-bin/htmldiff-5.cgi line 212, near "open"
Execution of C:/wamp/www/cgi-bin/htmldiff-5.cgi aborted due to compilation errors.
    The Line 212 mentioned in the error message is:

open(FH,$OldFile);

But that error is only when I comment out the original line and use the test line. Also, it is important to note that the whole script works perfectly on a Unix server.
Correction:
   I just noticed I had forgotten to put the semicolon at the end of the open "echo 'abcde' |";  .  
   When I added the  ;  the script runs without any error messages, but it does not print out the "abcde".
my mistake, try
open(DIFF,"echo 'abcde' |");
OK. I did this, and it printed  'abcde' :

open(DIFF,"echo 'abcde' |");
  while(<DIFF>){
     print;
  }
  print "";
So it is paying attention to that part of the script, at least.  But nothing is printed for "DIFF" when I do this:
      open(DIFF,"C:\Program Files\GnuWin32\bin\diff $OldFile $NewFile |");
        while(<DIFF>){
            print;
         }
        print "";
  I tried different variations, like   \diff.exe  ,  \diff ,  diff.exe -f $DiffArgs , etc.  Nothing works.  Any ideas?
- Does running diff on the command line work on the same 2 files that you are testing against??
- Do $OldFile, $NewFile refer to the sone sample file. AFAIK, diff gives no output if it doesnt find a difference betweent he 2 files.
Yes, it works on the command line. I copied the the two files into the GnuWin32\bin folder, and here is the DOS command line output:

C:\Program Files\GnuWin32\bin>diff old.htm new.htm
4c4
< <TITLE>OLD</TITLE>
---
> <TITLE>NEW</TITLE>
8,9c8,9
< <P ALIGN="CENTER"><B>OLD TEST</B></P>
< <P>This is the old file.</P>
---
> <P ALIGN="CENTER"><B>NEW TEST</B></P>
> <P>This is the new file.</P>

I tried setting the script to call the files from that folder, and still no Diff output from the script.
Does this output on STDOUT or STDERR??
The only thing I see is in lines 236-238, which appears to be STDOUT:
    my $FH;
    $FH=\*STDOUT;
    print $FH "\n" ;

By the way, I also tried a very short script just to test the diff, and it doesn't work either:

#!c:/wamp/perl/bin/perl
    print "Content-type: text/html\n\n";
open(DIFF,"C:\Program Files\GnuWin32\bin\diff.exe C:\wamp\www\old.htm C:\wamp\www\new.htm |");
      while(<DIFF>){
       print;
      }
     print "";

I was just trying to print the direct results of the command line. There is no error message; just a blank white page. Is there a better way to test printing the direct output of diff?
#!c:/wamp/perl/bin/perl
print "Content-type: text/html\n\n";
open(DIFF,"C:\Program Files\GnuWin32\bin\diff.exe C:\wamp\www\old.htm C:\wamp\www\new.htm 2>&1 |") or die "$!" ;
while(<DIFF>){
  print;
}
print "End of command";
close(DIFF) ;
OK. That printed "End of command," but nothing else.  I wonder why diff works on the command line but is not working from Perl?
Wierd!! Can you try

#!c:/wamp/perl/bin/perl
print "Content-type: text/html\n\n";
open(DIFF,"C:\\Program Files\\GnuWin32\\bin\\diff.exe C:\\wamp\\www\\old.htm C:\\wamp\\www\\new.htm 2>&1 |") or die "$!" ;
while(<DIFF>){
  print;
}
print "End of command";
close(DIFF) ;


and this too, just to see


#!c:/wamp/perl/bin/perl
print "Content-type: text/html\n\n";
my $oput = `C:\Program Files\GnuWin32\bin\diff.exe C:\wamp\www\old.htm C:\wamp\www\new.htm 2>&1` ;
print $oput;
print "End of command";
close(DIFF) ;
The last test only prints "End of command."  But maybe you're on to something with the first of those two tests, which outputs this:  

'C:\Program' is not recognized as an internal or external command, operable program or batch file. End of command

It looked like it was having a problem with the space between Program  Files, so I copied the GnuWin32 folder to the wamp folder and tried this:

#!c:/wamp/perl/bin/perl
print "Content-type: text/html\n\n";
open(DIFF,"C:\\wamp\\GnuWin32\\bin\\diff.exe C:\\wamp\\www\\old.htm C:\\wamp\\www\\new.htm 2>&1 |") or die "$!" ;
while(<DIFF>){
  print;
}
print "End of command";
close(DIFF) ;

and it printed the diff output!  Now I need to work that into the main script and see what happens.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Great! C:\\Progra~1\\  . . . works
   How should be work this in to the main script?
 
wherever you want to place it....
I placed this line where the old open( ) statement use to be in the main file, but the script still does not process to show the diff:

open(DIFF,"C:\\Progra~1\\GnuWin32\\bin\\diff.exe C:\\wamp\\www\\old.htm C:\\wamp\\www\\new.htm 2>&1 |") or die "$!" ;

(But when I added a debug print like  while(<DIFF>){  print; }, then it does manually show it.)
You must be doing something with the DIFF filehandle??
I just added the -f switch after diff.exe, and it is finally showing something (although not at all the same as when run on Unix). Maybe a different switch is required on GnuWin32. I'll check the documentation, because I know GnuWin32 uses switches for different effects than the Unix diff.  Maybe that's the only problem now.  
    But here is what the script does with DIFF after it opens it:

open(FH,$OldFile);
push(@OldLines,'');
push(@NewLines,'');
while(<FH>){
  chomp;
  push(@OldLines,$_);
  push(@NewLines,$_);
  warn"unclosed or unopened tag detected, malfunction warning: $_" if(/<[^>]*$|^[^<]*>/);
}
close(FH);
$iii=0;

# no strict 'ref';
my $TmpFile="$ENV{HOME}/.HtmlDiff";
my $FH;
$FH=\*STDOUT;
print $FH "\n" ;

#
while(<DIFF>){
  if(/^d(\d+)(\s+(\d+))?$/){
    $iiii= defined $2 ? $2 : $1;
    for($ii=$iii;$ii<$1;$ii++){PrintLine('Equal',$NewLines[$ii])}
    for($ii=$1;$ii<=$iiii;$ii++){PrintLine('Old',$NewLines[$ii])}
    $iii=$iiii+1;
  }
  elsif(/^c(\d+)(\s+(\d+))?$/){
    $iiii= defined $2 ? $2 : $1;
    for($ii=$iii;$ii<$1;$ii++){PrintLine('Equal',$NewLines[$ii])}
    for($ii=$1;$ii<=$iiii;$ii++){PrintLine('Old',$NewLines[$ii])}
    while(defined($is=<DIFF>)){
      chomp;
      if($is=~/^\.$/){last}
      else{PrintLine('New',$is)}
    }
    $iii=$iiii+1;
  }
  elsif(/^a(\d+)$/){
    $iiii=$1;
    for($ii=$iii;$ii<=$1;$ii++){PrintLine('Equal',$NewLines[$ii])}
    while(defined($is=<DIFF>)){
      if($is=~/^\.$/){last}
      else{PrintLine('New',$is)}
    }
    $iii=$1+1;
  }
}
for($ii=$iii;$ii<=$#NewLines;$ii++){PrintLine('Equal',$NewLines[$ii])}
unlink($OldFile,$NewFile);
print $FH "<hr>";
# close($FH);

Yes, you need to check the documentation.
Thanks manav_mathur,
   I'll see if I can figure it out from here, based on the documentation. You have been very patient and helpful. I think you've answered my original question, so I'm accepting your answer.  I really appreciate all the time you spent on this, so I'm increasing the points. Thanks again.
You're welcome.