2

caller関数が呼び出されたファイル名と行番号がわかりますが、文字またはバイトのオフセットを取得するにはどうすればよいですか? そのために XS にドロップダウンしなければならない場合でも問題ありません (関数はいずれにせよ XS になる可能性があります)。

私がやろうとしているのは、関数へのすべての呼び出しを一意に識別することです。そのため、ソース内の場所よりも優れた方法があれば、他のルートを受け入れることができます。

基本的な意図はeach、同じハッシュを安全に反復できる関数を作成することです。これは、私が考えているものに似た純粋な Perl バージョンです。

#!/usr/bin/perl

use 5.012;
use warnings;
use Scalar::Util qw/refaddr/;

sub safe_each(\%) {
    my $h    = shift;
    my $key  = join "/", (caller)[1,2], refaddr $h;
    state %iter;

    unless (exists $iter{$key}) {
        $iter{$key} = [ keys %$h ];
    }

    unless (@{$iter{$key}}) {
        delete $iter{$key};
        return;
    }

    my $cur = shift @{$iter{$key}};

    return wantarray ? ($cur, $h->{$cur}) : $cur;
}

my %h = (a => 1, b => 2);
while (my ($k, $v) = safe_each %h) {
    say "$k => $v";
    while (my ($k, $v) = safe_each %h) {
        say "\t$k => $v";
    }
}
4

1 に答える 1

1

perl デバッガーは、必要なソース ファイルのすべての行を、エントリの下のメイン シンボル テーブルにロードします。

@::{"_<$path_to_file"}

このようにして、ファイルFILEのLINE行でブレークポイントに到達すると、デバッガーは実行しようとしているコード行を表示できます。

$::{"_<FILE"}[LINE]

ただし、この情報を使用して、ソース ファイルへの現在の文字オフセットを計算することもできます。

sub _get_offset_into_file {
    my ($file,$line) = @_;
    my *teh_codez = @::{"_<$file"};

    my $offset = 0;
    # the debugger spoofs line $teh_codez[0], so don't include it in offset calc
    $offset += length $_ for @teh_codez[1 .. $line-1];
    return $offset
}

デバッガーの下でコードを実行するか、デバッガーが行うことをエミュレートしてファイルを自分でメモリにロードすることができます (そうすれば、同じ "_<" + ファイル名規則を使用したり、シンボル テーブルをまったく使用したりする必要がなくなります)。 )。

これがあなたが求めている質問とはまったく異なる質問への回答である場合は申し訳ありません。

于 2010-06-25T18:08:38.363 に答える