Prev: FAQ 5.38 How do I select a random line from a file?
Next: *main::exit = sub {die @_,"\n"} (was: eval exit/exec)
From: Marc Girod on 27 Feb 2010 14:33 On Feb 27, 6:56 pm, Marc Girod <marc.gi...(a)gmail.com> wrote: > That is... without the debugger, the errors I get are: And under the debugger, in my AutoTrace output, the first error is: ClearCase::Wrapper::CODE(0x1ae0ab8)(/cygdrive/o/atcctest/ClearCase- Wrapper/blib/lib/ClearCase/Wrapper.pm:119): 119: next unless eval "exists \&$tglob"; BEGIN not safe after errors--compilation aborted at /usr/lib/ perl5/5.10/Carp/Heavy.pm line 11. Compilation failed in require at /usr/lib/perl5/5.10/Carp.pm line 33. Attempt to reload Carp/Heavy.pm aborted. Compilation failed in require at /usr/lib/perl5/5.10/Carp.pm line 33. This is a place in the ClearCase::Wrapper.pm code, where it examines out of the AutoSplit modules produced from Wrapper functions, which ones correspond to 'commands' of the tool being emulated: # Now the overlay module is read in. We need to examine its # newly-created symbol table, determine which functions # it defined, and import them here. The same basic thing is # done for the base package later. my %names = %{"${pkg}::"}; for (keys %names) { my $tglob = "${pkg}::$_"; # Skip functions that can't be names of valid cleartool ops. next if m%^_?[A-Z]%; # Skip typeglobs that don't involve functions. We can only # do this test under >=5.6.0 since exists() on a coderef # is a new feature. The eval is needed to avoid a compile- # time error in <5.6.0. if ($] >= 5.006) { next unless eval "exists \&$tglob"; } The AutoTrace transcript shows earlier 'require Carp;' but for some reason, doesn't trace its loading, contrarily to blib, Cwd, strict, Exporter, etc... This only shows that I don't understand what gets traced. Marc
From: Marc Girod on 27 Feb 2010 17:14 On Feb 27, 9:06 pm, Ben Morrow <b...(a)morrow.me.uk> wrote: > I don't understand what you are trying to achieve here. What the code > above will actually do is: any code compiled in package 'main' after the > BEGIN block runs, that calls 'exit' or 'exec', will call your custom > subs instead. Is that what you meant? I have no package explicitely named 'main', so obviously I have misunderstood something you wrote earlier. Now, this makes indeed the 'redefine' errors 'self-explanatory' as you say. Or... maybe not quite. I understood I was redefining the meaning of a global 'exec' in different package contexts. > (Exporting into a specific package > like that is usually a very mad idea. > What if your caller isn't main:: > but some other package?) Sorry, but what is 'main'? Is there a main? In C, there is a 'main' symbol. It is garanteed to be unique, in the context of every program. This is what I understood. In fact, I would still believe this is OK. So, it is now that I must be misunderstanding you... At least I don't get errors mentioning '*main::'... I am writing a wrapper for a command line tool, so my caller will be 'main'... The caller is the 'cleartool.plx' script. > When you say 'member' you mean 'method', or perhaps 'function'? Method > calls to ClearCase::Argv->exec won't be affected. Calls to 'exit' or > 'exec' from within the ClearCase::Argv package won't be affected, they > will call the builtin as usual. 'Method' is the word Smalltalk used. 'Member' (function) is the word for C++. 'Function' is the C word for something slightly different (but called 'procedure' in Fortran). OK, there are functions in Lisp as well, and there are significant differences... The terminology is very confusing. By member, I mean a function in the restricted namespace of a class (aka package). In addition, I assume that it takes a first (syntactically implicit) argument being a reference to an instance of the class. This aspect is irrelevant here. > Overrides of builtins must be imported while in another package, in an > attempt to stop you doing it accidentally. That is, > > package Foo; > *main::exec = sub {...}; > > will be recognized as an override while in package main, but > > package main; > *exec = sub {...}; > > won't. Since I presume your module starts with > > package ClearCase::Argv; > > you shouldn't need another package statement inside the BEGIN block. I have: - a toplevl script: cleartool.plx (the wrapper) - a ClearCase::Wrapper module, which does define some functions, and use exit and exec in ways I want to override - a ClearCase::Argv module, which is used to implement the functions, and offers one 'exec' among other, which itself uses exit, in a way which I want to override - two specialized wrapper modules: - ClearCase::Wrapper::DSB which defines more functions (among which the 'des' which I use in my tests), and does use exit and exec in ways I want to override. - ClearCase::Wrapper::MGI of which I am the author, and thus does *not* use exit nor exec . These two modules are 'discovered' dynamically and loaded by ClearCase::Wrapper. There could in theory be more of them. So, my understanding is that I must override exec and exit in at least 3 packages: ClearCase::Argv ClearCase::Wrapper ClearCase::Wrapper::DSB (and probably in a 4th one: Argv, which is used by ClearCase::Argv). Where do I do this, and how do I prefix the 2 names? So far, I thought the functions I was overriding were global main:: functions, and I had to do it *in* every package. Obviously, this was wrong... Thanks Marc
From: Ben Morrow on 27 Feb 2010 17:58 Quoth Marc Girod <marc.girod(a)gmail.com>: > On Feb 27, 9:06�pm, Ben Morrow <b...(a)morrow.me.uk> wrote: > > > I don't understand what you are trying to achieve here. What the code > > above will actually do is: any code compiled in package 'main' after the > > BEGIN block runs, that calls 'exit' or 'exec', will call your custom > > subs instead. Is that what you meant? > > I have no package explicitely named 'main', > so obviously I have misunderstood something > you wrote earlier. Perl starts in package 'main', so any code that comes before a 'package' statement is compiled in package main. I think you perlhaps need to review perlmod. > Now, this makes indeed the 'redefine' errors > 'self-explanatory' as you say. > Or... maybe not quite. I understood I was > redefining the meaning of a global 'exec' > in different package contexts. Hmmm. Not quite. A statement like exec "one", "two"; is usually compiled as a builtin. However, if there is a sub in the current package called 'exec', *and* that sub was exported into the current package by a different package, then it is compiled as a call to that sub instead. > > (Exporting into a specific package > > like that is usually a very mad idea. > > What if your caller isn't main:: > > but some other package?) > > Sorry, but what is 'main'? Is there a main? > In C, there is a 'main' symbol. It is > garanteed to be unique, in the context of > every program. This is what I understood. No, not at all. 'main' is just the name of the default package. See above. > In fact, I would still believe this is OK. > So, it is now that I must be misunderstanding > you... > At least I don't get errors mentioning > '*main::'... > > I am writing a wrapper for a command line > tool, so my caller will be 'main'... > The caller is the 'cleartool.plx' script. OK, but since you are writing this as a module you must be at least implicitly assuming it might be used elsewhere. The usual method is to use 'caller' in your package's 'import' method, which will tell you which package the 'use' statement happed from: package ClearCase::Argv; sub import { my $pkg = caller; { no strict 'refs'; *{"$pkg\::exec"} = sub { ... }; } # whatever else you need to do # if you want Exporter to work you can goto &Exporter::import; } Since it appears you are working 'backwards', and trying to change the behaviour of modules that aren't loaded yet, you need to explicitly export into ClearCase::Wrapper &c. > > When you say 'member' you mean 'method', or perhaps 'function'? Method > > calls to ClearCase::Argv->exec won't be affected. Calls to 'exit' or > > 'exec' from within the ClearCase::Argv package won't be affected, they > > will call the builtin as usual. > > 'Method' is the word Smalltalk used. > 'Member' (function) is the word for C++. > 'Function' is the C word for something > slightly different (but called 'procedure' > in Fortran). OK, there are functions in Lisp > as well, and there are significant > differences... The terminology is very > confusing. By member, I mean a function > in the restricted namespace of a class > (aka package). In addition, I assume that it > takes a first (syntactically implicit) > argument being a reference to an instance > of the class. This aspect is irrelevant here. OK. 'Member' is not usually used in that sense in Perl. A function call (or sub call) looks like foo(1, 2, 3); or Some::Package::foo(1, 2, 3); The first form will look for a builtin with that name, or a 'sub foo' in the current package. The second form will always look for a 'sub foo' in Some::Package. A method call looks like Some::Package->foo(1, 2); $obj->foo(1, 2); and will look for a 'sub foo' in Some::Package or anything it inherits from, and call it with an implicit first argument. Method calls never compile as builtins, so you can have a method called 'exec' with no problems. > > Overrides of builtins must be imported while in another package, in an > > attempt to stop you doing it accidentally. That is, > > > > � � package Foo; > > � � *main::exec = sub {...}; > > > > will be recognized as an override while in package main, but > > > > � � package main; > > � � *exec = sub {...}; > > > > won't. Since I presume your module starts with > > > > � � package ClearCase::Argv; > > > > you shouldn't need another package statement inside the BEGIN block. > > I have: > - a toplevl script: cleartool.plx (the wrapper) > - a ClearCase::Wrapper module, which does > define some functions, and use exit and exec > in ways I want to override > - a ClearCase::Argv module, which is used to > implement the functions, and offers one 'exec' > among other, which itself uses exit, in a way > which I want to override Is this 'exec' called as a method or a function? If it's called as a method, or if it's always called fully-qualified, you can simply ignore the fact it's called 'exec'. > - two specialized wrapper modules: > - ClearCase::Wrapper::DSB which defines more > functions (among which the 'des' which I use > in my tests), and does use exit and exec in > ways I want to override. > - ClearCase::Wrapper::MGI of which I am the > author, and thus does *not* use exit nor > exec . > These two modules are 'discovered' dynamically > and loaded by ClearCase::Wrapper. If you wish to override CC::W's use of 'exec', this must happen *before* CC::W is loaded. This probably means you need to switch to using a module MGI::ClearCase, which does the overrides and *then* loads ClearCase::Wrapper, and avoid loading CC::W in cleartool.plx. > There could in theory be more of them. > > So, my understanding is that I must override > exec and exit in at least 3 packages: > ClearCase::Argv > ClearCase::Wrapper > ClearCase::Wrapper::DSB > > (and probably in a 4th one: Argv, which is used > by ClearCase::Argv). > > Where do I do this, and how do I prefix the > 2 names? I would say you want something like this: package MGI::ClearCase; use warnings; use strict; my $exec = sub {...}; my $exit = sub {...}; *ClearCase::Wrapper::exec = $exec; *ClearCase::Wrapper::exit = $exit; # leave CC::A::exec, since it's already being redefined *ClearCase::Argv::exit = $exit; *ClearCase::Wrapper::DSB::exec = $exec; *ClearCase::Wrapper::DSB::exit = $exit; # 'require' not 'use', so it isn't loaded until after the overrides require ClearCase::Wrapper; # more stuff 1; You shouldn't get any 'redefined' warnings from this; if you do, it indicates a problem. > So far, I thought the functions I was overriding > were global main:: functions, and I had to do it > *in* every package. > Obviously, this was wrong... No, they aren't functions (that is, Perl subs) at all, they're builtins. They are recognised specially by the compiler, and compiled into special ops, *unless* they have been overridden at that point. Ben
From: Marc Girod on 27 Feb 2010 18:30 On Feb 27, 10:58 pm, Ben Morrow <b...(a)morrow.me.uk> wrote: > Perl starts in package 'main', so any code that comes before a 'package' > statement is compiled in package main. I think you perlhaps need to > review perlmod. Quite possible indeed. I'll do it. > Hmmm. Not quite. A statement like > > exec "one", "two"; > > is usually compiled as a builtin. However, if there is a sub in the > current package called 'exec', *and* that sub was exported into the > current package by a different package, then it is compiled as a call to > that sub instead. OK... The clause *and* is still not quite clear to me, but I'll try to work on it. > No, not at all. 'main' is just the name of the default package. See > above. OK. > OK, but since you are writing this as a module you must be at least > implicitly assuming it might be used elsewhere. The usual method is to > use 'caller' in your package's 'import' method, which will tell you > which package the 'use' statement happed from: The module is there... I believe in order to autoload the split code... i.e. for performance reasons. I don't see an other reason for now. I cannot really see that it would be 'used'. This is why it does exec and exit... > package ClearCase::Argv; > > sub import { > my $pkg = caller; > { > no strict 'refs'; > *{"$pkg\::exec"} = sub { ... }; > } > # whatever else you need to do > # if you want Exporter to work you can > goto &Exporter::import; > } > > Since it appears you are working 'backwards', and trying to change the > behaviour of modules that aren't loaded yet, you need to explicitly > export into ClearCase::Wrapper &c. > OK. 'Member' is not usually used in that sense in Perl. OK. I can just see that all my references only confuse me. > A function call (or sub call) looks like > > foo(1, 2, 3); > > or > > Some::Package::foo(1, 2, 3); > > The first form will look for a builtin with that name, or a 'sub foo' in > the current package. The second form will always look for a 'sub foo' in > Some::Package. A method call looks like > > Some::Package->foo(1, 2); > $obj->foo(1, 2); > > and will look for a 'sub foo' in Some::Package or anything it inherits > from, and call it with an implicit first argument. Method calls never > compile as builtins, so you can have a method called 'exec' with no > problems. But it is 'defined' in the same way... sub exec {...} whether is is intended as a function or a method? Something I have to grasp there... > Is this 'exec' called as a method or a function? If it's called as a > method, or if it's always called fully-qualified, you can simply ignore > the fact it's called 'exec'. Well, I now looked that indeed, it is always called as a method. Which explains, as you said, that there is no problem. > If you wish to override CC::W's use of 'exec', this must happen *before* > CC::W is loaded. This probably means you need to switch to using a > module MGI::ClearCase, which does the overrides and *then* loads > ClearCase::Wrapper, and avoid loading CC::W in cleartool.plx. OK... > I would say you want something like this: > > package MGI::ClearCase; > > use warnings; > use strict; > > my $exec = sub {...}; > my $exit = sub {...}; > > *ClearCase::Wrapper::exec = $exec; > *ClearCase::Wrapper::exit = $exit; > # leave CC::A::exec, since it's already being redefined > *ClearCase::Argv::exit = $exit; > *ClearCase::Wrapper::DSB::exec = $exec; > *ClearCase::Wrapper::DSB::exit = $exit; > > # 'require' not 'use', so it isn't loaded until after the overrides > require ClearCase::Wrapper; > > # more stuff > > 1; Because of the require, you don't need a BEGIN block? With a BEGIN block, I can 'use' the module? > You shouldn't get any 'redefined' warnings from this; if you do, it > indicates a problem. > No, they aren't functions (that is, Perl subs) at all, they're builtins. OK. builtins are not functions! Terminology again... > They are recognised specially by the compiler, and compiled into special > ops, *unless* they have been overridden at that point. OK. Now, I committed (produced) this: Foo> cat foo #!/usr/bin/perl -w use strict; BEGIN { package Bar; *Foo::exit = sub { die 'Died ', @_, "\n" } } use Foo; my $foo = new Foo; $foo->foo; print "foo end\n"; exit 0; Foo> perl -I. foo; echo $? Foo:foo Died 85 255 It looks already close... Thanks a lot for your patience! Marc
From: Ben Morrow on 27 Feb 2010 19:18
Quoth Marc Girod <marc.girod(a)gmail.com>: > On Feb 27, 10:58�pm, Ben Morrow <b...(a)morrow.me.uk> wrote: > > > Hmmm. Not quite. A statement like > > > > � � exec "one", "two"; > > > > is usually compiled as a builtin. However, if there is a sub in the > > current package called 'exec', *and* that sub was exported into the > > current package by a different package, then it is compiled as a call to > > that sub instead. > > OK... The clause *and* is still not quite clear to me, > but I'll try to work on it. It is confusing. Really the only way to understand it is to play with the different possibilities until you see what works and what doesn't. > > A function call (or sub call) looks like > > > > � � foo(1, 2, 3); > > > > or > > > > � � Some::Package::foo(1, 2, 3); > > > > The first form will look for a builtin with that name, or a 'sub foo' in > > the current package. The second form will always look for a 'sub foo' in > > Some::Package. A method call looks like > > > > � � Some::Package->foo(1, 2); > > � � $obj->foo(1, 2); > > > > and will look for a 'sub foo' in Some::Package or anything it inherits > > from, and call it with an implicit first argument. Method calls never > > compile as builtins, so you can have a method called 'exec' with no > > problems. > > But it is 'defined' in the same way... > > sub exec {...} > > whether is is intended as a function or a method? > Something I have to grasp there... Yes. This is also a little confusing, and occasionally somewhat annoying :). > > I would say you want something like this: > > > > � � package MGI::ClearCase; > > > > � � use warnings; > > � � use strict; > > > > � � my $exec = sub {...}; > > � � my $exit = sub {...}; > > > > � � *ClearCase::Wrapper::exec � � � = $exec; > > � � *ClearCase::Wrapper::exit � � � = $exit; > > � � # leave CC::A::exec, since it's already being redefined > > � � *ClearCase::Argv::exit � � � � �= $exit; > > � � *ClearCase::Wrapper::DSB::exec �= $exec; > > � � *ClearCase::Wrapper::DSB::exit �= $exit; > > > > � � # 'require' not 'use', so it isn't loaded until after the overrides > > � � require ClearCase::Wrapper; > > > > � � # more stuff > > > > � � 1; > > Because of the require, you don't need a BEGIN block? > With a BEGIN block, I can 'use' the module? Yes to both. > > No, they aren't functions (that is, Perl subs) at all, they're builtins. > > OK. builtins are not functions! > Terminology again... Despite being documented in perlfunc... :). Actually, 'function' is used somewhat ambiguously in Perl. It's often used to mean 'a Perl sub or a builtin', while here I was using it to mean 'something called as a function rather than a method'. What's important is to realise that the builtins are fundamentally different from the things you define with 'sub', and they are (intentionally) a lot harder to redefine. Ben |