perlparameterssubroutine-prototypes

Passing parameters to a subroutine in Perl


I am attempting to create a subroutine that will open and edit a file in place.

I've been able to get the subroutine to run on it's own as a single Perl script, but when it's in the form of a subroutine I can't pass the parameters properly.

I come from a background of VB.Net and Objective-C where subroutines/functions are prototyped.

$FileName is assigned $ARGV[0] upon executing the script.

Here's my function call:

addComment("v-66721", "Open", "!!!FINDING!!! deployment.config does not exist.", $FileName);

Here is my declaration:

sub addComment($$$$);

And here's the subroutine:

sub addComment {
    my $VULN     = $_[0];
    my $Result   = $_[1];
    my $Comment  = $_[2];
    my $FileName = $_[3];

    # Copy the checklist to a new file name.
    my $outputFile = $FileName;
    $outputFile =~ s/\.ckl/_commented\.ckl/;
    copy( $FileName, $outputFile );

    # Create a temporary file to edit.
    my $tempFile = $FileName;
    $tempFile =~ s/\.ckl/\.ckl_temp/;

    open( OLD, "<$outputFile" ) or die "Can't open $outputFile: $!";
    open( NEW, ">$tempFile" )   or die "Can't open $tempFile: $!";

    my $foundVULN = 0;

    while ( <OLD> ) {

        if ( $foundVULN == 0 && $_ =~ /$VULN/ ) {
            $foundVULN = 1;
        }

        if ( $foundVULN == 1 && $_ =~ /Not_Reviewed/ ) {
            s/Not_Reviewed/$Result/;
        }

        if ( $foundVULN == 1 && $_ =~ /COMMENTS/ ) {
            s/<COMMENTS>/<COMMENTS>$Comment/;
            $foundVULN = 0;
        }

        print NEW $_;
    }

    close(OLD);
    close(NEW);

    # Replace the output file contents with what we did in our temp file.
    rename( $tempFile, $outputFile ) or die "Can't rename $tempFile to $outputFile: $!";

    return;
}

I've tried using

my $VULN = shift
my $Result = shift
my $Comment = shift
my $FileName = shift

But that doesn't seem to work.

I've read that I should not use prototyping but it doesn't seem to work whether I do or not.

The error message I'm getting is:

Prototype mismatch: sub main::addComment ($$$$) vs none at ./Jre8_manual.pl line 614.

Solution

  • Avoid prototypes. Prototypes in Perl don't work the way they do in other languages and the way that new programmers expect.

    Prototype mismatch ... means you have defined (or redefined) a method with a different prototype than the original declaration/definition. In this case.

    sub addComment ($$$$);
    sub addComment { ... }
    

    have two different prototypes (that is, the second declaration has no prototype). To fix, you could make the sub definition use the same prototype

    sub addComment ($$$$);
    sub addComment ($$$$) { ... }
    

    but in most cases you are better off without the prototype (and then you don't need the predeclaration, either)

    # sub addComment ($$$$);  # don't need this
    sub addComment { ... }