meaning of $^S

A

allenjo5

The meaning of $^S seems to have changed from perl 5.6.0 to perl 5.8.0.
There is mention in the Changes files of it being broken prior to perl
5.8.0, but if so, I no longer understand how it is supposed to work.
Take this module:

-----------
package T;

print '$^S is ', defined $^S ? "defined: '$^S'\n" : "not defined\n";

1;
-----------

With perl 560 I get these (sensible to me) results:

$ perl560 T.pm
$^S is defined: '0'

$ perl560 -MT -e 1
$^S is not defined

But with perl 588, I get this:

$ perl588 T.pm
$^S is defined: '0'

$ perl588 -MT -e 1
$^S is defined: '1'

The man page for $^S says this:

"$^S
$EXCEPTIONS_BEING_CAUGHT

Current state of the interpreter.

$^S State
--------- -------------------
undef Parsing module/eval
true (1) Executing an eval
false (0) Otherwise

The first state may happen in $SIG{__DIE__} and $SIG{__WARN__}
handlers."

It would seem to me that in the -MT case, the module is in fact being
"parsed", which would mean that $^S should be undef. For $^S to be 1,
it should be "executing an eval", which I don't believe -MT is doing.
In other words, the 560 behavior looks more correct to me than the 588
behavior. What am I missing here?

John.
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to

package T;
print '$^S is ', defined $^S ? "defined: '$^S'\n" : "not defined\n";
1;
$ perl588 T.pm
$^S is defined: '0'

$ perl588 -MT -e 1
$^S is defined: '1'
The man page for $^S says this:

"$^S
$EXCEPTIONS_BEING_CAUGHT

Current state of the interpreter.

$^S State
--------- -------------------
undef Parsing module/eval
true (1) Executing an eval
false (0) Otherwise

The first state may happen in $SIG{__DIE__} and $SIG{__WARN__}
handlers."

It would seem to me that in the -MT case, the module is in fact being
"parsed"

When code is run, its parsing is, obviously, done. undef means that
the interpreter is "not in consistent state"; e.g., if a syntax error
is discovered in the currently-parsed code, a warning is emitted
*immediately*, without changing the STATE of the parsing engine. So
$SIG{__WARN__} may be called DURING the actual parsing.

Hope this helps,
Ilya
 
A

allenjo5

When code is run, its parsing is, obviously, done. undef means that
the interpreter is "not in consistent state"; e.g., if a syntax error
is discovered in the currently-parsed code, a warning is emitted
*immediately*, without changing the STATE of the parsing engine. So
$SIG{__WARN__} may be called DURING the actual parsing.

I guess this makes some sense. I verified that $^S is indeed undef in
a $SIG{__WARN__} sub invoked by an error. Are $SIG{__DIE__} and
$SIG{__WARN__} the only cases when $^S can be undef? If so, that
should be added to the man page.

Also, as my test shows, $^S == 1 when "use"-ing a module ($^S == 0 in a
require). This is not "executing an eval" is it? Perhaps the man page
should be changed to "executing an eval or use statement".

Finally, the name $EXCEPTIONS_BEING_CAUGHT seems poor to me, but it it
no doubt way too late to change that.

John.
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to

I guess this makes some sense. I verified that $^S is indeed undef in
a $SIG{__WARN__} sub invoked by an error. Are $SIG{__DIE__} and
$SIG{__WARN__} the only cases when $^S can be undef? If so, that
should be added to the man page.

Even if it were true, this should NOT be added to the man page. Such
an addition will prohibit further progress.
Also, as my test shows, $^S == 1 when "use"-ing a module ($^S == 0 in a
require). This is not "executing an eval" is it? Perhaps the man page
should be changed to "executing an eval or use statement".

If this is so, this means you found another bug. What is the test case?
Finally, the name $EXCEPTIONS_BEING_CAUGHT seems poor to me

Why? AFAICS, this is exactly the semantic of $^S == 1.

Yours,
Ilya
 
A

allenjo5

Even if it were true, this should NOT be added to the man page. Such
an addition will prohibit further progress.

Progress toward what? Clarifying the pod would be some progress in my
mind.
Why? AFAICS, this is exactly the semantic of $^S == 1.

$^S == 1 means "executing an eval or use statement". How is that an
exception? Only in the rare case of $^S being undef is it _probably_
an exception. Wouldn't $INTERPRETER_STATE be far more appropriate?
 
A

allenjo5

This brings me to the question, why this (and other) variables reflecting
the "internal interpreter state" were made visible form Perl as $^<x>
variables. I think there are many PL_xxxxx locations witin the Perl
library which do this as well - but they aren't accessible from a Perl
script. So what was the actual reason for implementing
$^D, $^H, $^M, $^P and $^S`?
Are there examples of code which actually make use of these variables?

Perl strives to not hide anything from the coder - provided he wants to
get at it. As for real world use, I can only speak for $^S: I use it
to allow a perl script to detect if it is running from the shell
command line or being use'd as a module:

if ($^S == 1) {
# being use'd
} else if ($^S == 0) {
# running from the command line
}

I have several scripts/modules that do this. But perhaps there is a
better way...?

John.
 
A

Anno Siegel

Perl strives to not hide anything from the coder - provided he wants to
get at it. As for real world use, I can only speak for $^S: I use it
to allow a perl script to detect if it is running from the shell
command line or being use'd as a module:

if ($^S == 1) {
# being use'd
} else if ($^S == 0) {
# running from the command line
}

I have several scripts/modules that do this. But perhaps there is a
better way...?

I use

if ( defined caller ) {
# called through use() or require()
} else {
# called top level
}

I find that quite intuitive. $^S I would have to look up.

Anno
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to


Since some functionality in core scripts/modules will not work without
these variables present.
Grep.

to allow a perl script to detect if it is running from the shell
command line or being use'd as a module:

if ($^S == 1) {
# being use'd
} else if ($^S == 0) {
# running from the command line
}

Thus you "use" a bug in the implementation of $^S. According to its
documentation, it should be in the "exceptions are not catched" state
in both cases. Use caller() instead.

Hope this helps,
Ilya
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to

$^S == 1 means "executing an eval or use statement". How is that an
exception?

Who said it is? $^S shows what is going to happen IF an exception occurs.

Hope this helps,
Ilya
 
A

allenjo5

Thus you "use" a bug in the implementation of $^S. According to its
documentation, it should be in the "exceptions are not catched" state
in both cases. Use caller() instead.

First, yup, caller() is clearly the way to go. How could I have missed
that? Oh well.

As for $^S, I am now thoroughly confused. I thought it could be
interrogated to discover the state that perl is in at the time, hence
"S" as the mnemonic for State. The pod says - I think unclearly - that
there are three possible states:

$^S State
--------- -------------------
undef Parsing module/eval
true (1) Executing an eval
false (0) Otherwise

And that the undef state can happen in a $SIG{__WARN__} or
$SIG{__DIE__}. Are those the only times that $^S can be undef? I
don't know. But _something_ more should be said about that in the pod.

And $^S == 1 in a "use" statement as well, so I thought that should be
added to the pod. Are you saying that $^S being 1 in a "use" is
actually a bug?

I can make no sense of the documented "states" and the "english" alias
for this being $EXCEPTIONS_BEING_CAUGHT. If the value really meant
that "exceptions were being caught", $^S should be 1 in a WARN or DIE
handler, not undef.

John.
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to

$^S State
--------- -------------------
undef Parsing module/eval
true (1) Executing an eval
false (0) Otherwise

And that the undef state can happen in a $SIG{__WARN__} or
$SIG{__DIE__}. Are those the only times that $^S can be undef? I
don't know. But _something_ more should be said about that in the pod.

As I said, there should not. defined $^S has *semantic*: you can call
eval""/require.
And $^S == 1 in a "use" statement as well

A bug. I was too lazy when implementing $^S, and did not notice that
during use() there is an extra "frame" (do not rememeber what it is
created for). Apparently, nobody bothered to fix this...

Hope this helps,
Ilya
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,573
Members
45,046
Latest member
Gavizuho

Latest Threads

Top