Why is $^O assignable?

A

Andreas Pürzer

Greetings!

Recently I've stumbled over code where someone assigned to $^0. This
seemed rather nonsensical to me, so I tried:

D:\Temp>perl -MData::Dumper -we "use File::Spec; print Dumper(\%INC);"
$VAR1 = {
'warnings/register.pm' => 'C:/Perl/lib/warnings/register.pm',
'bytes.pm' => 'C:/Perl/lib/bytes.pm',
'XSLoader.pm' => 'C:/Perl/lib/XSLoader.pm',
'Carp.pm' => 'C:/Perl/lib/Carp.pm',
'C:/Perl/site/lib/sitecustomize.pl' =>
'C:/Perl/site/lib/sitecustomize.pl',
'File/Spec/Unix.pm' => 'C:/Perl/lib/File/Spec/Unix.pm',
'vars.pm' => 'C:/Perl/lib/vars.pm',
'strict.pm' => 'C:/Perl/lib/strict.pm',
'Exporter.pm' => 'C:/Perl/lib/Exporter.pm',
'warnings.pm' => 'C:/Perl/lib/warnings.pm',
'File/Spec.pm' => 'C:/Perl/lib/File/Spec.pm',
'overload.pm' => 'C:/Perl/lib/overload.pm',
'File/Spec/Win32.pm' => 'C:/Perl/lib/File/Spec/Win32.pm',
'Data/Dumper.pm' => 'C:/Perl/lib/Data/Dumper.pm'
};

So far, so good, everything as expected. File::Spec::Win32 shows up
because, as you may have guessed from my use of Doublequotes, I'm on
MSWin32.
But then I tried:

D:\Temp>perl -MData::Dumper -we "BEGIN { $^O = 'epoc'}; use File::Spec;
print Dumper(\%INC)"
$VAR1 = {
'File/Spec/Epoc.pm' => 'C:/Perl/lib/File/Spec/Epoc.pm',
'warnings/register.pm' => 'C:/Perl/lib/warnings/register.pm',
'bytes.pm' => 'C:/Perl/lib/bytes.pm',
'XSLoader.pm' => 'C:/Perl/lib/XSLoader.pm',
'Carp.pm' => 'C:/Perl/lib/Carp.pm',
'C:/Perl/site/lib/sitecustomize.pl' =>
'C:/Perl/site/lib/sitecustomize.pl',
'File/Spec/Unix.pm' => 'C:/Perl/lib/File/Spec/Unix.pm',
'vars.pm' => 'C:/Perl/lib/vars.pm',
'strict.pm' => 'C:/Perl/lib/strict.pm',
'Exporter.pm' => 'C:/Perl/lib/Exporter.pm',
'warnings.pm' => 'C:/Perl/lib/warnings.pm',
'File/Spec.pm' => 'C:/Perl/lib/File/Spec.pm',
'overload.pm' => 'C:/Perl/lib/overload.pm',
'Data/Dumper.pm' => 'C:/Perl/lib/Data/Dumper.pm'
};

No more File::Spec::Win32, but File::Spec::Epoc!
According to `perldoc perlvar`:
$OSNAME
$^O The name of the operating system under which this copy of Perl
was built, as determined during the configuration process.

So, I'm a little lost why it's even possible to (ab-)use $^O this way,
and I fail to see the possible benefits of doing so. OTOH, I'd have
expected to see something along the lines of:
Modification of a read-only value attempted

So, is this a bug or a feature? ;->
Could someone please shed some light on this?

Thank you,
Andreas Puerzer
 
S

Sisyphus

..
..
So, I'm a little lost why it's even possible to (ab-)use $^O this way,

Damn good question ... I don't know the answer (and I look forward to seeing
responses from folk who *do* know).
and I fail to see the possible benefits of doing so.

Me too. (Though there are benefits in being able to modify other %Config
values - see, for example, ExtUtils::FakeConfig.)

Mind you, it's interesting to note that:
1) $Config::Config{osname} is readonly;
2) $Config::Config{osname} can be modifed.

--------------------------------
C:\>perl -MConfig -we "$Config::Config{osname} = 'crap'"
%Config::Config is read-only

C:\>perl -MConfig -we "$obj=tied %Config::Config;$obj->{osname} =
'crap';print $Config::Config{osname}"
crap
 
B

Ben Morrow

Quoth "Sisyphus said:
.
.

Damn good question ... I don't know the answer (and I look forward to seeing
responses from folk who *do* know).

I can't answer, but there is special code in mg.c to make it possible,
and it has been there since at least 5.003.

I guess perhaps for testing? Presumably the File::Spec test suite, for
instance, contains some tests along the lines of

{
local $^O = 'MSWin32';
require File::Spec;
File::Spec->import;
# check that File::Spec::Win32 got loaded
}

Ben
 
S

Sisyphus

..
..
I guess perhaps for testing? Presumably the File::Spec test suite, for
instance, contains some tests along the lines of

{
local $^O = 'MSWin32';
require File::Spec;
File::Spec->import;
# check that File::Spec::Win32 got loaded
}

Seems a reasonable suggestion ... but, then again, I wonder if there's any
point in checking that File::Spec::Win32 gets loaded when the operating
system is not Win32. It would be a bit if a waste if you're running Solaris
and the tests fail simply because File::Spec::Win32 failed to load.

In other words why not simply:

require File::Spec;
File::Spec->import;
# check that File::Spec::$Config::Config{osname} got loaded.

(I actually did take a look at t/spec.t ... but couldn't summons the energy
to parse it :)

Cheers,
Rob
 
X

xhoster

Andreas_Pürzer said:
Greetings!

Recently I've stumbled over code where someone assigned to $^0. This
seemed rather nonsensical to me, so I tried:

D:\Temp>perl -MData::Dumper -we "use File::Spec; print Dumper(\%INC);"
$VAR1 = {
'warnings/register.pm' => 'C:/Perl/lib/warnings/register.pm',
'bytes.pm' => 'C:/Perl/lib/bytes.pm',
'XSLoader.pm' => 'C:/Perl/lib/XSLoader.pm',
'Carp.pm' => 'C:/Perl/lib/Carp.pm',
'C:/Perl/site/lib/sitecustomize.pl' =>
'C:/Perl/site/lib/sitecustomize.pl',
'File/Spec/Unix.pm' => 'C:/Perl/lib/File/Spec/Unix.pm',
'vars.pm' => 'C:/Perl/lib/vars.pm',
'strict.pm' => 'C:/Perl/lib/strict.pm',
'Exporter.pm' => 'C:/Perl/lib/Exporter.pm',
'warnings.pm' => 'C:/Perl/lib/warnings.pm',
'File/Spec.pm' => 'C:/Perl/lib/File/Spec.pm',
'overload.pm' => 'C:/Perl/lib/overload.pm',
'File/Spec/Win32.pm' => 'C:/Perl/lib/File/Spec/Win32.pm',
'Data/Dumper.pm' => 'C:/Perl/lib/Data/Dumper.pm'
};

So far, so good, everything as expected. File::Spec::Win32 shows up
because, as you may have guessed from my use of Doublequotes, I'm on
MSWin32.
But then I tried:

D:\Temp>perl -MData::Dumper -we "BEGIN { $^O = 'epoc'}; use File::Spec;
print Dumper(\%INC)"
$VAR1 = {
'File/Spec/Epoc.pm' => 'C:/Perl/lib/File/Spec/Epoc.pm',
'warnings/register.pm' => 'C:/Perl/lib/warnings/register.pm',
'bytes.pm' => 'C:/Perl/lib/bytes.pm',
'XSLoader.pm' => 'C:/Perl/lib/XSLoader.pm',
'Carp.pm' => 'C:/Perl/lib/Carp.pm',
'C:/Perl/site/lib/sitecustomize.pl' =>
'C:/Perl/site/lib/sitecustomize.pl',
'File/Spec/Unix.pm' => 'C:/Perl/lib/File/Spec/Unix.pm',
'vars.pm' => 'C:/Perl/lib/vars.pm',
'strict.pm' => 'C:/Perl/lib/strict.pm',
'Exporter.pm' => 'C:/Perl/lib/Exporter.pm',
'warnings.pm' => 'C:/Perl/lib/warnings.pm',
'File/Spec.pm' => 'C:/Perl/lib/File/Spec.pm',
'overload.pm' => 'C:/Perl/lib/overload.pm',
'Data/Dumper.pm' => 'C:/Perl/lib/Data/Dumper.pm'
};

No more File::Spec::Win32, but File::Spec::Epoc!
According to `perldoc perlvar`:
$OSNAME
$^O The name of the operating system under which this copy of Perl
was built, as determined during the configuration process.

So, I'm a little lost why it's even possible to (ab-)use $^O this way,
and I fail to see the possible benefits of doing so.

I can see doing that for various testing, debugging, and development
purposes.


Xho
 
A

Andreas Pürzer

I can see doing that for various testing, debugging, and development
purposes.


Xho

Yes, testing, I had thought of that too, with the following scenario:

Developing a Module that is intended to behave differently on differing
platforms. Say I'm on Win32 and want to test the part of the Module
designed for MacOs, what good would it be to trick the Module into
believing being on MacOs, if, in fact it's still on Win32?
I mean, none of the MacOs code could possibly work, right?
At least not the code depending on the filesystem.
That's why I discarded the testing-answer.

But then again, for example File::Spec->devnull() could very well be
tested with $^O-magic.

So, your answer seems to be absolutely perfect.

I guess I was struck by perlvar talking about $^O in the past, so I
considered it to be a constant, the $OSNAME perl was built on.
Somehow I was under the impression there were 2 $^O-Variables, something
like $BUILD_OSNAME and $RUN_OSNAME. My bad...

Thanks for clearing things up,
Andreas Pürzer
 
A

Andreas Pürzer

Ben said:
I can't answer, but there is special code in mg.c to make it possible,
and it has been there since at least 5.003.

Magical Case '\017', I see...
So $^0 can be used as both the historical value while building, as well
as the currently running OS, very nice.
But why am I surprised, it's Perl! ;->
I guess perhaps for testing? Presumably the File::Spec test suite, for
instance, contains some tests along the lines of

{
local $^O = 'MSWin32';
require File::Spec;
File::Spec->import;
# check that File::Spec::Win32 got loaded
}

Ben

This seems to be 'The Answer'.

Thanks to both Sisyphus and Ben Morrow for helping me understand,
Andreas Pürzer
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top