From: Marc Girod on
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
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

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
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

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