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

I made some code, that is causing these errors:
Use of uninitialized value in eval "string" at /path_to/req/readin_pag +evars.cgi line 10, <STDIN> line 47. Use of uninitialized value in eval "string" at /path_to/req/readin_pag +evars.cgi line 10, <STDIN> line 47. Use of uninitialized value in eval "string" at /path_to/req/readin_pag +evars.cgi line 10, <STDIN> line 47. Use of uninitialized value in substitution iterator at /path_to/req/re +adin_pagevars.cgi line 10, <STDIN> line 47. Use of uninitialized value in eval "string" at /path_to/req/readin_pag +evars.cgi line 10, <STDIN> line 47. Use of uninitialized value in eval "string" at /path_to/req/readin_pag +evars.cgi line 10, <STDIN> line 47.


I wanted to use variables in database 'text'(content for a website). However, since perl won't use the variables in a database, it would just show the variable (ie: $_co_name for Company Name) in the text.

So I had to make a way to replace those variables while it is reading them from the database into the hash that calls them.

Can you please critique my code and tell me what could be causing those errors?

Here is my code:
sub Get_Page_Vars { my ($temp_vars,$type) = @_; my ($code1, $code2, $_do_code, $syscode1, $syscode2); $sth = $dbh->prepare (qq{ SELECT `name`,`value`,`add_name` FROM `p +age_vars` WHERE `type` = ? OR `type2` = ? ORDER BY add_name,id,d}); $sth->execute($type,$type); while(my ($db_name,$content,$_add_name) = $sth->fetchrow_array()) +{ $content =~ s/(\$[a-zA-Z0-9\{\'\}_]+)/ eval($temp_vars{$1}) /g +e; $content =~ s/(\$[a-zA-Z0-9\{\'\}_]+)/ $temp_vars{eval($1)} /g +e; $content =~ s/\<templ_var ([a-zA-Z0-9\{\'\}_]+)\>/ eval ($vars +{$1}) /ge; $content =~ s/\<templ_var ([a-zA-Z0-9\{\'\}_]+)\>/ $vars{eval( +$1)} /ge; $content =~ s/\<templ_var ([a-zA-Z0-9\{\'\}_]+)\>/ eval ($temp +_vars{$1}) /ge; $content =~ s/\<templ_var ([a-zA-Z0-9\{\'\}_]+)\>/ $temp_vars{ +eval($1)} /ge; $content =~ s/\<templ_var ([a-zA-Z0-9\{\'\}_]+)\>/ eval ($1) / +ge; $content =~ s/{{([a-zA-Z0-9\{\'\}_]+)}}/ eval($vars{$1}) /ge; $content =~ s/{{([a-zA-Z0-9\{\'\}_]+)}}/ $vars{eval($1)} /ge; $content =~ s/(\$[a-zA-Z0-9\{\'\}_]+)/ eval($vars{$1}) /ge; $content =~ s/(\$[a-zA-Z0-9\{\'\}_]+)/ $vars{eval($1)} /ge; $content =~ s/(\$[a-zA-Z0-9\{\'\}_]+)/ eval($1) /ge; if ($content && ($content =~ /<code>/i && $content =~ /<\/code +>/i)) { while($content =~ /<code>/i && $content =~ /<\/code>/i) { my ($code1,$code2,$_do_code); ($content,$code1) = split /<code>/, $content, 2; ($code2,$ocontent) = split /<\/code>/, $code1, 2; $_do_code = eval($code2) if $_do_code && $_do_code ne +""; $content = $content . $_do_code . $ocontent; } } if ($content && ($content =~ /<syscode>/i && $content =~ /<\/s +yscode>/i)) { while($content =~ /<syscode>/i && $content =~ /<\/syscode> +/i) { my ($syscode1,$syscode2); ($content,$syscode1) = split /<syscode>/i, $content, 2 +; ($syscode2,$ocontent) = split /<\/syscode>/i, $syscode +1, 2; eval($syscode2) if $syscode2 && $syscode2 ne ""; $content = $content . $ocontent; } } if ($_add_name) { $content = qq~<!--Start $db_name-->$content<!--End $db_nam +e-->~; } $temp_vars{$db_name} = $content; } $sth->finish(); return(%temp_vars); }

I would appreciate any and all positive criticism.

Thank you very much.
thx,
Richard

Retitled by g0n from 'Positive Criticism Requested, please.'.

Replies are listed 'Best First'.
Re: Help with 'Use of uninitialized value...' error in DB code
by Zaxo (Archbishop) on Sep 03, 2005 at 05:01 UTC

    You should indicate which line is #47 in your program. There are a number of eval expressions on different lines. Can you redesign to do what you want without eval? It is a tricky function which is often a source of errors and security breaches.

    There is one point where errors look likely. On line 8 we see a hash value eval'ed which has the same name as a scalar argument of the sub. If $temp_vars is a hashref, you should get a value from it with $temp_vars->{$1}. If you don't have a global %temp_vars (which from the name seems likely), then $temp_vars{$1} will generate an empty one for you, and feed undef to eval, producing the error you see.

    This code appears to parse some sort of tagged text. Is it XML fragments? One of the XML parsers may be more suitable than these regex substitutions.

    After Compline,
    Zaxo

Re: Help with 'Use of uninitialized value...' error in DB code
by davidrw (Prior) on Sep 03, 2005 at 13:54 UTC
    I wanted to use variables in database 'text'(content for a website). However, since perl won't use the variables in a database, it would just show the variable (ie: $_co_name for Company Name) in the text.

    So I had to make a way to replace those variables while it is reading them from the database into the hash that calls them.
    Ok, so it seems like what you're really after here is a home grown template system, right? Is it possible to use an existing robust one like Template Toolkit or HTML::Template? Using TT as an example, you would have the string I work for [% co_name %], the best company there is! stored in the db. Then perl code would look like:
    my $template = Template->new(); my $vars = {co_name=>"Foo-Co"}; my $my_template_string = 'I work for [% co_name %], the best company t +here is!'; my $string; $template->process(\$my_template_string, $vars, \$string); # stores o +utput in $string print $string; $template->process(\$my_template_string, $vars ); # dumps output to S +TDOUT

    As for your code, a couple major things jump out at me.. the first is eval ($vars{$1}) vs $vars{eval($1)} .. why are both necessary? can you provide template examples for each of the substitutions? is the intent to do something like this?
    $content =~ s/(\$[a-zA-Z0-9\{\'\}_]+)/ eval($vars{$1}) || $var +s{eval($1)} || eval($1) /ge;

    The other (related) item is looking at these two lines:
    $content =~ s/(\$[a-zA-Z0-9\{\'\}_]+)/ eval($temp_vars{$1}) /g +e; $content =~ s/(\$[a-zA-Z0-9\{\'\}_]+)/ $temp_vars{eval($1)} /g +e;
    They have the exact same pattern, and the first is a global replacement, which means that the second can never match (unless the first replacement value included a template string itself)... this goes for pretty much all of the replacement sets...
Re: Help with 'Use of uninitialized value...' error in DB code
by CountZero (Bishop) on Sep 03, 2005 at 08:15 UTC
    That's a bunch of code to look at. Can you just post some minimal code which exhibits the "Use of uninitialized value" behaviour? That would make it easier to spot the error.

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

      That is the problem, I don't know what is doing it. That subroutine is what does it, I don't know which line.


      thx,
      Richard
        if the line number from the error message doesn't help, then just put a bunch of warn 'foo'; lines inbetween all those eval statements .. then in the output/log you can see which warn's the "uninitialized value" appears between and work from there.
Re: Help with 'Use of uninitialized value...' error in DB code
by Errto (Vicar) on Sep 03, 2005 at 21:50 UTC
    One other note: you refer frequently in your code to two hashes %vars and %temp_vars. Where do these get populated? What do they contain? You do take a parameter called $temp_vars, a scalar, but then you don't use it at all. And where is line 10 of your code?