Well, that's the most obscure Perl bug I've ever seen

K

Kyle T. Jones

I guess instead of a snark, I could have offered this (it's ugly,
there's undoubtedly an easier way to do it, I invite criticism, but I'm
95% it'll work just fine):

#!/usr/bin/perl;
use strict;
use warnings;

sub appendtotop{
my ($olddir, $newdir, $filename)=@_;
my $oldfile=$olddir.$filename;
my $newfile=$newdir.$filename;
open(OLDPERL, $oldfile) || die "cannot open file $oldfile";
open(NEWPERL, ">$newfile")|| die "cannot open file $newfile";
my @contents=<OLDPERL>;
my ($isstrict, $iswarned)=(0,0);

#this looks kind of odd because I'm only checking the first ten
#lines to make sure we don't have duplicate use whatevers
#but it's more because you mentioned that you were dropping
#use strict and use warnings in blocks later on in the code

for (my $i=0; $i<10; $i++){
if($contents[$i]){
$isstrict=1 if($contents[$i]=~/use strict;/);
$iswarned=1 if($contents[$i]=~/use warnings;/);
}
}
my @appendmaterial;
$appendmaterial[0]="use strict;\n" unless($isstrict==1);
$appendmaterial[1]="use warnings;\n" unless($iswarned==1);
print NEWPERL @appendmaterial;
print NEWPERL @contents;
return;
}


my $currentperlscripts='/var/www/cgi-bin/';
my $newdirectory='/var/www/new-cgi-bin/';
opendir(OLD,$currentperlscripts) || die "Cannot opendir
$currentperlscripts: $!";
my @files=readdir(OLD);
foreach (@files){
if($_=~/\.pl/){
appendtotop($currentperlscripts, $newdirectory, $_);
}
}
 
P

Peter J. Holzer

There's no such thing in Perl. Evaluating a ref in numeric context
numifies it. It's the same as

float a;
int b = 3;
a = b;

in C, which is actually an implicit function call

There is no implicit function call here. Did you mean an implicit cast?
(though Perl caches the result, which C doesn't).

Well, the result is stored in a. So it is "cached" in some sense.
And the compiler is of course free to cache the value of any expression
somewhere in a temporary variable if it thinks it can reuse it. So in some
code like:

x = a + b * c + d;
y = a + b * c;

a C compiler probably will "cache" the result of "a + b * c", while the
perl compiler won't.

hp
 
P

Peter J. Holzer

I guess instead of a snark, I could have offered this (it's ugly,
there's undoubtedly an easier way to do it, I invite criticism, but I'm
95% it'll work just fine):
[script snipped]

I seem to be missing the part of the script which fixes all the errors
and warnings ...

hp
 
F

Frank Seitz

Ben said:
There's no such thing in Perl.

Hm. Perl has no data structures?
Evaluating a ref in numeric context numifies it.

Yes. But it is perl that interprets and converts the
the scalar (= data structure), not the scalar itself.
It's the same as

float a;
int b = 3;
a = b;

in C, which is actually an implicit function call (though Perl caches
the result, which C doesn't).

Would you say about line 3: b "returns" a float?

Frank
--
Dipl.-Inform. Frank Seitz
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel

Blog: http://www.fseitz.de/blog
XING-Profil: http://www.xing.com/profile/Frank_Seitz2
 
P

Permostat

I was fixing a problem that "just appeared" in some otherwise working
code. There were no syntax errors and the program ran fine - it's just
that the result went from being correct to being uttterly and completely
wrong. A bit of lateral thinking and investigation solved the problem.
However, for your entertainment and education, here's a cut down version
that exhibts the same effect:

$

# set up a counter
$i = 0;

for($j = 0; $j < 10; $j++) {
  print "j = $j\n";
  $i++;}

print "j = $j, i=$i\n";

which, when run produces:

root: perl bug.pl
j = 0
j = 1
j = 2
j = 3
j = 4
j = 5
j = 6
j = 7
j = 8
j = 9
j = 10, i=6308506

Yup, it's that solitary "$" all alone in the middle of nowhere.
it only took me about an hour and a half to spot - probably because
I was looking in entirely the wrong place as the real-life code had
a large block of comment lines between the "$" and "$i = 0;"

All I can say is aaaaaaaaaaaaaaaaaah!

Blast it with piss.

Herm=
 
K

Kyle T. Jones

Peter said:
I guess instead of a snark, I could have offered this (it's ugly,
there's undoubtedly an easier way to do it, I invite criticism, but I'm
95% it'll work just fine):
[script snipped]

I seem to be missing the part of the script which fixes all the errors
and warnings ...

hp

So add in a section that splits the script into subs and main then
parses each for the first instance of declared variables, and append my
to the front of each. That's likely to be a huge percentage of the
errors you'll hit adding in use strict to scripts authored by folks that
don't use, well, use strict.

You know what though - I did think he had said he had "thousands of
scripts" - but what he said was "several scripts of a thousand lines of
code". So, that changes things.

Tell you what, though - you go and create something that "fixes all the
errors and warnings" for any perl script (or any language for that
matter). You'll be rich, @#$%^.

Cheers.
 
P

Peter J. Holzer

I phrased that badly: there is no C function call. But there is an
operation more complicated than simple assignment, such as might result
from the inlining of a function that does the conversion.

The operation has about the same order of complexity as other C
operators. You wouldn't say that "+" is actually an implicit function call,
would you? Even though for some data types on some architectures an
addition is actually implemented as a function (maybe not even inlined).

I was avoiding the term 'cast' because it means two different things in
C. Sometimes it means an actual conversion from one representation to
another, sometimes it means simply reinterpreting the existing bits as a
different type (casts between pointers to compatible structures, for
instance).

Conceptionally it is always a conversion. However, some conversions
happen to be noops. For example, the conversion int -> unsigned int is
arithmetically defined in the standard: For a nonnegative int i,
(unsigned)i is i, for a negative int i, (unsigned)i is i + UINT_MAX + 1.
If you happen to use two's complement representation (all modern
architectures, AFAIK) of signed ints, that's a noop, if you use
sign-magnitude or one's complement, you need to fiddle some bits.
Similarly for pointers: Theoretically pointers to different types could
be different at the bit level, but I don't know any modern architecture
where they are - so casts between pointers are always a noop in
practice (I also remember the quote "all struct pointers smell the
same", but I'm not sure whether that means they have to be the same at
the bit level - it's been too long since I participated in comp.std.c).

That's true, of course. OTOH, if you have

void bar(int x)
{
float f = x;
}

void foo()
{
int a = 1;
float b = a;
bar(a);
}

it won't, unless it can inline bar to assist the optimization, whereas
perl would.

True. OTOH, if the C compiler can inline function calls, it will
probably also optimize away foo() completely ;-).

hp
 
P

Peter J. Holzer

Peter said:
I guess instead of a snark, I could have offered this (it's ugly,
there's undoubtedly an easier way to do it, I invite criticism, but I'm
95% it'll work just fine):
[script snipped]

I seem to be missing the part of the script which fixes all the errors
and warnings ...

So add in a section that splits the script into subs and main then
parses each for the first instance of declared variables, and append my
to the front of each. That's likely to be a huge percentage of the
errors you'll hit adding in use strict to scripts authored by folks that
don't use, well, use strict.

You know what though - I did think he had said he had "thousands of
scripts" - but what he said was "several scripts of a thousand lines of
code". So, that changes things.

Tell you what, though - you go and create something that "fixes all the
errors and warnings" for any perl script (or any language for that
matter). You'll be rich, @#$%^.

Well, that was sort of my point. Just mechanically adding a line "use
strict;" is easy, but that almost certainly isn't what keeps the OP from
doing it. Wading through the plethora of warnings and errors and
deciding how to fix them is the real work and that cannot be easily
automated. Automatically generating my() or our() declarations isn't
quite trivial due to the irregular syntax of Perl but should be possible
- but I think the danger of covering up or creating bugs is greater than
the benefit.

I'd do it like this:

When you need to change anything in a script the very first time, you
have to spend some time anyway to read and understand it. So this is the
perfect time to add "use warnings; use strict" an fix all the resulting
errors and warnings as you go. (This is also an advantage of "use
warnings" over "-w" - it affects only the source file, not any used
modules, so you can add it one file at a time)

hp
 
K

Kyle T. Jones

Peter said:
Peter said:
I guess instead of a snark, I could have offered this (it's ugly,
there's undoubtedly an easier way to do it, I invite criticism, but I'm
95% it'll work just fine):

[script snipped]

I seem to be missing the part of the script which fixes all the errors
and warnings ...
So add in a section that splits the script into subs and main then
parses each for the first instance of declared variables, and append my
to the front of each. That's likely to be a huge percentage of the
errors you'll hit adding in use strict to scripts authored by folks that
don't use, well, use strict.

You know what though - I did think he had said he had "thousands of
scripts" - but what he said was "several scripts of a thousand lines of
code". So, that changes things.

Tell you what, though - you go and create something that "fixes all the
errors and warnings" for any perl script (or any language for that
matter). You'll be rich, @#$%^.

Well, that was sort of my point. Just mechanically adding a line "use
strict;" is easy, but that almost certainly isn't what keeps the OP from
doing it.

Especially given that it was just a couple scripts, what I suggested
wouldn't be helpful at all.

Wading through the plethora of warnings and errors and
deciding how to fix them is the real work and that cannot be easily
automated. Automatically generating my() or our() declarations isn't
quite trivial due to the irregular syntax of Perl but should be possible
- but I think the danger of covering up or creating bugs is greater than
the benefit.

I'd do it like this:

When you need to change anything in a script the very first time, you
have to spend some time anyway to read and understand it. So this is the
perfect time to add "use warnings; use strict" an fix all the resulting
errors and warnings as you go. (This is also an advantage of "use
warnings" over "-w" - it affects only the source file, not any used
modules, so you can add it one file at a time)

hp

Check.

Cheers.
 

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,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top