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

I'm trying to track down the problems in a script I wrote. I get severl errors in the log file that I'm having a hard time figuring out. I have a library file that I think I may have a few problems with they way I do things in it as well. I'll list the library file first. Any help on this will have a reward of a big smile from yours truely.
## Global Links package common::links; use strict; #use CGI::Carp qw(fatalsToBrowser); #warn "this is a complaint"; #die "But this is serious"; use vars qw ($timeclock_link $searchform_link); $timeclock_link = "timeclock.cgi"; $searchform_link = "search_form.cgi"; ## Global Authentication Variables package common::auth; use vars qw($user $admin); $user = $ENV{"REMOTE_USER"}; $admin = "admin"; # Set to the Administrators username ########################################## ## Authentication Error ########################################## sub print_error{ print <<HTML; <HTML> <HEAD> <TITLE>Error</TITLE> </HEAD> <BODY> <CENTER><B><FONT size=3><P> Authentication Failed. Please Restart your + Browser.</FONT></B></CENTER><HR> </P> </BODY></HTML> HTML } # End of print_results subroutine ########################################## ## Create a connection to the database. ## ########################################## package common::sql; use vars qw($sth $dbh); sub Create_DB_Connection{ use DBI; use DBD::Pg; my ($DSN, $db_user, $pw); $DSN = "DBI:Pg:dbname=user"; $db_user = "user"; $pw = "resu"; #$dbh = DBI->connect($DSN,$db_user,$pw, { RaiseError => 1 }) $dbh = DBI->connect($DSN,$db_user,$pw, { PrintError => 1 }) || die "Cannot connect: $DBI::errstr\n" unless $dbh; return; } # End of Create_DB_Connection subroutine. ########################################## ########################################## ## Executes the SQL command and then ## ## returns to the calling area of the ## ## program. ## ########################################## sub Do_SQL{ eval{ $sth = $dbh->prepare($main::SQL); }; # End of eval # Check for errors. if($@){ $dbh->disconnect; print "Content-type: text/html\n\n"; print "An ERROR occurred! $@\n<P>"; exit; } else { $sth->execute; } # End of if..else return ($sth); } # End of Do_SQL subroutine ################################################################# #################################### ### Filter - Gets rid of ### ### characters that screw up the ### ### program. ### #################################### sub filter{ $_[0]=~s/\'/\\\'/g; return $_[0]; } # End of filter subroutine ################################################################# 1; # Required or won't work!
Here is the main script(relevant parts).
#!/usr/bin/perl -w use CGI qw/:standard/; require "common.sub"; use strict; #use CGI::Carp qw(fatalsToBrowser); #warn "this is a complaint"; #die "But this is serious"; my $username = "$common::auth::user"; my ($time, $date); + # Declare current_time_da +te() args #my ($in_time, $print_date, $hidden_oid, @out_oid); + # Declare check_for_in() args print header; if ($username eq ""){ &common::auth::print_error; }elsif($username eq "$common::auth::admin"){ &common::sql::Create_DB_Connection; admin_get_users_in(); current_time_date(); print_admin_data(); }else{ &common::sql::Create_DB_Connection; current_time_date(); check_for_in ($username); } $common::sql::dbh->disconnect; ####################### GET TIME AND DATE FOR IN FORM sub current_time_date { my ($min, $hour, $day, $month, $year, $calc_year, $calc_month); ($date, $time) = @_; ($min, $hour, $day, $month, $year) = (localtime)[1,2,3,4,5]; #($calc_year, $calc_month); $calc_year = $year+1900; $calc_month = $month+1; $date = "$calc_year-$calc_month-$day"; $time = sprintf("%d:%02d", $hour,$min); } ####################### END GET TIME AND DATE FOR IN FORM ################ BEGIN GET USERS CLOCKED IN SUBROUTINE - ADMIN sub admin_get_users_in { $main::SQL="SELECT oid,username,start_stamp FROM timeclock WHERE tot +al_hours = NULL AND total_minutes = NULL AND end_stamp = NULL ORDER B +Y username"; common::sql::Do_SQL(); } ################ END GET USERS CLOCKED IN SUBROUTINE ################ CHECK IF CLOCKED IN SUBROUTINE - NORMAL sub check_for_in ($) { my ($username) = @_; my (@clocked_in, @date_array01, $in_time_sec, @in_time_array, $pri +nt_date, $in_time, $hidden_oid); # $main::SQL="SELECT oid,* FROM timeclock WHERE end_stamp = NULL AN +D total_hours = NULL AND total_minutes = NULL AND username = #'$usern +ame'"; $main::SQL="SELECT oid,* FROM timeclock WHERE end_stamp = NULL AND use +rname = '$username'"; common::sql::Do_SQL(); @clocked_in = $common::sql::sth->fetchrow(); unless ($clocked_in[1] eq "$username"){ clock_in_form($username, $date, $time); }else{ $main::SQL="SELECT oid,* FROM timeclock WHERE username = + '$username' AND oid = $clocked_in[0]"; common::sql::Do_SQL(); while(my @out_oid = $common::sql::sth->fetchrow()){ @date_array01 = split(/ /,$out_oid[2]); $print_date = $date_array01[0]; $in_time_sec = $date_array01[1]; @in_time_array = split(/:/,$in_time_sec); $in_time = join(":",$in_time_array[0],$in_time_array[1]); $hidden_oid = $out_oid[0]; clock_out_form($hidden_oid, $username, $time, $print_date +, $in_time, @out_oid); } } } ################ END CHECK FOR IN SUBROUTINE
And finally the error log.
main::check_for_in() called too early to check prototype at /home/http +d/cgi-bin/timeclock-1.0.1/timeclock.cgi line 28. Name "common::sql::dbh" used only once: possible typo at /home/httpd/c +gi-bin/timeclock-1.0.1/timeclock.cgi line 30. Name "common::auth::admin" used only once: possible typo at /home/http +d/cgi-bin/timeclock-1.0.1/timeclock.cgi line 20. Name "common::auth::user" used only once: possible typo at /home/httpd +/cgi-bin/timeclock-1.0.1/timeclock.cgi line 11. Use of uninitialized value in string eq at /home/httpd/cgi-bin/timeclo +ck-1.0.1/timeclock.cgi line 68.

Edit by tye to add <readmore>

Replies are listed 'Best First'.
Re: too early to check prototype
by derby (Abbot) on Apr 29, 2002 at 18:04 UTC
    For the "too early to prototype" message, you need to have the function definition (or at least declaration) before the call. Compare:

    #!/usr/bin/perl -w use strict; check_for_in( "derby" ); sub check_for_in( $ ) { my( $arg ) = shift; print $arg, "\n"; }

    to

    #!/usr/bin/perl -w use strict; sub check_for_in( $ ) { my( $arg ) = shift; print $arg, "\n"; } check_for_in( "derby" );

    -derby

Re: too early to check prototype
by Juerd (Abbot) on Apr 29, 2002 at 18:06 UTC
    Read the perldiag page, and find out for yourself. Here are the answers to your problems:

    called too early to check prototype

    (W prototype) You've called a function that has a prototype before the parser saw a definition or declaration for it, and Perl could not check that the call conforms to the prototype. You need to either add an early prototype declaration for the subroutine in question, or move the subroutine definition ahead of the call to get proper prototype checking. Alternatively, if you are certain that you're calling the function correctly, you may put an ampersand before the name to avoid the warning. See perlsub.

    used only once: possible typo

    (W once) Typographical errors often show up as unique variable names. If you had a good reason for having a unique name, then just mention it again somehow to suppress the message. The "our" declaration is provided for this purpose.

    Use of uninitialized value

    (W uninitialized) An undefined value was used as if it were already defined. It was interpreted as a "" or a 0, but maybe it was a mistake. To suppress this warning assign a defined value to your variables. To help you figure out what was undefined, perl tells you what operation you used the undefined value in. Note, however, that perl optimizes your program and the operation displayed in the warning may not necessarily appear literally in your program. For example, "that $foo" is usually optimized into "that " . $foo, and the warning will refer to the "concatenation (.)" operator, even though there is no . in your program.

    Note: these descriptions are taken from the perldiag page.

    - Yes, I reinvent wheels.
    - Spam: Visit eurotraQ.
    

Re: too early to check prototype
by boo_radley (Parson) on Apr 29, 2002 at 18:10 UTC
    declare the prototype before the sub is invoked. perl needs to understand the prototype before you call the sub, otherwise, when it gets to the subroutine declaration it says "I've already been asked to call this sub, but I see it has a prototype... I don't remember if the invocation matched this prototype. I should throw a fatal warning and let the user deal with it".
    You can rememdy this by putting your sub declaration before the main body of your program (known as forward declaration), or by using a prototype before the main body, which just looks like :
     sub foo ($$); for more details, see perlsub and perldiag.
Re: too early to check prototype
by jsprat (Curate) on Apr 29, 2002 at 21:23 UTC
    If you would like perl to give you more informative error messages (such as the ones mentioned above, from perldiag) just add:

    use diagnostics;

    along with your warnings pragma. Perl will hunt down and print those verbose error messages for you.
      Thank you for this tip. Very helpful!
Re: too early to check prototype
by vek (Prior) on Apr 29, 2002 at 18:09 UTC
    You're using a function prototype in your check_for_in subroutine:
    sub check_for_in ($) {
    If you really meant to do that then you need to make sure the function is not called before declaration. That is, move that 'chunk' of code somewhere in your source prior to calling check_for_in. The compiler needs to see the declaration first.

    -- vek --