From: Vincent Pit Date: Tue, 7 Jul 2009 22:58:54 +0000 (+0200) Subject: Fix line number for multiline indirect constructs X-Git-Tag: v0.15~3 X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2Findirect.git;a=commitdiff_plain;h=eb4b05d5ad6eec232107b4688e59685bc54f7a65;hp=9e8840b03b5cfb27dc88d7e1e85533fc6bbef6b5 Fix line number for multiline indirect constructs --- diff --git a/MANIFEST b/MANIFEST index aee4fac..512c163 100644 --- a/MANIFEST +++ b/MANIFEST @@ -9,6 +9,7 @@ ptable.h samples/indirect.pl t/00-load.t t/10-args.t +t/11-line.t t/20-good.t t/21-bad.t t/22-bad-mixed.t diff --git a/indirect.xs b/indirect.xs index 9347467..01b4a77 100644 --- a/indirect.xs +++ b/indirect.xs @@ -164,6 +164,7 @@ typedef struct { const char *pos; char *buf; STRLEN len, size; + line_t line; } indirect_op_info_t; #define PTABLE_NAME ptable @@ -368,8 +369,8 @@ STATIC SV *indirect_hint(pTHX) { /* ... op -> source position ............................................... */ -STATIC void indirect_map_store(pTHX_ const OP *o, const char *src, SV *sv) { -#define indirect_map_store(O, S, N) indirect_map_store(aTHX_ (O), (S), (N)) +STATIC void indirect_map_store(pTHX_ const OP *o, const char *src, SV *sv, line_t line) { +#define indirect_map_store(O, S, N, L) indirect_map_store(aTHX_ (O), (S), (N), (L)) indirect_op_info_t *oi; const char *s; STRLEN len; @@ -401,8 +402,9 @@ STATIC void indirect_map_store(pTHX_ const OP *o, const char *src, SV *sv) { oi->size = len; } Copy(s, oi->buf, len, char); - oi->len = len; - oi->pos = src; + oi->len = len; + oi->pos = src; + oi->line = line; } STATIC const indirect_op_info_t *indirect_map_fetch(pTHX_ const OP *o) { @@ -459,7 +461,8 @@ STATIC OP *indirect_ck_const(pTHX_ OP *o) { if (indirect_hint()) { SV *sv = cSVOPo_sv; if (SvPOK(sv) && (SvTYPE(sv) >= SVt_PV)) { - indirect_map_store(o, indirect_find(sv, PL_oldbufptr), sv); + const char *s = indirect_find(sv, PL_oldbufptr); + indirect_map_store(o, s, sv, CopLINE(&PL_compiling)); return o; } } @@ -524,7 +527,7 @@ STATIC OP *indirect_ck_rv2sv(pTHX_ OP *o) { } o = CALL_FPTR(indirect_old_ck_rv2sv)(aTHX_ o); - indirect_map_store(o, s, sv); + indirect_map_store(o, s, sv, CopLINE(&PL_compiling)); return o; } @@ -552,7 +555,7 @@ STATIC OP *indirect_ck_padany(pTHX_ OP *o) { while (s < t && isSPACE(*t)) --t; sv = sv_2mortal(newSVpvn("$", 1)); sv_catpvn_nomg(sv, s, t - s + 1); - indirect_map_store(o, s, sv); + indirect_map_store(o, s, sv, CopLINE(&PL_compiling)); return o; } } @@ -570,22 +573,25 @@ STATIC OP *indirect_ck_method(pTHX_ OP *o) { OP *op = cUNOPo->op_first; const indirect_op_info_t *oi = indirect_map_fetch(op); const char *s = NULL; + line_t line; SV *sv; if (oi && (s = oi->pos)) { - sv = sv_2mortal(newSVpvn(oi->buf, oi->len)); + sv = sv_2mortal(newSVpvn(oi->buf, oi->len)); + line = oi->line; /* Keep the old line so that we really point to the first */ } else { sv = cSVOPx_sv(op); if (!SvPOK(sv) || (SvTYPE(sv) < SVt_PV)) goto done; - sv = sv_mortalcopy(sv); - s = indirect_find(sv, PL_oldbufptr); + sv = sv_mortalcopy(sv); + s = indirect_find(sv, PL_oldbufptr); + line = CopLINE(&PL_compiling); } o = CALL_FPTR(indirect_old_ck_method)(aTHX_ o); /* o may now be a method_named */ - indirect_map_store(o, s, sv); + indirect_map_store(o, s, sv, line); return o; } @@ -646,8 +652,7 @@ STATIC OP *indirect_ck_entersub(pTHX_ OP *o) { goto done; if (moi->pos < ooi->pos) { - SV *file; - line_t line; + SV *file; dSP; ENTER; @@ -658,14 +663,13 @@ STATIC OP *indirect_ck_entersub(pTHX_ OP *o) { #else file = sv_mortalcopy(CopFILESV(&PL_compiling)); #endif - line = CopLINE(&PL_compiling); PUSHMARK(SP); EXTEND(SP, 4); mPUSHp(ooi->buf, ooi->len); mPUSHp(moi->buf, moi->len); PUSHs(file); - mPUSHu(line); + mPUSHu(moi->line); PUTBACK; call_sv(code, G_VOID); diff --git a/t/11-line.t b/t/11-line.t new file mode 100644 index 0000000..6832844 --- /dev/null +++ b/t/11-line.t @@ -0,0 +1,48 @@ +#!perl -T + +use strict; +use warnings; + +use Test::More tests => 3 * 4; + +sub expect { + my ($pkg, $line) = @_; + return qr/^Indirect\s+call\s+of\s+method\s+"new"\s+on\s+object\s+"$pkg"\s+at\s+\(eval\s+\d+\)\s+line\s+$line/; +} + +{ + local $/ = "####"; + while () { + chomp; + s/^\s+//; + + my ($code, $lines) = split /#+/, $_, 2; + $lines = eval "[ sort ($lines) ]"; + if ($@) { + diag "Couldn't parse line numbers: $@"; + next; + } + + my (@warns, @lines); + { + local $SIG{__WARN__} = sub { push @warns, "@_" }; + eval "return; no indirect hook => sub { push \@lines, \$_[3] }; $code"; + } + + is $@, '', 'did\'t croak'; + is_deeply \@warns, [ ], 'didn\'t warn'; + is_deeply [ sort @lines ], $lines, 'correct line numbers'; + } +} + +__DATA__ +my $x = new X; # 1 +#### +my $x = new + X; # 1 +#### +my $x = new X; $x = new X; # 1, 1 +#### +my $x = new + X new + X; # 1, 2