[comp.unix.questions] Perl question relating to pattern substitution

frechett@boulder.Colorado.EDU (-=Runaway Daemon=-) (01/05/91)

I am having some problems with the following perl script.  It is supposed to 
take a file with strings like A2448932B3F233490 which starts with 
%%HP        and the string itsself starts with "   and has a newline
every sixty characters and a " terminats it, and convert this mess into
a binary file that can be downloaded to the hp48sx calculator.  This script
was posted, with the statement that it works fine on the poster's system.
Unfortunately, I don't know what that was.  Here is the script and 
my comments after the @s.

#!/usr/local/bin/perl 
# unasc
# A perl program to extract a HP-48 binary from a text file containing a 
# ->ASC program. 
#
# Usage: unasc file > binfile
#
# Written by Wayne Scott  1990

while (<>) {
	next if (!(/%%HP/../"$/)); 	# Skip everything but program
	chop;				
	$file .= $_;		
}
@ I added the following two lines and commented out the one after that 
@ as my perl had no idea what to make of \w.
$file =~ s/"//g;
$file =~ s/%%HP//g;
# $file =~ s/.*"(\w*)\w\w\w\w".*/\1/;	# strip newlines, ", and CRC

@ This is the line that I am having problems with.. Simply, it replaces every
@ two characters with the string "pack(C,hex(\1.\2)"  whis is totally useless
@ as it is supposed to be converting ascii to binary.  
$file =~ s/(.)(.)/pack(C,hex(\1.\2))/eg;  # convert ascii to bin

print $file;

-----------------------------------------------------------------
The problem is that my perl doesn't recognize pack as being a function
which is understandable as I can't find reference to pack in 
TFM for ed, ex, sed, awk, perl, or C.   Anyone know how I might be able to
work around this little bug and get this to work.. Remember, this works on
some machine somewhere...  Any help would be appreciated.

	ian
--
-=Runaway Daemon=-

tchrist@convex.COM (Tom Christiansen) (01/05/91)

From the keyboard of frechett@horton.Colorado.EDU.Colorado.EDU:

:I am having some problems with the following perl script.  It is supposed to 
:take a file with strings like A2448932B3F233490 which starts with 
:%%HP        and the string itsself starts with "   and has a newline
:every sixty characters and a " terminats it, and convert this mess into
:a binary file that can be downloaded to the hp48sx calculator.  This script
:was posted, with the statement that it works fine on the poster's system.
:Unfortunately, I don't know what that was.  Here is the script and 
:my comments after the @s.

:#!/usr/local/bin/perl 
:# unasc
:# A perl program to extract a HP-48 binary from a text file containing a 
:# ->ASC program. 
:#
:# Usage: unasc file > binfile
:#
:# Written by Wayne Scott  1990
:
:while (<>) {
:	next if (!(/%%HP/../"$/)); 	# Skip everything but program
:	chop;				
:	$file .= $_;		
:}
:@ I added the following two lines and commented out the one after that 
:@ as my perl had no idea what to make of \w.
:$file =~ s/"//g;
:$file =~ s/%%HP//g;
:# $file =~ s/.*"(\w*)\w\w\w\w".*/\1/;	# strip newlines, ", and CRC

Well, that's awfully strange.  I don't know that there's ever been
a perl that didn't know what to make of \w.  Your replacement won't
do the same thing, as the original code is stripping off the 4 or
more "word" ([a-zA-Z0-9_] characters between the quotes.  That 
expression could be more efficiently written:

    $file ~= s/"(\w*)\w{4}"/$1/;

but it should still work.

:@ This is the line that I am having problems with.. Simply, it replaces every
:@ two characters with the string "pack(C,hex(\1.\2)"  whis is totally useless
:@ as it is supposed to be converting ascii to binary.  
:$file =~ s/(.)(.)/pack(C,hex(\1.\2))/eg;  # convert ascii to bin
:
:print $file;

:The problem is that my perl doesn't recognize pack as being a function
:which is understandable as I can't find reference to pack in 
:TFM for ed, ex, sed, awk, perl, or C.   Anyone know how I might be able to
:work around this little bug and get this to work.. Remember, this works on
:some machine somewhere...  Any help would be appreciated.

I suspect that you're running on an OLD version of perl.  Pack has
been around since perl, version 3.  Maybe you're running perl 2.
Pack is a function that takes a template and converts some text data
into binary format, which is what you want.

It may be that you have pack() and it's just choking on the unadorned
C where it would really prefer "C".  Newer patchlevels accept unquoted
literal strings, but older ones don't.  I guess I'd probably write 
the conversion this way:

    $file =~ s/(..)/pack("C",hex($1))/eg;  # convert ascii to bin

Note that the following obfuscation is actually around 30% faster -- which
is unfortunately still pretty slow by my standards:

    print pack("C" x ((length($file))/2), 
	    grep($_ ne '' && (($_ = hex) || 1), split(/(..)/, $file)));

You could also save time if you wouldn't put the whole thing in 
one big string before you translate it, but rather do it at line at
a time.

Does that fix up your program?

--tom
--
Tom Christiansen		tchrist@convex.com	convex!tchrist

	"EMACS belongs in <sys/errno.h>: Editor Too Big!" -me

merlyn@iwarp.intel.com (Randal L. Schwartz) (01/06/91)

In article <1991Jan5.051035.7202@csn.org>, frechett@boulder (-=Runaway Daemon=-) writes:
| @ This is the line that I am having problems with.. Simply, it replaces every
| @ two characters with the string "pack(C,hex(\1.\2)"  whis is totally useless
| @ as it is supposed to be converting ascii to binary.  
| $file =~ s/(.)(.)/pack(C,hex(\1.\2))/eg;  # convert ascii to bin

| The problem is that my perl doesn't recognize pack as being a function
| which is understandable as I can't find reference to pack in 
| TFM for ed, ex, sed, awk, perl, or C.   Anyone know how I might be able to
| work around this little bug and get this to work.. Remember, this works on
| some machine somewhere...  Any help would be appreciated.

You have an old Perl (the "pack" function wasn't in earlier Perls).
Say perl -v.  If you don't get at least version 3.0, get yerself a
brand-spankin'-new Perl.  Version 3.0 patchlevel 41 is the latest, and
can be fetched from most GNU places as well as devvax.jpl.nasa.com.

Just another Perl hacker,
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel: putting the 'backward' in 'backward compatible'..."====/