http://www.perlmonks.org?node_id=1219500

topherv has asked for the wisdom of the Perl Monks concerning the following question:

Hi, After upgrading AIX on a host, my perl code no longer works. The upgrade included a perl update, from v5.10.1 to v5.20.1. If I roll back perl, the code works. But, I’d like to fix the code for new version. It looks like it’s all function prototyping issues. I am a perl newbie. I know I can change the functions, but I’m hoping I can add a line to the top to have the code use the old methods, like a use statement. (I’m afraid I’ll miss a function buried deep in the code on a branch that doesn’t get run often) Is there a way to have the code use the old method? Or do I need to find all the function declarations and correct them? If so, do I simply remove the ‘()’ or do I use function prototyping?

This code is distributed to many different platforms. So, whatever changes I make will need to run on the old and new version of perl. (So, adding “use V5.20;” is probably not an option, since they are still at older versions.)

The Error:

# /usr/dtha/bin/dtha_stack_info -L
Illegal declaration of subroutine dtha_stack::get_stack_list at /usr/dtha/bin/../lib/dtha_stack.pm line 244.
Compilation failed in require at /usr/dtha/bin/../lib/Dtha.pm line 80.
BEGIN failed--compilation aborted at /usr/dtha/bin/../lib/Dtha.pm line 80.
Compilation failed in require at /usr/dtha/bin/dtha_stack_info line 68.
BEGIN failed--compilation aborted at /usr/dtha/bin/dtha_stack_info line 68.

dtha_stack.pm code (starting at line 244):

sub get_stack_list() { my $self = shift; my $group = shift || '.*'; # group = PROD | TEST # read stacks.xml and build $DESCRIPTIONS hash parse_stacks(); my @stacks; foreach my $i (sort (keys %DESCRIPTIONS)) { push @stacks, $i if ( $DESCRIPTIONS{$i}{group} eq $gro +up ); push @stacks, $i if ( $group eq ".*" ); } return @stacks; } # endsub get_stack_list

I tried to change the code to how I thought it should be coded, but it complains too.

sub get_stack_list( $self, $group = '.*' ) { #my $self = shift; #my $group = shift || '.*'; # group = PROD | TEST # read stacks.xml and build $DESCRIPTIONS hash parse_stacks(); my @stacks; foreach my $i (sort (keys %DESCRIPTIONS)) { push @stacks, $i if ( $DESCRIPTIONS{$i}{group} eq $gro +up ); push @stacks, $i if ( $group eq ".*" ); } return @stacks; } # endsub get_stack_list

The above code gives:

# /usr/dtha/bin/dtha_stack_info -L
Illegal character in prototype for dtha_stack::get_stack_list : $self, $group = '.*'  at /usr/dtha/bin/../lib/dtha_stack.pm line 244.
Illegal declaration of subroutine dtha_stack::get_stack_list at /usr/dtha/bin/../lib/dtha_stack.pm line 244.
Compilation failed in require at /usr/dtha/bin/../lib/Dtha.pm line 80.
BEGIN failed--compilation aborted at /usr/dtha/bin/../lib/Dtha.pm line 80.
Compilation failed in require at /usr/dtha/bin/dtha_stack_info line 68.
BEGIN failed--compilation aborted at /usr/dtha/bin/dtha_stack_info line 68.

So, I simplified the code. Using the code below, it does not error on this function anymore. (fails on the next function defined the same way) Not sure the best method for modification…

sub get_stack_list { my $self = shift; my $group = shift || '.*'; # group = PROD | TEST # read stacks.xml and build $DESCRIPTIONS hash parse_stacks(); my @stacks; foreach my $i (sort (keys %DESCRIPTIONS)) { push @stacks, $i if ( $DESCRIPTIONS{$i}{group} eq $gro +up ); push @stacks, $i if ( $group eq ".*" ); } return @stacks; } # endsub get_stack_list

Replies are listed 'Best First'.
Re: function prototyping & perl 5.8.20
by Corion (Patriarch) on Jul 30, 2018 at 18:07 UTC

    Can you reduce your problem to a complete module that is reduced to a short self-contained example that reproduces the problem?

    Note that it is really weird to declare your subroutines with a prototype indicating no parameters and then to call the subroutines with actual parameters.

    If you are really, really intent on moving to the new (but still experimental) function parameters as in your second example, you will have to modify all your source code to the second style. With Filter::signatures, you can then use the new style in almost all versions of Perl. You have to tell Perl that you want to use experimental features:

    use feature 'signatures; sub example( $foo, $bar='baz' ) { ... }

    But personally, I would recommend against making such a sweeping change right during the move between Perl versions.

    Your simplified third style is what I would expect you to start out with, but as your code is in the first style, changing to the third style is inconvenient at this time too.

    For me, your first example compiles without problems, so can you show us a stand-alone version that fails perl -wc so we can reproduce your situation?

Re: function prototyping & perl 5.8.20
by Laurent_R (Canon) on Jul 30, 2018 at 19:29 UTC
    I think that you should probably just change:
    sub get_stack_list() { # ...
    to:
    sub get_stack_list { # ...
    i.e. remove the pair of parentheses after the subroutine name. This change should work on both your Perl versions.
Re: function prototyping & perl 5.8.20
by dave_the_m (Monsignor) on Jul 31, 2018 at 06:39 UTC
    The code that you've shown is legal in both versions of perl. Either something just above the sub declaration is tripping up perl, or maybe there are invisible chars at the end of the 'sub' line (such as \r) which one version of perl is more fussy about. It may be that your 'simplifying' edit just happens to remove the \r's (or whatever).

    That particular error message means that following the empty prototype '()' and after skipping any whitespace, perl didn't see a character that it expected, such as '{'.

    Dave.

Re: function prototyping & perl 5.8.20
by topherv (Initiate) on Aug 01, 2018 at 11:28 UTC
    Hi monks, I figured I’d share my learnings. When I rolled up to perl 5.8.20, a few of my modules gave errors. The errors pointed at the function declaration lines. I changed:
    Sub function() {
    To:
    Sub function() {
    After making these changes, there was one more fix:
    foreach my $key qw( id group title rank )
    To:
    foreach my $key (qw( id group title rank ))
    I saw many other places where my functions were defined with the ‘{‘ on the next line. But, things were running. I wondered if I removed the “use strict”, if the function errors would go away. So, I undid the function changes. The code still worked!

    This means the functions weren’t my problem at all, just the foreach line. But the compiler could not point to that line until I corrected all the functions. So, having the ‘{‘ on the same line as the sub is good coding practice, but not required for perl 5.8.20

    Thanks for you help!

      $ perl5.12.5 -we'for my $k qw(a b) {$_=$k}' $ perl5.14.0 -we'for my $k qw(a b) {$_=$k}' Use of qw(...) as parentheses is deprecated at -e line 1. $ perl5.16.3 -we'for my $k qw(a b) {$_=$k}' Use of qw(...) as parentheses is deprecated at -e line 1. $ $ perl5.18.0 -we'for my $k qw(a b) {$_=$k}' syntax error at -e line 1, near "$k qw(a b)" Execution of -e aborted due to compilation errors.

      If you upgrade, you might as well read the release notes. Oké, if you take big steps, there are a lot of changes to read, but all of this is documented.

      See the 5.14.0 delta entry:

      And the 5.18.0 delta entry:

      Which makes me think you made a move from perl-5.10.1 to perl-5.18.0 or newer. As you state 5.8.20 (which never existed), I assume you mean 5.28.0.


      Enjoy, Have FUN! H.Merijn
      Note that there's no such perl version as 5.8.20. perhaps you mean 5.20.0???

      Dave.

Re: function prototyping & perl 5.8.20
by topherv (Initiate) on Aug 03, 2018 at 10:48 UTC
    Yes, I had stated the wrong perl versions... My older versions are v5.8.8, and v5.10.1 AIX 7.2 brought in v5.20.1 (that no longer ran the code)

    Thanks again for all your help.