develooper Front page | perl.perl5.porters | Postings from February 2003

binmode(FH => ":layer") should overwrite the previous layer

Thread Next
From:
Dan Kogai
Date:
February 26, 2003 00:51
Subject:
binmode(FH => ":layer") should overwrite the previous layer
Message ID:
7D5819A8-4967-11D7-8DB0-000393AE4244@dan.co.jp
Nick XS and Porters,

   I have painfully learned that binmode(FH => ":layer") STACKS layer 
instead of overwriting the layer.  In other words,

	binmode(FH => ":first"); binmode(FH => ":second");

means

	binmode(FH => ":first :second");

Nick, I think this is rather a feature instead of a bug but see this.

# Module.pm
package Encode::ROT13;
use base qw(Encode::Encoding);
__PACKAGE__->Define('rot13');
sub encode($$;$){
     my ($obj, $str, $chk) = @_;
     $str =~ tr/A-Za-z/N-ZA-Mn-za-m/;
     $_[1] = '' if $chk; # this is what in-place edit means
     return $str;
}
# Jr pna or ynml yvxr guvf;
*decode = \&encode;

package Module;
binmode STDOUT => ":encoding(rot13)";
1;

# main.pl
use Module;
# binmode STDOUT => ":encoding(rot13)"; # Comment me out and see!
print "Perl\n";
__END__

With binmode() in main.pl commented out, main.pl prints "Crey", just as 
expected.  But when you uncomment that, it magically prints "Perl" !

This counterintuitive nature of binmode() was accidentally found by 
SUGAWARA Hajime <sugawara@hdt.co.jp> when he tried to 'use encoding 
"euc-jp";' both in his module and script.  Since encoding.pm implicitly 
binmode()s STDIN and STDOUT, something totally unexpeded happened.

For the time being I have made a patch to encoding.pm so it inimport()s 
before import()s (Actual patch right after the signature) to make it 
behave as expected.  But considering the facts:

* That filehandles are global -- what if the modules called installs 
the layer and the user of the module has no idea that it does?
* There is no known way to tell what layers a given filehands are in -- 
so you can't sensibly binmode(FH => ":pop") ?

the behavior of binmode() should be modified so that it overwrites 
instead of stacks.

Dan the Encode Maintainer

diff -u -r1.41 encoding.pm
--- encoding.pm 2003/02/06 01:52:11     1.41
+++ encoding.pm 2003/02/26 07:39:21
@@ -39,6 +39,7 @@
         require Carp;
         Carp::croak("Unknown encoding '$name'");
      }
+    __PACKAGE__->unimport; # clean up binmode
      $name = $enc->name; # canonize
      unless ($arg{Filter}) {
         $DEBUG and warn "_exception($name) = ", _exception($name);


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About