Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Wrapping the open() built-in

by almut (Canon)
on Oct 26, 2006 at 21:18 UTC ( [id://580833]=perlquestion: print w/replies, xml ) Need Help??

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

Hi All,

I need to replace Perl's built-in open() function. The reason I want to do this is described in detail in another recent post of mine. In a nutshell, I have to do encoding conversions on filename arguments (unicode -> CP932).

Actually, it's not only open() I need to wrap, but open() appears to be the most flexible beast of those, and I'd very much appreciate if some of you wise monks could take a look at what I currently have, and let me know if I've overlooked something...

_____ I18N/Japanese.pm (the 'compatibility' module) _____

package I18N::Japanese; use Encode 'encode'; use Symbol 'qualify_to_ref'; # eventually, determine this dynamically my $encoding = "cp932"; # this is meant to take effect for whoever uses us require encoding; encoding->import($encoding); # override/wrap Perl built-ins that take or return filenames # (... snippage of all but open()-wrapper) *CORE::GLOBAL::open = sub (*@) { my $fhref = \$_[0]; my $autov = !defined $_[0]; my $fh = qualify_to_ref(shift, scalar caller); # pass filehandle up to caller when "open my $f, ..." $$fhref = $fh if $autov; my ($arg2, $arg3, @args) = convert_encoding(@_); # need to handle the different prototypes seperately if (@_ >= 3) { CORE::open $fh, $arg2, $arg3, @args; } elsif (@_ == 2) { if (defined $arg3) { CORE::open $fh, $arg2, $arg3; } else { # must be undef _syntactically_ CORE::open $fh, $arg2, undef; } } elsif (@_ == 1) { CORE::open $fh, $arg2; } else { CORE::open $fh; } }; sub convert_encoding { return ( map ref(\$_) eq 'SCALAR' ? encode($encoding, $_) : $_, @_ + ); } 1;

_____ using the replaced open() _____

use I18N::Japanese; open F, ">", "myfile" and print F "foo\n"; open my $f, ">", "myfile" or die $!; print $f "foo\n"; # ...

I believe this code is able to handle all various usages of open() ... but please don't hesitate to prove me wrong ;) Otherwise, well, I'd be glad to share this snippet with whoever in need might google this up in the future.

(Note: the encoding conversion aspect is not what I'm worried about at the moment, but rather whether the replaced open() is still behaving like the built-in one, interface-wise)

Thanks,
Almut

Replies are listed 'Best First'.
Re: Wrapping the open() built-in
by vkon (Curate) on Oct 26, 2006 at 21:53 UTC
    Perl do not process unicode filenames from command line, but this is rather OS's fault, not Perl one.

    BTW, what operating Windows you have..?
    Err, what system operates your windows?
    what is your $^O? :)

    All in all, you'll better off overriding 'open' for such purposes, the danger do not worth the risk!

    If your $^O is MSWin32, then following my advice could help: Re: enumerate windows unicode filenames

    HTH

Re: Wrapping the open() built-in
by Anonymous Monk on Oct 27, 2006 at 05:40 UTC
    Don't touch core, use Export.

      I deliberately chose to use CORE::GLOBAL in my specific case (despite the unless-you-know-what-you're-doing type of warnings in "Overriding Built-in Functions", Chap 11.3, the Camel Book).

      Only having a vague idea of what the existing code1 looks like, I thought that, all in all, I might be better off replacing the built-ins globally. As I understand it, Exporter does only export into a specific namespace, e.g.

      _____ MySystem.pm _____

      package MySystem; use Exporter 'import'; @EXPORT = qw(system); sub system { print "wrapped system(): @_\n"; } 1;

      _____ test.pl _____

      #!/usr/bin/perl use MySystem; system "echo foo"; package SomeOtherModule; system "echo bar";

      would print

      $ ./test.pl wrapped system(): echo foo bar

      i.e. the second call of system() is not being wrapped...

      I'd rather not have to take care of such subleties (not all that sure I'm not getting myself into other subtleties this way, though... ;)

      Could you elaborate on why not to use CORE:: ?

      Almut

      _____

      1  as I mentioned in Using literal Japanese filenames in legacy CP932 encoding with system(), etc., the idea behind writing a jperl compatibility module is that the large number of existing scripts wouldn't need to be touched

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://580833]
Approved by Paladin
Front-paged by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (7)
As of 2024-04-18 07:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found