Poldi: Was bedeutet diese Fehlermeldung ?

Im NMS formmail von sourceforge.net wollte ich einen Text variabel gestalten und habe daher in dem folgenden Codeteil die Zeile (#....) durch die darauf folgende ersetzt.
Ich erhalte dann die Fehlermeldung:

Global symbol "$tDanke" requires explicit package name at (eval 8) line
 1342

Als Perl-Anfänger sagt mir die Meldung nichts. Könnt Ihr mir - ohne das gesamte Listing zu kennen, sagen, woran es liegen könnte ?

Hier der Code-Teil:

use vars qw(... $tDanke ....);
...
$tDanke = ".....";

sub success_page_html_preamble {
  my ($self, $date) = @_;

#  my $title = $self->escape_html( $self->{FormConfig}{'title'} || "Danke für die Nachricht");
  my $title = $self->escape_html( $self->{FormConfig}{'title'} || "$tDanke");

my $torecipient = 'to ' . $self->escape_html($self->{FormConfig}{'recipient'});
  $torecipient = '' if $self->{Hide_Recipient};
  my $attr = $self->body_attributes;
.........

  1. Hallo ,

    Global symbol "$tDanke" requires explicit package name at
    (eval 8) line  1342

    Das strict Modul beschwert sich da drueber, dass die Variable
    $tDanke nicht explizit deklariert wurde.

      
    
    > use vars qw(... $tDanke ....);  
    > ...  
    > my $tDanke = ".....";  
    
    

    Such mal ein wenig in deiner Perl-Dokumentation nach der Seite
    perldiag.html. Das ist eine Diagnose Datei, die dokumentiert was
    und wo drueber sich der Perl-Parser beschwert.

    gruesse aus'm ruhrpott
      jens mueller

    --
    As long as a single mind remembers, as long as a single heart
    beats with passion, how can a dream die?
    \//_ Live long and prosper
    sh:( fo:) ch:| rl:° br:^ n4:| ie:% mo:| va:} de:> zu:) fl:( ss:) ls:> js:|
    1. Hallo ,

      Such mal ein wenig in deiner Perl-Dokumentation nach der Seite
      perldiag.html.

      Danke für den Hinweis

      Das strict Modul beschwert sich da drueber, dass die Variable
      $tDanke nicht explizit deklariert wurde.

      Mit der Angabe my $tDanke .... kommt die gleiche Meldung.

      Gruß
      Poldi

      1. Das strict Modul beschwert sich da drueber, dass die Variable
        $tDanke nicht explizit deklariert wurde.

        Mit der Angabe my $tDanke .... kommt die gleiche Meldung.

        Die Datei wo du das hingeschrieben hast, ist die Gleiche in der der Fehler auftritt?

        Struppi.

        --
        Javascript ist toll (Perl auch!)
        1. Die Datei wo du das hingeschrieben hast, ist die Gleiche in der der Fehler auftritt?

          Ja,
          aber ich habe folgenden Kommentar im Script gefunden.

          The code below consists of module source inlined into this

          script to make it a standalone CGI.

          Heißt das vielleicht, das das Script wie mehrere Dateien zu betrachten ist ?
          Es hat mehrere BEGIN-Blöcke !

          1. Ja,
            aber ich habe folgenden Kommentar im Script gefunden.

            The code below consists of module source inlined into this

            script to make it a standalone CGI.

            Was immer das bedeuten mag, ich versteh es nicht.

            Heißt das vielleicht, das das Script wie mehrere Dateien zu betrachten ist ?
            Es hat mehrere BEGIN-Blöcke !

            Ein BEGIN Block wird vor dem Start des Skriptes ausgeführt (während der Übersetzung), es sollte schon klar sein, warum man das tut.

            Struppi.

            --
            Javascript ist toll (Perl auch!)
            1. Ein BEGIN Block wird vor dem Start des Skriptes ausgeführt (während der Übersetzung), es sollte schon klar sein, warum man das tut.

              Ich tue es ja nicht,
              ich möchte es ja nur verstehen!

              1. Ein BEGIN Block wird vor dem Start des Skriptes ausgeführt (während der Übersetzung), es sollte schon klar sein, warum man das tut.

                Ich tue es ja nicht,
                ich möchte es ja nur verstehen!

                http://perldoc.perl.org/perlmod.html#BEGIN%2C-CHECK%2C-INIT-and-END-BEGIN-CHECK-INIT-END

                Es sollte aber nichts mit deiner Fehlermeldung zu tun haben.

                Struppi.

                --
                Javascript ist toll (Perl auch!)
                1. Hallo ,

                  Ein BEGIN Block wird vor dem Start des Skriptes ausgeführt

                  (während der Übersetzung), es sollte schon klar sein, warum
                  man das tut.

                  Ich tue es ja nicht,
                  ich möchte es ja nur verstehen!

                  Es ist a nicht Poldis Script, er moechte es ja nur bei sich einsetzen.

                  Begin

                  Es sollte aber nichts mit deiner Fehlermeldung zu tun haben.

                  Doch es sollte:

                  »A BEGIN code block is executed as soon as possible, that is, the
                    moment it is completely defined, even before the rest of the
                    containing file (or string) is parsed.«

                  Original Code:~~~perl

                  sub success_page_html_preamble {
                    my ($self, $date) = @_;

                  my $title = $self->escape_html( $self->{FormConfig}{'title'} || 'Thank You' );
                    my $torecipient = 'to ' . $self->escape_html($self->{FormConfig}{'recipient'});
                    $torecipient = '' if $self->{Hide_Recipient};
                    my $attr = $self->body_attributes;

                    
                  Der Fehler des Scripts liegt da dran, das der Begin Block als eigene  
                  Script Datei augefuehrt wird. [In dieser Existiert die Variable `$tDanke`{:.language-perl}  
                  gar nicht.  
                    Die Variable `$tDanke`{:.language-perl} muss noch einmal explizit mit `my`{:.language-perl} aufgerufen  
                  werden  
                    
                  ~~~perl
                    
                  sub success_page_html_preamble {  
                    my ($self, $date) = @_;  
                    
                    # Kleine Modifizierung: Wenn du noch andere Variablen in $tDanke  
                    # aufrufst, dann  muessn diese auch mit *my* gekenzeichnet werden  
                    my $tDanke = ".....";  
                    my $title = $self->escape_html( $self->{FormConfig}{'title'} || "$tDanke");  
                    ...  
                  
                  

                  Die vorherige deklarierung, kann geloescht werden

                    
                  use vars qw(... $tDanke ....);  
                  ...  
                  # ... und wech damit: $tDanke = ".....";  
                  
                  

                  gruesse aus'm ruhrpott
                    jens mueller

                  --
                  As long as a single mind remembers, as long as a single heart
                  beats with passion, how can a dream die?
                  \//_ Live long and prosper
                  sh:( fo:) ch:| rl:° br:^ n4:| ie:% mo:| va:} de:> zu:) fl:( ss:) ls:> js:|
                  1. Begin

                    Es sollte aber nichts mit deiner Fehlermeldung zu tun haben.

                    Doch es sollte:

                    »A BEGIN code block is executed as soon as possible, that is, the
                      moment it is completely defined, even before the rest of the
                      containing file (or string) is parsed.«

                    Bis jetzt war noch nicht davon die Rede, dass der code im BEGIN Block steht und selbst wenn, dann definiert man die betreffende Variabel in diesem Block.

                    Original Code:~~~perl

                    Na, du weißt mehr als ich. Wobei aus dem Beispiel auch der Fehler nicht klar wird, weil hier nirgends ein BEGIN Block ist. Und wenn, wozu ist der gut?

                    Der Fehler des Scripts liegt da dran, das der Begin Block als eigene
                    Script Datei augefuehrt wird. [In dieser Existiert die Variable [code lang=perl]$tDanke

                    
                    > gar nicht.  
                      
                    Ich kenn den Code ja nicht, aber der Fehler ist vermutlich eher die Existenz des BEGIN Blocks.  
                      
                    
                    >   Die Variable `$tDanke`{:.language-perl} muss noch einmal explizit mit `my`{:.language-perl} aufgerufen  
                    > werden  
                      
                    Oder einfach den BEGIN block rausschmeissen.  
                      
                    Struppi.
                    
                    -- 
                    [Javascript ist toll](http://javascript.jstruebig.de/) (Perl auch!)
                    
                    1. Ist mein Beitrag untergegangen ?

                      Zu Jens:

                      # Kleine Modifizierung: Wenn du noch andere Variablen in $tDanke
                        # aufrufst, dann  muessn diese auch mit *my* gekenzeichnet werden
                        my $tDanke = ".....";
                        my $title = $self->escape_html( $self->{FormConfig}{'title'} || "$tDanke");

                      Auf diese Art erhalte ich jetzt zwar keine Fehlermeldung mehr, aber ich weiß nicht, wie ich $tDanke einen dynamischen Wert zuweisen soll.
                      Ich erhalte vom rufenden Skript die Sprache (spr) übergeben.
                      Ich habe also in der Subroutine folgende Befehle eingefügt.
                        my $tsprache    = param('spr');
                        my $tDanke;
                        if ($tsprache == "d")
                           {$tDanke = "Danke für die Nachricht"}
                        else
                           {$tDanke = "Merci pour votre message"};

                      Da bringt mir das System aber nur noch die nichtssagende Meldung

                      Application Error
                      An error has occurred in the program
                      See the web server's error log for details

                      Das Dumme ist nur, ich kann den Log (bei Netbeat) nicht anschauen.

                      Zu Jens und Struppi:

                      Ich sehe vollkommen ein, dass eine realistische Einschätzung der Fehlersituation ohne Vorlage des Script eigentlich nicht möglich ist.
                      Ich wollte allerdings der SELFHTML-Gemeinde nicht ein so langes Script zumuten (über 3500 Zeilen).

                      Falls sich doch jemand die Mühe machen wollte (mein Dank wird ihr/ihm gewiss sein), ich habe das Skript unter
                      beinahe<Minuszeichen>gratis<Punkt>de<Schrägstrich>feedback-test.txt
                      abgestellt (fragliche Stelle ab Zeile 3236).

                      1. Ist mein Beitrag untergegangen ?

                        nein, aber angesichts des Umfanges (des in meinem augen nicht schönen Skript) und meiner eingeschränkten Zeit, ist da keine Chance, dass ich mir das antue.

                        Meiner Meinung nach beruht dein Problem darin, dass dieses Skript überall diese BEGIN Blöcke verwendet, allerdings fehlt mir wie gesagt die Zeit das nachzuprüfen.

                        Auf diese Art erhalte ich jetzt zwar keine Fehlermeldung mehr, aber ich weiß nicht, wie ich $tDanke einen dynamischen Wert zuweisen soll.
                        Ich erhalte vom rufenden Skript die Sprache (spr) übergeben.
                        Ich habe also in der Subroutine folgende Befehle eingefügt.
                          my $tsprache    = param('spr');
                          my $tDanke;
                          if ($tsprache == "d")
                             {$tDanke = "Danke für die Nachricht"}
                          else
                             {$tDanke = "Merci pour votre message"};

                        Hier fehlen die abschliessenden Semikolons (arghh, die heissen bestimmt anders, ich Legasteniker)

                        Falls sich doch jemand die Mühe machen wollte (mein Dank wird ihr/ihm gewiss sein), ich habe das Skript unter
                        beinahe<Minuszeichen>gratis<Punkt>de<Schrägstrich>feedback-test.txt
                        abgestellt (fragliche Stelle ab Zeile 3236).

                        ich hab's runtergeladen und angeschaut. Aber wie gesagt, es ist nicht mein Stil und daher hab ich auch wenig Lust gehabt das auszuprobieren.

                        Struppi.

                        --
                        Javascript ist toll (Perl auch!)
                        1. Hallo Struppi,

                          ich hab's runtergeladen und angeschaut. Aber wie gesagt, es ist nicht mein Stil und daher hab ich auch wenig Lust gehabt das auszuprobieren.

                          Habe vollstes Verständnis bei der Länge des Skripts.
                          Danke Dir trotzdem, Du warst ja bisher sehr engagiert, und wie ich sehe auch in vielen anderen Beiträgen.

                          Ich hoffe ja immer noch, dass sich jemand meldet, der das Skript selbst verwendet und viel darin geändert hat (vielleicht sogar mehrsprachig erweitert hat) - und die Hoffnung stirbt zuletzt.
                          Ansonsten werde ich halt weiter herumstochern.
                          Gruß Poldi

                        2. Moin,

                          Hier fehlen die abschliessenden Semikolons (arghh, die heissen
                          bestimmt anders, ich Legasteniker)

                          Dem kann nachgeholfen werden:

                          »Semiko̱lon, das; -s, -s / Semikola lat. + griech. /Satzzeichen, das
                            keinen starken Einschnitt zwischen zwei selbständigen Sätzen
                            kennzeichnet: ;/ das S. trennt schärfer als das Komma, aber
                            weniger scharf als der Punkt«

                          gruesse aus'm ruhrpott
                            jens mueller

                          --
                          As long as a single mind remembers, as long as a single heart
                          beats with passion, how can a dream die?
                          \//_ Live long and prosper
                          sh:( fo:) ch:| rl:° br:^ n4:| ie:% mo:| va:} de:> zu:) fl:( ss:) ls:> js:|
                      2. Hell-O!

                        my $tDanke = ".....";
                          my $title = $self->escape_html( $self->{FormConfig}{'title'} || "$tDanke");
                        Auf diese Art erhalte ich jetzt zwar keine Fehlermeldung mehr, aber ich weiß nicht, wie ich $tDanke einen dynamischen Wert zuweisen soll.

                        Innerhalb der entsprechenden Routine.

                        Ich erhalte vom rufenden Skript die Sprache (spr) übergeben.
                        Ich habe also in der Subroutine folgende Befehle eingefügt [...]

                        Und diese Subroutine steht vermutlich innerhalb des BEGIN-Blocks, weshalb die Variable nicht deklariert wurde und der entsprechende Fehler geworfen wird.

                        Falls sich doch jemand die Mühe machen wollte (mein Dank wird ihr/ihm gewiss sein), ich habe das Skript unter beinahe<Minuszeichen>gratis<Punkt>de<Schrägstrich>feedback-test.txt abgestellt (fragliche Stelle ab Zeile 3236).

                        Warum kein Link? Was helfen dürfte, ist ein no strict "vars" am Anfang des Scripts, was aber nicht Sinn und Zweck der Sache sein kann. Leider fällt die Dokumentation auf der Projektseite ziemlich dürftig aus und die Herren Experten scheinen keinen gesteigerten Wert darauf zu legen, dass jemand anderes ihr Script versteht.

                        Siechfred

                        --
                        Hier könnte Ihre Werbung stehen.
                        Dark Millennium || Die neue 1%-Regelung
                        1. Hallo Siechfred !

                          Und diese Subroutine steht vermutlich innerhalb des BEGIN-Blocks, weshalb die Variable nicht deklariert wurde und der entsprechende Fehler geworfen wird.

                          Ja, das ist wohl so. Wie ich erfahren habe, wird ein BEGIN-Block schon vor der Ausführung des Skripts, nämlich bei der Prüfung des Skripts ausgeführt.
                          Heißt dies, dass dann im BEGIN-Block noch gar keine Vaiablen des rufenden Skripts angesprochen werden können ?

                          Gruß
                          Poldi

                          1. Hell-O!

                            Heißt dies, dass dann im BEGIN-Block noch gar keine Vaiablen des rufenden Skripts angesprochen werden können ?

                            Ja, BEGIN-Blöcke werden *vor* der Kompilierung des verbleibenden Scripts ausgeführt, deshalb sind ihm von Haus aus keinerlei Variablen bekannt. Du musst halt zwischen Kompilierung und Ausführung des Scripts unterscheiden. BEGIN-Blöcke werden während der Kompilierung des Scripts ausgeführt und sind danach Geschichte. Daher kann man auch keine Variablen, die im BEGIN-Block deklariert wurden, unter dem strict-Pragma außerhalb dieses Blockes - also während des Ausführens des Scripts - aufrufen, ohne ihre Gültigkeit zur Laufzeit explizit festzulegen.

                            Mal ein paar Beispiele:

                            use strict;  
                            use CGI qw/param/;  
                              
                            BEGIN {  
                              $boo = param('foo');  
                            }  
                              
                            print $boo;
                            

                            Das wird nicht funktionieren. Zwar wird $boo innerhalb des BEGIN-Blocks deklariert, steht während der Ausführung aber nicht zur Verfügung.

                            use strict;  
                            use CGI qw/param/;  
                              
                            BEGIN {  
                              sub return_boo { my $boo = param('foo'); }  
                            }  
                              
                            print return_boo();
                            

                            Das funktioniert, da u.a. das Deklarieren von Subroutinen - ggf. aus anderen Packages - zu den Aufgaben eines BEGIN-Blocks gehört.

                            Und schließlich noch die letzte Variante:

                            use strict;  
                            use CGI qw/param/;  
                              
                            my $boo;  
                              
                            BEGIN {  
                              $boo = param('foo');  
                            }  
                              
                            print $boo;
                            

                            Diese Variante funktioniert auch und kommt dem Grundprinzip des von dir verwendeten Scripts m.E. am nächsten. Die Variable $boo wird zweimal deklariert, nämlich während des Kompilierens im BEGIN-Block (wichtig: Ohne my oder our) und während der Ausführung via my $boo;. Dadurch erhältst du zur Laufzeit Zugriff auf den Inhalt der Variablen, den sie während der Kompilierungsphase erhalten hat. Würdest du es so schreiben:

                            use strict;  
                            use CGI qw/param/;  
                              
                            my $boo = "";  
                              
                            BEGIN {  
                              $boo = param('foo');  
                            }  
                              
                            print $boo;
                            

                            weist du der Variablen einen Leerstring zu und überschreibst damit den Wert, den sie während der Kompilierungsphase im BEGIN-Block erhalten hat.

                            Ich hoffe, ein kleines bisschen Licht ins Dunkel gebracht zu haben :-)

                            Siechfred

                            --
                            Hier könnte Ihre Werbung stehen.
                            Dark Millennium || Die neue 1%-Regelung
                            1. Auch Hell-O!
                              Gut erklärt ! Werde versuchen, damit auch 'mein' Skript zu verstehen (für einen Rentner und Perl-Anfänger gar nicht so einfach). Ich gehe wohl erst ein paar Tage (Wochen) auf Tauchstation, bevor ich mich dann wieder mit einer Erfolgsmeldung (oder einer neuen Frage) melde !
                              Danke
                              Poldi

                      3. Hallo,

                        Ist mein Beitrag untergegangen ?

                        Nein, war nur anders beschaeftigt. Ausserdem, kostet es ein wenig
                        Zeit, so ein langes Script zu analysieren.

                        Zu Jens:

                        # Kleine Modifizierung: Wenn du noch andere Variablen in
                          $tDanke aufrufst, dann  muessn diese auch mit *my*
                        gekennzeichnet werden my $tDanke = ".....";

                        Auf diese Art erhalte ich jetzt zwar keine Fehlermeldung mehr,
                        aber ich weiß nicht, wie ich $tDanke einen dynamischen Wert
                        zuweisen soll.

                        Weil du schon vorher, innerhalb deines Scripts mindestens einen
                        Fehler hast.

                        Gleich am Anfang steht:

                        #!shebang line -wT

                        -w warnings

                        -T Taint modus

                        Anstatt: $tempfaenger = param('empfaenger'); , muss es
                        dann heisen:

                        my $tempfaenger = ($self->cgi_object->param('empfaenger'));

                        Das Modul strict(); erfordert die my Variante.
                        Der Taint Modus, den anderen Code. Das gillt fuer alle deine
                        eingefuegten Variablen. (Zeilen zwischen: 107 und 115)

                        Versuche deine Variablen Deklarationen so frueh wie Moeglich zu machen, innerhalb des im Script vorgegebenen Blocks.

                        # USER CUSTOMISATION SECTION
                          # --------------------------
                          # Place any custom code here

                        Ich wollte allerdings der SELFHTML-Gemeinde nicht ein so langes
                        Script zumuten (über 3500 Zeilen).

                        Generell richtig. Aber hier steckt der Teufgel wohl im Detail.

                        gruesse aus'm ruhrpott
                          jens mueller

                        --
                        As long as a single mind remembers, as long as a single heart
                        beats with passion, how can a dream die?
                        \//_ Live long and prosper
                        sh:( fo:) ch:| rl:° br:^ n4:| ie:% mo:| va:} de:> zu:) fl:( ss:) ls:> js:|
                        1. Hallo Jens,

                          Gleich am Anfang steht:
                          #!shebang line -wT

                          das -wT steht doch erst in der zweiten Zeile, in der ersten steht nur -w. Wird die zweite trotzdem interpretiert ?

                          my $tempfaenger = ($self->cgi_object->param('empfaenger'));

                          Das Skript läuft auch mit
                          $tempfaenger = param('empfaenger');
                          einwandfrei.
                          Das Problem erhalte ich erst, wenn ich diese beiden kleinen Texte variabel gestalten will.
                          Gruß Poldi

                          1. Howdy Poldi,

                            Gleich am Anfang steht:
                            #!shebang line -wT

                            das -wT steht doch erst in der zweiten Zeile, in der ersten
                            steht nur -w. Wird die zweite trotzdem interpretiert ?

                            Ja das wird es:
                               »The #! line is always examined for switches as the line is
                              being parsed.«  Perlrun Manpage

                            Das Skript läuft auch mit $tempfaenger = param('empfaenger');
                            einwandfrei.

                            Sollte nicht, da -T beim Start beachtet wird. Oder aber, das Script
                            selbst fuehrt schon das Parsing durch...
                              Ja tut es:

                            sub parse_config_form_input {  
                              my ($self, $name) = @_;  
                              
                              my $val = $self->strip_nonprint($self->cgi_object->param($name));  
                              if ($name =~ /return_link_url|redirect$/) {  
                                $val = $self->validate_url($val);  
                              }  
                              $self->{FormConfig}{$name} = $val;  
                              unless ($self->{CFG}{emulate_matts_code}) {  
                                $self->{Form}{$name} = $val;  
                                if ( $self->{CFG}{"include_config_$name"} ) {  
                                  push @{ $self->{Field_Order} }, $name;  
                                }  
                              }  
                            }  
                            
                            

                            Das Problem erhalte ich erst, wenn ich diese beiden kleinen
                            Texte variabel gestalten will.

                            Dann extrahiere mal die POD-Doku
                            aus dem Script selbst. Als Text in der Shell oder als HTML Seite.

                            gruesse aus'm ruhrpott
                              jens mueller

                            --
                            As long as a single mind remembers, as long as a single heart
                            beats with passion, how can a dream die?
                            \//_ Live long and prosper
                            sh:( fo:) ch:| rl:° br:^ n4:| ie:% mo:| va:} de:> zu:) fl:( ss:) ls:> js:|
                  2. Zu Jens:

                    # Kleine Modifizierung: Wenn du noch andere Variablen in $tDanke
                      # aufrufst, dann  muessn diese auch mit *my* gekenzeichnet werden
                      my $tDanke = ".....";
                      my $title = $self->escape_html( $self->{FormConfig}{'title'} || "$tDanke");

                    Auf diese Art erhalte ich jetzt zwar keine Fehlermeldung mehr, aber ich weiß nicht, wie ich $tDanke einen dynamischen Wert zuweisen soll.
                    Ich erhalte vom rufenden Skript die Sprache (spr) übergeben.
                    Ich habe also in der Subroutine folgende Befehle eingefügt.
                      my $tsprache    = param('spr');
                      my $tDanke;
                      if ($tsprache == "d")
                         {$tDanke = "Danke für die Nachricht"}
                      else
                         {$tDanke = "Merci pour votre message"};

                    Da bringt mir das System aber nur noch die nichtssagende Meldung

                    Application Error
                    An error has occurred in the program
                    See the web server's error log for details

                    Das Dumme ist nur, ich kann den Log (bei Netbeat) nicht anschauen.

                    Zu Jens und Struppi:

                    Ich sehe vollkommen ein, dass eine realistische Einschätzung der Fehlersituation ohne Vorlage des Script eigentlich nicht möglich ist.
                    Ich wollte allerdings der SELFHTML-Gemeinde nicht ein so langes Script zumuten (über 3500 Zeilen).

                    Falls sich doch jemand die Mühe machen wollte (mein Dank wird ihr/ihm gewiss sein), ich habe das Skript unter
                    beinahe<Minuszeichen>gratis<Punkt>de<Schrägstrich>feedback-test.txt
                    abgestellt (fragliche Stelle ab Zeile 3236).