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