using binmode in the strings program (and other ppt programs) 
Author Message
 using binmode in the strings program (and other ppt programs)

The ppt project is wonderful, see http://www.*-*-*.com/
details of the Perl Power Tools, e.g. a port of most Unix utilites
to run in pure perl.  From my perspective the big win is that these
now run on a PC.
Unfortunately when I tried using strings
on a Microsoft Powerpoint file it stopped after 6 characters -- when it
hit the first Ctrl+Z.  (The file full of Ctrl+Z characters.)

The full program (only 40 lines, but not copied here) is in:
http://www.*-*-*.com/

I believe the fix involves adding binmode.
But I am not exactly how or where to do that, given that binmode
requires a filehandle as an argument.
I tried adding
binmode STDIN;
just after the while(<>) but that failed to work.
So I wound up hard coding the file name I wanted and changed the
read loop from
while (<>) {
to
open(IN, "myfile.ppt"); # !!! Bad
binmode IN;
while (<IN>) {

Clearly hard coding the file name is bogus.  (This code illustrates the
maxim: there is more than one way to do it WRONG.)

1.  What is the right way to fix this?  Note that the code earlier does
the common: while ($ARGV[0] =~ /^-/) {
2.  The doc for binmode says it is ignored on Unix.
Should binmode be used routinely in (many of) the ppt programs, so they
will work on Microsoft sytems.

Thanks in advance,
Steve
---

Fidelity Investments   82 Devonshire St. R24D    Boston MA 02109
There is nothing so practical as a good theory.  Comments are by me,
not Fidelity Investments, its subsidiaries or affiliates.



Fri, 02 Nov 2001 03:00:00 GMT  
 using binmode in the strings program (and other ppt programs)

# Should binmode be used routinely in (many of) the ppt programs, so they
# will work on Microsoft sytems.

I think so, where an input file is known to be binary.  I can think of no
reason why it shouldn't be.

As to the right way to fix this file, something along the lines of a for
loop, probably.


    local *F;
    my $l;
    open F, "< $f" or die $!;
    binmode F;
    while (<F>) {
      while (/$pat/og) {
        printf "%07d ", ($l+pos()-length $&) if $opt_o;
        print $&, "\n" ;
      }
      $l += length;
    }
  }

Dunno if it works.  You can test it.  :)

--

%PGPKey = ('B76E72AD', [1024, '0824090B CE73CA10  1FF77F13 8180B6B6'])



Sat, 03 Nov 2001 03:00:00 GMT  
 using binmode in the strings program (and other ppt programs)

Quote:
Chris Nandor writes:


 >
 > # Should binmode be used routinely in (many of) the ppt programs, so they
 > # will work on Microsoft sytems.
 >
 > As to the right way to fix this file, something along the lines of a for
 > loop, probably.
 >

[snip]
 >   }

But this skips some of the magic of <>, which also works on standard
input.  perlop would seem to suggest this:


while ($ARGV = shift) {
    open(ARGV, $ARGV);
    binmode(ARGV);      # my addition
    while (<ARGV>) {
        ...         # code for each line
    }

Quote:
}

But perlop claims this doesn't work, since it treats <ARGV> as
non-magical.  I've always wondered what that means: the only thing I
can figure is that $. doesn't keep incrementing between files.  A
couple simple tests suggest that it doesn't blow up.  I ask all of
you: is it true that this is safe so long as one does not depend on
<>-like behavior of $.?  (It's phrases like that last one that make
Perl so much fun to write about).  Thanks,

     David Saff



Sat, 03 Nov 2001 03:00:00 GMT  
 using binmode in the strings program (and other ppt programs)

Quote:

> But perlop claims this doesn't work, since it treats <ARGV> as
> non-magical.

Perlop is right.  Consider the following code; a fiver says you can't
guess what output it produces on NT.

        #!perl -w
        use strict;


        # Create three test files containing some ^Z characters:

        for my $filenum (0 .. 2)
        {       my $filename = "test$filenum.txt";
                open F, ">$filename"
                        or die "Can't create $filename:\n$!";

                binmode F;
                print F join "\cZ\n",
                        $filenum * 3 .. $filenum * 3 + 2, '';
                close F;
        }




        my $filesdone = 0;
        my $ARGV;

        {       print "File $ARGV:\n";
                open ARGV, $ARGV
                        or die "Can't open $ARGV:\n$!";
                binmode ARGV;
                $_ = join '', <>;
                tr/\cZ/!/;
                print "\$_ = $_\n\$. = $.\n";
                ++ $filesdone;
        }


                ")\n$filesdone file(s) done\n"

On NT, this prints:


        File test0.txt:
        $_ = 0!
        1!
        2!
        36
        $. = 5

        1 file(s) done

What's going on?  Well, as far as I can tell, the first file is open()ed
and binmode()d as you expect.  But the diamond operator causes all lines
in all files to be read -- and so we only go through the loop once, not
three times.  When those files are automagically opened, they aren't
binmode()d -- and so we only read the first line in each file, without
its trailing newline.

To make the code work, you have to change the name of the file handle
from ARGV to something else and you have to specify it inside the
diamond operator.  If you write the second while-loop like this --


        {       print "File $ARGV:\n";
                open G, $ARGV
                        or die "Can't open $ARGV:\n$!";
                binmode G;
                $_ = join '', <G>;
                tr/\cZ/!/;
                print "\$_ = $_\n\$. = $.\n";
                ++ $filesdone;
        }

-- then the code does what you expect.

Incidentally, don't forget the defined() at the top of the loop.  It's
perfectly possible for a file to be called '0'.

Markus

--
Delete the 'delete this bit' bit of my address to reply



Sun, 04 Nov 2001 03:00:00 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. how to call one program through another program and capture the out put of another program

2. calling perl program from within a C program?

3. passwd program from Programming Perl

4. The *undump* program referenced in the Programming Perl manual

5. VERSIONS 3.1 -- program to retrieve version numbers of programs

6. Programming Perl Programs

7. Problems: programming serial port w/ Perl, can't find program cu

8. tee like program to pipe to another program?

9. Encrypting in one program and Decrypting in another program

10. Encrypting in one program and Decrypting in another program

11. How to call perl program from C program ?

12. Need: PERL program to capture internet interactions of a given WINDOWS program

 

 
Powered by phpBB® Forum Software