t/op/eval.t See if eval operator works
t/op/exec.t See if exec and system work
t/op/exp.t See if math functions work
+t/op/fh.t See if filehandles work
t/op/filetest.t See if file tests work
t/op/flip.t See if range operator works
t/op/fork.t See if fork works
#define invert CPerlObj::Perl_invert
#define io_close CPerlObj::Perl_io_close
#define is_an_int CPerlObj::Perl_is_an_int
+#define is_handle_constructor CPerlObj::Perl_is_handle_constructor
#define is_uni_alnum CPerlObj::Perl_is_uni_alnum
#define is_uni_alnum_lc CPerlObj::Perl_is_uni_alnum_lc
#define is_uni_alpha CPerlObj::Perl_is_uni_alpha
bset_obj_store
new_logop
simplify_sort
+ is_handle_constructor
do_trans_CC_simple
do_trans_CC_count
do_trans_CC_complex
#define io_close pPerl->Perl_io_close
#undef is_an_int
#define is_an_int pPerl->Perl_is_an_int
+#undef is_handle_constructor
+#define is_handle_constructor pPerl->Perl_is_handle_constructor
#undef is_uni_alnum
#define is_uni_alnum pPerl->Perl_is_uni_alnum
#undef is_uni_alnum_lc
static OP *newDEFSVOP _((void));
static OP *new_logop _((I32 type, I32 flags, OP **firstp, OP **otherp));
static void simplify_sort _((OP *o));
+static bool is_handle_constructor _((OP *o, I32 argnum));
#endif
STATIC char*
}
}
+STATIC bool
+is_handle_constructor(OP *o, I32 argnum)
+{
+ switch (o->op_type) {
+ case OP_PIPE_OP:
+ case OP_SOCKPAIR:
+ if (argnum == 2)
+ return TRUE;
+ /* FALL THROUGH */
+ case OP_SYSOPEN:
+ case OP_OPEN:
+ case OP_SOCKET:
+ case OP_OPEN_DIR:
+ case OP_ACCEPT:
+ if (argnum == 1)
+ return TRUE;
+ /* FALL THROUGH */
+ default:
+ return FALSE;
+ }
+}
+
OP *
refkids(OP *o, I32 type)
{
ref(kid, type);
break;
case OP_RV2SV:
+ if (type == OP_DEFINED)
+ o->op_flags |= OPf_SPECIAL; /* don't create GV */
ref(cUNOPo->op_first, o->op_type);
/* FALL THROUGH */
case OP_PADSV:
o->op_flags |= OPf_REF;
/* FALL THROUGH */
case OP_RV2GV:
+ if (type == OP_DEFINED)
+ o->op_flags |= OPf_SPECIAL; /* don't create GV */
ref(cUNOPo->op_first, o->op_type);
break;
*tokid = kid;
}
else if (kid->op_type != OP_RV2AV && kid->op_type != OP_PADAV)
- bad_type(numargs, "array", PL_op_desc[o->op_type], kid);
+ bad_type(numargs, "array", PL_op_desc[type], kid);
mod(kid, type);
break;
case OA_HVREF:
*tokid = kid;
}
else if (kid->op_type != OP_RV2HV && kid->op_type != OP_PADHV)
- bad_type(numargs, "hash", PL_op_desc[o->op_type], kid);
+ bad_type(numargs, "hash", PL_op_desc[type], kid);
mod(kid, type);
break;
case OA_CVREF:
bad_type(numargs, "HANDLE", PL_op_desc[o->op_type], kid);
}
else {
+ I32 flags = OPf_SPECIAL;
+ /* is this op a FH constructor? */
+ if (is_handle_constructor(o,numargs))
+ flags = 0;
kid->op_sibling = 0;
- kid = newUNOP(OP_RV2GV, 0, scalar(kid));
+ kid = newUNOP(OP_RV2GV, flags, scalar(kid));
}
kid->op_sibling = sibl;
*tokid = kid;
(F) This machine doesn't implement the select() system call.
+=item select() on unopened file
+
+(W) You tried to use the select() function on a filehandle that
+was either never opened or has since been closed.
+
=item sem%s not implemented
(F) You don't have System V semaphore IPC on your system.
RETSETUNDEF;
}
sym = SvPV(sv, n_a);
- if (PL_op->op_private & HINT_STRICT_REFS)
- DIE(PL_no_symref, sym, "a symbol");
- sv = (SV*)gv_fetchpv(sym, TRUE, SVt_PVGV);
+ if ((PL_op->op_flags & OPf_SPECIAL) &&
+ !(PL_op->op_flags & OPf_MOD))
+ {
+ sv = (SV*)gv_fetchpv(sym, FALSE, SVt_PVGV);
+ if (!sv)
+ RETSETUNDEF;
+ }
+ else {
+ if (PL_op->op_private & HINT_STRICT_REFS)
+ DIE(PL_no_symref, sym, "a symbol");
+ sv = (SV*)gv_fetchpv(sym, TRUE, SVt_PVGV);
+ }
}
}
if (PL_op->op_private & OPpLVAL_INTRO)
RETSETUNDEF;
}
sym = SvPV(sv, n_a);
- if (PL_op->op_private & HINT_STRICT_REFS)
- DIE(PL_no_symref, sym, "a SCALAR");
- gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PV);
+ if ((PL_op->op_flags & OPf_SPECIAL) &&
+ !(PL_op->op_flags & OPf_MOD))
+ {
+ gv = (GV*)gv_fetchpv(sym, FALSE, SVt_PV);
+ if (!gv)
+ RETSETUNDEF;
+ }
+ else {
+ if (PL_op->op_private & HINT_STRICT_REFS)
+ DIE(PL_no_symref, sym, "a SCALAR");
+ gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PV);
+ }
}
sv = GvSV(gv);
}
RETSETUNDEF;
}
sym = SvPV(sv,n_a);
- if (PL_op->op_private & HINT_STRICT_REFS)
- DIE(PL_no_symref, sym, "an ARRAY");
- gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PVAV);
- } else {
+ if ((PL_op->op_flags & OPf_SPECIAL) &&
+ !(PL_op->op_flags & OPf_MOD))
+ {
+ gv = (GV*)gv_fetchpv(sym, FALSE, SVt_PVAV);
+ if (!gv)
+ RETSETUNDEF;
+ }
+ else {
+ if (PL_op->op_private & HINT_STRICT_REFS)
+ DIE(PL_no_symref, sym, "an ARRAY");
+ gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PVAV);
+ }
+ }
+ else {
gv = (GV*)sv;
}
av = GvAVn(gv);
RETSETUNDEF;
}
sym = SvPV(sv,n_a);
- if (PL_op->op_private & HINT_STRICT_REFS)
- DIE(PL_no_symref, sym, "a HASH");
- gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PVHV);
- } else {
+ if ((PL_op->op_flags & OPf_SPECIAL) &&
+ !(PL_op->op_flags & OPf_MOD))
+ {
+ gv = (GV*)gv_fetchpv(sym, FALSE, SVt_PVHV);
+ if (!gv)
+ RETSETUNDEF;
+ }
+ else {
+ if (PL_op->op_private & HINT_STRICT_REFS)
+ DIE(PL_no_symref, sym, "a HASH");
+ gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PVHV);
+ }
+ }
+ else {
gv = (GV*)sv;
}
hv = GvHVn(gv);
}
if (newdefout) {
- if (!GvIO(newdefout))
- gv_IOadd(newdefout);
+ if (!GvIO(newdefout)) {
+ if (ckWARN(WARN_UNOPENED))
+ warner(WARN_UNOPENED, "select() on unopened file");
+ if (SvTYPE(newdefout) != SVt_PVGV)
+ RETURN;
+ gv_IOadd(newdefout); /* XXX probably bogus */
+ }
setdefout(newdefout);
}
void *bset_obj_store _((void *obj, I32 ix));
OP *new_logop _((I32 type, I32 flags, OP **firstp, OP **otherp));
void simplify_sort _((OP *o));
+bool is_handle_constructor _((OP *o, I32 argnum));
I32 do_trans_CC_simple _((SV *sv));
I32 do_trans_CC_count _((SV *sv));
--- /dev/null
+#!./perl
+
+print "1..6\n";
+
+my $test = 0;
+
+# symbolic filehandles should only result in glob entries with FH constructors
+
+my $a = "SYM000";
+print "not " if defined(fileno($a)) or defined *{$a};
+++$test; print "ok $test\n";
+
+select select $a;
+print "not " if defined *{$a};
+++$test; print "ok $test\n";
+
+print "not " if close $a or defined *{$a};
+++$test; print "ok $test\n";
+
+print "not " unless open($a, ">&STDOUT") and defined *{$a};
+++$test; print $a "ok $test\n";
+
+print "not " unless close $a;
+++$test; print $a "not "; print "ok $test\n";
# various typeglob tests
#
-print "1..23\n";
+print "1..29\n";
# type coersion on assignment
$foo = 'foo';
print {*x{IO}} "ok 22\n";
print {*x{FILEHANDLE}} "ok 23\n";
+# test if defined() doesn't create any new symbols
+
+{
+ my $test = 23;
+
+ my $a = "SYM000";
+ print "not " if defined *{$a};
+ ++$test; print "ok $test\n";
+
+ print "not " if defined @{$a} or defined *{$a};
+ ++$test; print "ok $test\n";
+
+ print "not " if defined %{$a} or defined *{$a};
+ ++$test; print "ok $test\n";
+
+ print "not " if defined ${$a} or defined *{$a};
+ ++$test; print "ok $test\n";
+
+ print "not " if defined &{$a} or defined *{$a};
+ ++$test; print "ok $test\n";
+
+ *{$a} = sub { print "ok $test\n" };
+ print "not " unless defined &{$a} and defined *{$a};
+ ++$test; &{$a};
+}
package X;
sub any { bless {} }
my $f = "FH000"; # just to thwart any future optimisations
-sub afh { select select ++$f; my $r = *{$f}{IO}; delete $X::{$f}; bless $r }
+sub afh {
+ open(++$f, '>&STDOUT') or die;
+ select select $f;
+ my $r = *{$f}{IO};
+ delete $X::{$f};
+ bless $r;
+}
sub DESTROY { print "destroyed\n" }
package main;
$x = any X; # to bump sv_objcount. IO objs aren't counted??