BEGIN/CHECK Block oder nicht?
BEGIN/CHECK Block oder nicht?
am 23.05.2007 15:28:54 von Ferry Bolhar
Hallo,
gibt es eine Möglichkeit für Code, festzustellen, ob er in einem
BEGIN/CHECK/INIT/END Block oder zur "normalen" Laufzeit
abläuft?
Und bevor jetzt die Frage nach dem "Wozu" kommt: es kann
für Code, der z.B. die Symboltabelle manipuliert, von Interesse
sein, ob er jetzt mit einem "use" oder einem "require" geladen
wird. Auch für XS-Code kann es interessant sein, ob er vor
dem eigentlichen Program abläuft oder bereits während des
Programmlaufes.
Ich kenne nur $^S, aber das unterscheidet nur zwischen
BEGIN, dem Hauptprogramm und eval; die anderen Blöcke
werden wie eval's betrachtet (was sie ja eigentlich auch sind,
nur dass sie der Perl-Core eben selbst aufruft).
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: BEGIN/CHECK Block oder nicht?
am 23.05.2007 17:12:07 von Frank Seitz
Ferry Bolhar wrote:
>
> gibt es eine Möglichkeit für Code, festzustellen, ob er in einem
> BEGIN/CHECK/INIT/END Block oder zur "normalen" Laufzeit
> abläuft?
>
> Und bevor jetzt die Frage nach dem "Wozu" kommt: es kann
> für Code, der z.B. die Symboltabelle manipuliert, von Interesse
> sein, ob er jetzt mit einem "use" oder einem "require" geladen
> wird.
Den Unterschied zwischen use und require könntest Du herausfinden,
indem Du import() definierst. Die Subroutine wird ja nur
im Falle von use gerufen.
> Auch für XS-Code kann es interessant sein, ob er vor
> dem eigentlichen Program abläuft oder bereits während des
> Programmlaufes.
Wenn $^S dies noch nicht leistet (verstehe die Variable nicht
so ganz), müsste das durch Definition eines CHECK{}- oder
INIT{}-Blocks erkennbar sein (durch Setzen einer eigenen Variable).
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: BEGIN/CHECK Block oder nicht?
am 23.05.2007 21:46:57 von Ferry Bolhar
Frank Seitz:
> Den Unterschied zwischen use und require könntest Du herausfinden,
> indem Du import() definierst. Die Subroutine wird ja nur
> im Falle von use gerufen.
Naja, import() kann aber auch zur Laufzeit aufgerufen werden:
require Hugo;
Hugo->import();
Der Aufruf von import() alleine ist noch keine Garantie, dass
ein "use" (und damit ein BEGIN-Block) abgearbeitet wird.
>> Auch für XS-Code kann es interessant sein, ob er vor
>> dem eigentlichen Program abläuft oder bereits während des
>> Programmlaufes.
>
> Wenn $^S dies noch nicht leistet (verstehe die Variable nicht
> so ganz), müsste das durch Definition eines CHECK{}- oder
> INIT{}-Blocks erkennbar sein (durch Setzen einer eigenen Variable).
Soweit ich verstanden habe, sind die Bedeutungen folgende:
undef: BEGIN Block
0: normaler Code
1: eval-Block (und auch CHECK/INIT/END Blöcke)
Man kann also mit $^S nicht unterscheiden, ob jetzt Code eines
normalen eval-Blocks oder einer der übrigen benannten Blöcke
abläuft. $^S berücksichtigt auch nicht die Möglichkeit von Source-
Filtern, deren Code ja noch vor der eigentlichen Compilierungs-
phase abgearbeitet wird, und Code von I/O Layern und Attribute-
Handlern. Der Code all dieser Blöcke läuft in ganz speziellen
Umgebungen ab, sodass es u.U. interessant sein könnte zu wissen,
wo man sich gerade befindet. Man müsste $^S entsprechend
erweitern.
LG, Fery
--
Re: BEGIN/CHECK Block oder nicht?
am 24.05.2007 11:08:04 von Frank Seitz
Ferry Bolhar wrote:
> Frank Seitz:
>>
>>Den Unterschied zwischen use und require könntest Du herausfinden,
>>indem Du import() definierst. Die Subroutine wird ja nur
>>im Falle von use gerufen.
>
> Naja, import() kann aber auch zur Laufzeit aufgerufen werden:
>
> require Hugo;
> Hugo->import();
>
> Der Aufruf von import() alleine ist noch keine Garantie, dass
> ein "use" (und damit ein BEGIN-Block) abgearbeitet wird.
Wenn Du es für Dein Modul definierst, dass import()
nicht händisch gerufen werden soll, ist das für
mein Gefühl ausreichend.
> Soweit ich verstanden habe, sind die Bedeutungen folgende:
>
> undef: BEGIN Block
> 0: normaler Code
> 1: eval-Block (und auch CHECK/INIT/END Blöcke)
>
> Man kann also mit $^S nicht unterscheiden, ob jetzt Code eines
> normalen eval-Blocks oder einer der übrigen benannten Blöcke
> abläuft.
Hm, 1 auch in CHECK/INIT/END-Blöcken? Was haben die mit eval zu tun?
Ich frage $^S in einem $SIG{__DIE__}-Handler ab,
um zu erkennen, ob eine Exception anderweitig abgefangen wird
und lasse sie im Falle von 1 passieren. Das wird auch so empfohlen,
scheint demnach aber nicht vollkommen sicher zu sein.
Naja, in dem Bereich ist Perl ganz schön schmutzig.
> Man kann also mit $^S nicht unterscheiden, ob jetzt Code eines
> normalen eval-Blocks oder einer der übrigen benannten Blöcke
> abläuft. $^S berücksichtigt auch nicht die Möglichkeit von Source-
> Filtern, deren Code ja noch vor der eigentlichen Compilierungs-
> phase abgearbeitet wird, und Code von I/O Layern und Attribute-
> Handlern. Der Code all dieser Blöcke läuft in ganz speziellen
> Umgebungen ab, sodass es u.U. interessant sein könnte zu wissen,
> wo man sich gerade befindet. Man müsste $^S entsprechend
> erweitern.
Oder man sorgt durch Setzung einer eigenen Zustandsvariable
dafür, dass einem der gewünschte Verarbeitungsstand angezeigt
wird.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: BEGIN/CHECK Block oder nicht?
am 24.05.2007 11:25:46 von Christian Winter
Ferry Bolhar schrieb:
> gibt es eine Möglichkeit für Code, festzustellen, ob er in einem
> BEGIN/CHECK/INIT/END Block oder zur "normalen" Laufzeit
> abläuft?
>
> Und bevor jetzt die Frage nach dem "Wozu" kommt: es kann
> für Code, der z.B. die Symboltabelle manipuliert, von Interesse
> sein, ob er jetzt mit einem "use" oder einem "require" geladen
> wird. Auch für XS-Code kann es interessant sein, ob er vor
> dem eigentlichen Program abläuft oder bereits während des
> Programmlaufes.
>
> Ich kenne nur $^S, aber das unterscheidet nur zwischen
> BEGIN, dem Hauptprogramm und eval; die anderen Blöcke
> werden wie eval's betrachtet (was sie ja eigentlich auch sind,
> nur dass sie der Perl-Core eben selbst aufruft).
Ein solcher Aufruf sollte sich über (caller($x))[3] erwischen
lassen:
------------------------------------------------------------ -
package SpecialBlock;
use Exporter;
our @ISA =qw(Exporter);
our @EXPORT = qw(specialblock);
my $specialre = join '|', qw(BEGIN CHECK INIT DESTROY END);
sub specialblock {
my $pos = 1;
while( my @info = caller($pos++) ) {
return $1 if( $info[3] =~ /::($specialre)$/ );
}
return undef;
}
1;
------------------------------------------------------------ --
-Christian