summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Ing-Simmons <nik@tiuk.ti.com>1997-11-22 16:30:27 +0000
committerNick Ing-Simmons <nik@tiuk.ti.com>1997-11-22 16:30:27 +0000
commitf81342c8ed56420002f9ad172de0b7485a7c6b96 (patch)
tree921a34f0d4476503ddbf328e789517d6cfd07e42
parenta868473fb9213692497e27ae968094b32a41c501 (diff)
parent0da4822f11e97ce202166899552c06d720eb835a (diff)
downloadperl-f81342c8ed56420002f9ad172de0b7485a7c6b96.tar.gz
Resolve ansiperl against win32
p4raw-id: //depot/ansiperl@278
-rw-r--r--embed.h4
-rw-r--r--ext/Thread/Thread.xs2
-rw-r--r--global.sym4
-rw-r--r--op.c82
-rw-r--r--op.h1
-rw-r--r--perl.c10
-rw-r--r--perl.h8
-rw-r--r--perly.c2
-rw-r--r--perly.c.diff53
-rw-r--r--perly.y2
-rw-r--r--pp.c11
-rw-r--r--pp_ctl.c26
-rw-r--r--pp_hot.c6
-rw-r--r--proto.h3
-rw-r--r--scope.c19
-rw-r--r--sv.h72
-rwxr-xr-xt/lib/english.t10
-rwxr-xr-xt/op/misc.t11
-rw-r--r--thread.h2
-rw-r--r--toke.c13
-rw-r--r--util.c15
-rw-r--r--vms/perly_c.vms11
-rw-r--r--win32/win32sck.c86
23 files changed, 263 insertions, 190 deletions
diff --git a/embed.h b/embed.h
index 6069959d5c..b577200f98 100644
--- a/embed.h
+++ b/embed.h
@@ -216,6 +216,7 @@
#define filter_add Perl_filter_add
#define filter_del Perl_filter_del
#define filter_read Perl_filter_read
+#define find_threadsv Perl_find_threadsv
#define fold Perl_fold
#define fold_constants Perl_fold_constants
#define fold_locale Perl_fold_locale
@@ -516,7 +517,6 @@
#define padix Perl_padix
#define patleave Perl_patleave
#define peep Perl_peep
-#define per_thread_magicals Perl_per_thread_magicals
#define pidgone Perl_pidgone
#define pidstatus Perl_pidstatus
#define pmflag Perl_pmflag
@@ -938,6 +938,7 @@
#define save_scalar Perl_save_scalar
#define save_sptr Perl_save_sptr
#define save_svref Perl_save_svref
+#define save_threadsv Perl_save_threadsv
#define savepv Perl_savepv
#define savepvn Perl_savepvn
#define savestack Perl_savestack
@@ -1084,6 +1085,7 @@
#define thisexpr Perl_thisexpr
#define thr_key Perl_thr_key
#define threads_mutex Perl_threads_mutex
+#define threadsv_names Perl_threadsv_names
#define timesbuf Perl_timesbuf
#define tokenbuf Perl_tokenbuf
#define too_few_arguments Perl_too_few_arguments
diff --git a/ext/Thread/Thread.xs b/ext/Thread/Thread.xs
index db1b5d7dd2..0844312dd4 100644
--- a/ext/Thread/Thread.xs
+++ b/ext/Thread/Thread.xs
@@ -147,7 +147,7 @@ threadstart(void *arg)
SvREFCNT_dec(curstack);
#endif
SvREFCNT_dec(thr->cvcache);
- SvREFCNT_dec(thr->magicals);
+ SvREFCNT_dec(thr->threadsv);
SvREFCNT_dec(thr->specific);
SvREFCNT_dec(thr->errsv);
SvREFCNT_dec(thr->errhv);
diff --git a/global.sym b/global.sym
index e422fba58e..46378729d6 100644
--- a/global.sym
+++ b/global.sym
@@ -63,6 +63,7 @@ exp_amg
expect
expectterm
fallback_amg
+find_threadsv
fold
fold_locale
freq
@@ -163,7 +164,6 @@ pad_reset_pending
padix
padix_floor
patleave
-per_thread_magicals
pidstatus
pow_amg
pow_ass_amg
@@ -223,6 +223,7 @@ sv_no
sv_undef
sv_yes
thisexpr
+threadsv_names
thr_key
timesbuf
tokenbuf
@@ -1048,6 +1049,7 @@ save_pptr
save_scalar
save_sptr
save_svref
+save_threadsv
savepv
savepvn
savestack_grow
diff --git a/op.c b/op.c
index 30cbe3a20e..029aac85a7 100644
--- a/op.c
+++ b/op.c
@@ -40,6 +40,7 @@ static OP *too_many_arguments _((OP *o, char* name));
static void null _((OP* o));
static PADOFFSET pad_findlex _((char* name, PADOFFSET newoff, U32 seq,
CV* startcv, I32 cx_ix));
+static OP *newDEFSVOP _((void));
static char*
gv_ename(GV *gv)
@@ -496,42 +497,46 @@ pad_reset(void)
}
#ifdef USE_THREADS
-/* find_thread_magical is not reentrant */
+/* find_threadsv is not reentrant */
PADOFFSET
-find_thread_magical(char *name)
+find_threadsv(char *name)
{
dTHR;
char *p;
PADOFFSET key;
SV **svp;
- /* We currently only handle single character magicals */
- p = strchr(per_thread_magicals, *name);
+ /* We currently only handle names of a single character */
+ p = strchr(threadsv_names, *name);
if (!p)
return NOT_IN_PAD;
- key = p - per_thread_magicals;
- svp = av_fetch(thr->magicals, key, FALSE);
+ key = p - threadsv_names;
+ svp = av_fetch(thr->threadsv, key, FALSE);
if (!svp) {
SV *sv = NEWSV(0, 0);
- av_store(thr->magicals, key, sv);
+ av_store(thr->threadsv, key, sv);
/*
* Some magic variables used to be automagically initialised
* in gv_fetchpv. Those which are now per-thread magicals get
* initialised here instead.
*/
switch (*name) {
+ case '_':
+ break;
case ';':
sv_setpv(sv, "\034");
+ sv_magic(sv, 0, 0, name, 1);
break;
case '&':
case '`':
case '\'':
sawampersand = TRUE;
SvREADONLY_on(sv);
+ default:
+ sv_magic(sv, 0, 0, name, 1);
break;
}
- sv_magic(sv, 0, 0, name, 1);
DEBUG_L(PerlIO_printf(PerlIO_stderr(),
- "find_thread_magical: new SV %p for $%s%c\n",
+ "find_threadsv: new SV %p for $%s%c\n",
sv, (*name < 32) ? "^" : "",
(*name < 32) ? toCTRL(*name) : *name));
}
@@ -565,7 +570,7 @@ op_free(OP *o)
break;
#ifdef USE_THREADS
case OP_THREADSV:
- o->op_targ = 0; /* Was holding index into thr->magicals AV. */
+ o->op_targ = 0; /* Was holding index into thr->threadsv AV. */
break;
#endif /* USE_THREADS */
default:
@@ -613,7 +618,7 @@ op_free(OP *o)
static void
null(OP *o)
{
- if (o->op_type != OP_NULL && o->op_targ > 0)
+ if (o->op_type != OP_NULL && o->op_type != OP_THREADSV && o->op_targ > 0)
pad_free(o->op_targ);
o->op_targ = o->op_type;
o->op_type = OP_NULL;
@@ -1529,6 +1534,18 @@ block_end(I32 floor, OP *seq)
return retval;
}
+static OP *
+newDEFSVOP(void)
+{
+#ifdef USE_THREADS
+ OP *o = newOP(OP_THREADSV, 0);
+ o->op_targ = find_threadsv("_");
+ return o;
+#else
+ return newSVREF(newGVOP(OP_GV, 0, defgv));
+#endif /* USE_THREADS */
+}
+
void
newPROG(OP *o)
{
@@ -1592,7 +1609,7 @@ jmaybe(OP *o)
OP *o2;
#ifdef USE_THREADS
o2 = newOP(OP_THREADSV, 0);
- o2->op_targ = find_thread_magical(";");
+ o2->op_targ = find_threadsv(";");
#else
o2 = newSVREF(newGVOP(OP_GV, 0, gv_fetchpv(";", TRUE, SVt_PV))),
#endif /* USE_THREADS */
@@ -2110,7 +2127,7 @@ pmruntime(OP *o, OP *expr, OP *repl)
#ifdef USE_THREADS
else if (repl->op_type == OP_THREADSV
&& strchr("&`'123456789+",
- per_thread_magicals[repl->op_targ]))
+ threadsv_names[repl->op_targ]))
{
curop = 0;
}
@@ -2793,7 +2810,7 @@ newLOOPOP(I32 flags, I32 debuggable, OP *expr, OP *block)
if (expr->op_type == OP_READLINE || expr->op_type == OP_GLOB
|| (expr->op_type == OP_NULL && expr->op_targ == OP_GLOB)) {
expr = newUNOP(OP_DEFINED, 0,
- newASSIGNOP(0, newSVREF(newGVOP(OP_GV, 0, defgv)), 0, expr) );
+ newASSIGNOP(0, newDEFSVOP(), 0, expr) );
}
}
@@ -2827,7 +2844,7 @@ newWHILEOP(I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *expr, OP *b
if (expr && (expr->op_type == OP_READLINE || expr->op_type == OP_GLOB
|| (expr->op_type == OP_NULL && expr->op_targ == OP_GLOB))) {
expr = newUNOP(OP_DEFINED, 0,
- newASSIGNOP(0, newSVREF(newGVOP(OP_GV, 0, defgv)), 0, expr) );
+ newASSIGNOP(0, newDEFSVOP(), 0, expr) );
}
if (!block)
@@ -2914,11 +2931,22 @@ newFOROP(I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *block,OP *cont
op_free(sv);
sv = Nullop;
}
+ else if (sv->op_type == OP_THREADSV) { /* per-thread variable */
+ padoff = sv->op_targ;
+ iterflags |= OPf_SPECIAL;
+ op_free(sv);
+ sv = Nullop;
+ }
else
croak("Can't use %s for loop variable", op_desc[sv->op_type]);
}
else {
+#ifdef USE_THREADS
+ padoff = find_threadsv("_");
+ iterflags |= OPf_SPECIAL;
+#else
sv = newGVOP(OP_GV, 0, defgv);
+#endif
}
if (expr->op_type == OP_RV2AV || expr->op_type == OP_PADAV) {
expr = scalar(ref(expr, OP_ITER));
@@ -3409,9 +3437,9 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
CV *cv;
HV *hv;
- sv_setpvf(sv, "%_:%ld-%ld",
- GvSV(curcop->cop_filegv),
- (long)subline, (long)curcop->cop_line);
+ sv_setpvf(sv, "%_:%ld-%ld", GvSV(curcop->cop_filegv),
+ (long)(subline < 0 ? -subline : subline),
+ (long)curcop->cop_line);
gv_efullname3(tmpstr, gv, Nullch);
hv_store(GvHV(DBsub), SvPVX(tmpstr), SvCUR(tmpstr), sv, 0);
if (!db_postponed) {
@@ -3846,7 +3874,7 @@ ck_eval(OP *o)
}
else {
op_free(o);
- o = newUNOP(OP_ENTEREVAL, 0, newSVREF(newGVOP(OP_GV, 0, defgv)));
+ o = newUNOP(OP_ENTEREVAL, 0, newDEFSVOP());
}
o->op_targ = (PADOFFSET)hints;
return o;
@@ -3974,7 +4002,7 @@ ck_ftst(OP *o)
return newGVOP(type, OPf_REF, gv_fetchpv("main::STDIN", TRUE,
SVt_PVIO));
else
- return newUNOP(type, 0, newSVREF(newGVOP(OP_GV, 0, defgv)));
+ return newUNOP(type, 0, newDEFSVOP());
}
return o;
}
@@ -4007,7 +4035,7 @@ ck_fun(OP *o)
kid = kid->op_sibling;
}
if (!kid && opargs[type] & OA_DEFGV)
- *tokid = kid = newSVREF(newGVOP(OP_GV, 0, defgv));
+ *tokid = kid = newDEFSVOP();
while (oa && kid) {
numargs++;
@@ -4105,7 +4133,7 @@ ck_fun(OP *o)
}
else if (opargs[type] & OA_DEFGV) {
op_free(o);
- return newUNOP(type, 0, newSVREF(newGVOP(OP_GV, 0, defgv)));
+ return newUNOP(type, 0, newDEFSVOP());
}
if (oa) {
@@ -4123,7 +4151,7 @@ ck_glob(OP *o)
GV *gv;
if ((o->op_flags & OPf_KIDS) && !cLISTOPo->op_first->op_sibling)
- append_elem(OP_GLOB, o, newSVREF(newGVOP(OP_GV, 0, defgv)));
+ append_elem(OP_GLOB, o, newDEFSVOP());
if (!((gv = gv_fetchpv("glob", FALSE, SVt_PVCV)) && GvIMPORTED_CV(gv)))
gv = gv_fetchpv("CORE::GLOBAL::glob", FALSE, SVt_PVCV);
@@ -4260,7 +4288,7 @@ ck_listiob(OP *o)
}
if (!kid)
- append_elem(o->op_type, o, newSVREF(newGVOP(OP_GV, 0, defgv)) );
+ append_elem(o->op_type, o, newDEFSVOP());
o = listkids(o);
@@ -4383,7 +4411,7 @@ ck_shift(OP *o)
op_free(o);
#ifdef USE_THREADS
- if (subline) {
+ if (subline > 0) {
argop = newOP(OP_PADAV, OPf_REF);
argop->op_targ = 0; /* curpad[0] is @_ */
}
@@ -4394,7 +4422,7 @@ ck_shift(OP *o)
}
#else
argop = newUNOP(OP_RV2AV, 0,
- scalar(newGVOP(OP_GV, 0, subline ?
+ scalar(newGVOP(OP_GV, 0, subline > 0 ?
defgv : gv_fetchpv("ARGV", TRUE, SVt_PVAV))));
#endif /* USE_THREADS */
return newUNOP(type, 0, scalar(argop));
@@ -4485,7 +4513,7 @@ ck_split(OP *o)
scalar(kid);
if (!kid->op_sibling)
- append_elem(OP_SPLIT, o, newSVREF(newGVOP(OP_GV, 0, defgv)) );
+ append_elem(OP_SPLIT, o, newDEFSVOP());
kid = kid->op_sibling;
scalar(kid);
diff --git a/op.h b/op.h
index 6aa441f666..e3d3f3d93e 100644
--- a/op.h
+++ b/op.h
@@ -74,6 +74,7 @@ typedef U32 PADOFFSET;
/* On UNOPs, saw bare parens, e.g. eof(). */
/* On OP_ENTERSUB || OP_NULL, saw a "do". */
/* On OP_(ENTER|LEAVE)EVAL, don't clear $@ */
+ /* On OP_ENTERITER, loop var is per-thread */
/* old names; don't use in new code, but don't break them, either */
#define OPf_LIST 1
diff --git a/perl.c b/perl.c
index db5821c642..3608f0dd34 100644
--- a/perl.c
+++ b/perl.c
@@ -937,7 +937,7 @@ print \" \\@INC:\\n @INC\\n\";");
SvREFCNT_dec(rs);
rs = SvREFCNT_inc(nrs);
#ifdef USE_THREADS
- sv_setsv(*av_fetch(thr->magicals, find_thread_magical("/"), FALSE), rs);
+ sv_setsv(*av_fetch(thr->threadsv, find_threadsv("/"), FALSE), rs);
#else
sv_setsv(GvSV(gv_fetchpv("/", TRUE, SVt_PV)), rs);
#endif /* USE_THREADS */
@@ -1052,10 +1052,10 @@ perl_get_sv(char *name, I32 create)
GV *gv;
#ifdef USE_THREADS
if (name[1] == '\0' && !isALPHA(name[0])) {
- PADOFFSET tmp = find_thread_magical(name);
+ PADOFFSET tmp = find_threadsv(name);
if (tmp != NOT_IN_PAD) {
dTHR;
- return *av_fetch(thr->magicals, tmp, FALSE);
+ return *av_fetch(thr->threadsv, tmp, FALSE);
}
}
#endif /* USE_THREADS */
@@ -2501,7 +2501,7 @@ init_predump_symbols(void)
GV *othergv;
#ifdef USE_THREADS
- sv_setpvn(*av_fetch(thr->magicals,find_thread_magical("\""),FALSE)," ", 1);
+ sv_setpvn(*av_fetch(thr->threadsv,find_threadsv("\""),FALSE)," ", 1);
#else
sv_setpvn(GvSV(gv_fetchpv("\"", TRUE, SVt_PV)), " ", 1);
#endif /* USE_THREADS */
@@ -2789,7 +2789,7 @@ init_main_thread()
Newz(53, thr, 1, struct thread);
curcop = &compiling;
thr->cvcache = newHV();
- thr->magicals = newAV();
+ thr->threadsv = newAV();
thr->specific = newAV();
thr->errhv = newHV();
thr->flags = THRf_R_JOINABLE;
diff --git a/perl.h b/perl.h
index 4cbc6775ed..724384f9e9 100644
--- a/perl.h
+++ b/perl.h
@@ -462,9 +462,13 @@ register struct op *op asm(stringify(OP_IN_REGISTER));
#ifdef USE_THREADS
# define ERRSV (thr->errsv)
# define ERRHV (thr->errhv)
+# define DEFSV *av_fetch(thr->threadsv, find_threadsv("_"), FALSE)
+# define SAVE_DEFSV save_threadsv(find_threadsv("_"))
#else
# define ERRSV GvSV(errgv)
# define ERRHV GvHV(errgv)
+# define DEFSV GvSV(defgv)
+# define SAVE_DEFSV SAVESPTR(GvSV(defgv))
#endif /* USE_THREADS */
#ifndef errno
@@ -1349,7 +1353,7 @@ int runops_standard _((void));
int runops_debug _((void));
#endif
-#define PER_THREAD_MAGICALS "123456789&`'+/.,\\\";^-%=|~:\001\005!@"
+#define THREADSV_NAMES "_123456789&`'+/.,\\\";^-%=|~:\001\005!@"
/****************/
/* Truly global */
@@ -1367,7 +1371,7 @@ EXT struct thread * eval_owner; /* Owner thread for doeval */
EXT int nthreads; /* Number of threads currently */
EXT perl_mutex threads_mutex; /* Mutex for nthreads and thread list */
EXT perl_cond nthreads_cond; /* Condition variable for nthreads */
-EXT char * per_thread_magicals INIT(PER_THREAD_MAGICALS);
+EXT char * threadsv_names INIT(THREADSV_NAMES);
#ifdef FAKE_THREADS
EXT struct thread * thr; /* Currently executing (fake) thread */
#endif
diff --git a/perly.c b/perly.c
index 7117566c20..9ae4211943 100644
--- a/perly.c
+++ b/perly.c
@@ -1767,7 +1767,7 @@ case 56:
{ char *name = SvPV(((SVOP*)yyvsp[0].opval)->op_sv, na);
if (strEQ(name, "BEGIN") || strEQ(name, "END")
|| strEQ(name, "INIT"))
- CvUNIQUE_on(compcv);
+ { CvUNIQUE_on(compcv); subline = -subline; }
yyval.opval = yyvsp[0].opval; }
break;
case 57:
diff --git a/perly.c.diff b/perly.c.diff
index b4aec9d598..e13b04bd8c 100644
--- a/perly.c.diff
+++ b/perly.c.diff
@@ -88,12 +88,24 @@ Index: perly.c
- short yyss[YYSTACKSIZE];
- YYSTYPE yyvs[YYSTACKSIZE];
- #define yystacksize YYSTACKSIZE
- #line 631 "perly.y"
+ #line 632 "perly.y"
/* PROGRAM */
--- 1283,1288 ----
***************
*** 1361,1372 ****
---- 1291,1347 ----
+ #define YYACCEPT goto yyaccept
+ #define YYERROR goto yyerrlab
+ int
+! yyparse()
+ {
+ register int yym, yyn, yystate;
+ #if YYDEBUG
+ register char *yys;
+ extern char *getenv();
+
+ if (yys = getenv("YYDEBUG"))
+ {
+--- 1291,1348 ----
#define YYACCEPT goto yyaccept
#define YYERROR goto yyerrlab
+
@@ -109,8 +121,7 @@ Index: perly.c
+ };
+
+ void
-+ yydestruct(ptr)
-+ void* ptr;
++ yydestruct(void *ptr)
+ {
+ struct ysv* ysave = (struct ysv*)ptr;
+ if (ysave->yyss) Safefree(ysave->yyss);
@@ -125,7 +136,7 @@ Index: perly.c
+ }
+
int
- yyparse()
+! yyparse(void)
{
register int yym, yyn, yystate;
+ register short *yyssp;
@@ -136,8 +147,10 @@ Index: perly.c
+ int retval = 0;
#if YYDEBUG
register char *yys;
++ #ifndef __cplusplus
extern char *getenv();
+ #endif
++ #endif
+
+ struct ysv *ysave = (struct ysv*)safemalloc(sizeof(struct ysv));
+ SAVEDESTRUCTOR(yydestruct, ysave);
@@ -153,7 +166,7 @@ Index: perly.c
{
***************
*** 1381,1384 ****
---- 1356,1367 ----
+--- 1357,1368 ----
yychar = (-1);
+ /*
@@ -173,7 +186,7 @@ Index: perly.c
! printf("yydebug: state %d, reading %d (%s)\n", yystate,
yychar, yys);
}
---- 1379,1383 ----
+--- 1380,1384 ----
if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
if (!yys) yys = "illegal-symbol";
! fprintf(stderr, "yydebug: state %d, reading %d (%s)\n", yystate,
@@ -191,7 +204,7 @@ Index: perly.c
! goto yyoverflow;
}
*++yyssp = yystate = yytable[yyn];
---- 1389,1412 ----
+--- 1390,1413 ----
#if YYDEBUG
if (yydebug)
! fprintf(stderr, "yydebug: state %d, shifting to state %d\n",
@@ -228,7 +241,7 @@ Index: perly.c
! goto yyoverflow;
}
*++yyssp = yystate = yytable[yyn];
---- 1444,1468 ----
+--- 1445,1469 ----
#if YYDEBUG
if (yydebug)
! fprintf(stderr,
@@ -262,7 +275,7 @@ Index: perly.c
! *yyssp);
#endif
if (yyssp <= yyss) goto yyabort;
---- 1474,1480 ----
+--- 1475,1481 ----
#if YYDEBUG
if (yydebug)
! fprintf(stderr,
@@ -278,7 +291,7 @@ Index: perly.c
! yystate, yychar, yys);
}
#endif
---- 1493,1499 ----
+--- 1494,1500 ----
if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
if (!yys) yys = "illegal-symbol";
! fprintf(stderr,
@@ -293,21 +306,21 @@ Index: perly.c
! printf("yydebug: state %d, reducing by rule %d (%s)\n",
yystate, yyn, yyrule[yyn]);
#endif
---- 1504,1508 ----
+--- 1505,1509 ----
#if YYDEBUG
if (yydebug)
! fprintf(stderr, "yydebug: state %d, reducing by rule %d (%s)\n",
yystate, yyn, yyrule[yyn]);
#endif
***************
-*** 2278,2283 ****
+*** 2279,2284 ****
#if YYDEBUG
if (yydebug)
! printf("yydebug: after reduction, shifting from state 0 to\
! state %d\n", YYFINAL);
#endif
yystate = YYFINAL;
---- 2292,2298 ----
+--- 2294,2300 ----
#if YYDEBUG
if (yydebug)
! fprintf(stderr,
@@ -316,20 +329,20 @@ Index: perly.c
#endif
yystate = YYFINAL;
***************
-*** 2293,2297 ****
+*** 2294,2298 ****
if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
if (!yys) yys = "illegal-symbol";
! printf("yydebug: state %d, reading %d (%s)\n",
YYFINAL, yychar, yys);
}
---- 2308,2312 ----
+--- 2310,2314 ----
if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
if (!yys) yys = "illegal-symbol";
! fprintf(stderr, "yydebug: state %d, reading %d (%s)\n",
YYFINAL, yychar, yys);
}
***************
-*** 2308,2317 ****
+*** 2309,2318 ****
#if YYDEBUG
if (yydebug)
! printf("yydebug: after reduction, shifting from state %d \
@@ -340,7 +353,7 @@ Index: perly.c
! goto yyoverflow;
}
*++yyssp = yystate;
---- 2323,2347 ----
+--- 2325,2349 ----
#if YYDEBUG
if (yydebug)
! fprintf(stderr,
@@ -367,7 +380,7 @@ Index: perly.c
}
*++yyssp = yystate;
***************
-*** 2319,2326 ****
+*** 2320,2327 ****
goto yyloop;
yyoverflow:
! yyerror("yacc stack overflow");
@@ -376,7 +389,7 @@ Index: perly.c
yyaccept:
! return (0);
}
---- 2349,2356 ----
+--- 2351,2358 ----
goto yyloop;
yyoverflow:
! yyerror("Out of memory for yacc stack");
diff --git a/perly.y b/perly.y
index 481a2ccad6..fa0e0f5f59 100644
--- a/perly.y
+++ b/perly.y
@@ -291,7 +291,7 @@ startformsub: /* NULL */ /* start a format subroutine scope */
subname : WORD { char *name = SvPV(((SVOP*)$1)->op_sv, na);
if (strEQ(name, "BEGIN") || strEQ(name, "END")
|| strEQ(name, "INIT"))
- CvUNIQUE_on(compcv);
+ { CvUNIQUE_on(compcv); subline = -subline; }
$$ = $1; }
;
diff --git a/pp.c b/pp.c
index 5ed3e989ce..8fbe61de71 100644
--- a/pp.c
+++ b/pp.c
@@ -590,7 +590,7 @@ PP(pp_trans)
if (op->op_flags & OPf_STACKED)
sv = POPs;
else {
- sv = GvSV(defgv);
+ sv = DEFSV;
EXTEND(SP,1);
}
TARG = sv_newmortal();
@@ -2714,7 +2714,7 @@ PP(pp_reverse)
if (SP - MARK > 1)
do_join(TARG, &sv_no, MARK, SP);
else
- sv_setsv(TARG, (SP > MARK) ? *SP : GvSV(defgv));
+ sv_setsv(TARG, (SP > MARK) ? *SP : DEFSV);
up = SvPV_force(TARG, len);
if (len > 1) {
down = SvPVX(TARG) + len - 1;
@@ -4310,14 +4310,11 @@ PP(pp_threadsv)
{
djSP;
#ifdef USE_THREADS
- SV **svp = av_fetch(thr->magicals, op->op_targ, FALSE);
- if (!svp)
- croak("panic: pp_threadsv");
EXTEND(sp, 1);
if (op->op_private & OPpLVAL_INTRO)
- PUSHs(save_svref(svp));
+ PUSHs(*save_threadsv(op->op_targ));
else
- PUSHs(*svp);
+ PUSHs(*av_fetch(thr->threadsv, op->op_targ, FALSE));
#else
DIE("tried to access per-thread data in non-threaded perl");
#endif /* USE_THREADS */
diff --git a/pp_ctl.c b/pp_ctl.c
index dadc145a22..48876909f9 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -546,14 +546,17 @@ PP(pp_grepstart)
ENTER; /* enter outer scope */
SAVETMPS;
- SAVESPTR(GvSV(defgv));
-
+#if 0
+ SAVE_DEFSV;
+#else
+ save_sptr(av_fetch(thr->threadsv, find_threadsv("_"), FALSE));
+#endif
ENTER; /* enter inner scope */
SAVESPTR(curpm);
src = stack_base[*markstack_ptr];
SvTEMP_off(src);
- GvSV(defgv) = src;
+ DEFSV = src;
PUTBACK;
if (op->op_type == OP_MAPSTART)
@@ -623,7 +626,7 @@ PP(pp_mapwhile)
src = stack_base[markstack_ptr[-1]];
SvTEMP_off(src);
- GvSV(defgv) = src;
+ DEFSV = src;
RETURNOP(cLOGOP->op_other);
}
@@ -1334,12 +1337,19 @@ PP(pp_enteriter)
ENTER;
SAVETMPS;
- if (op->op_targ)
- svp = &curpad[op->op_targ]; /* "my" variable */
+#ifdef USE_THREADS
+ if (op->op_flags & OPf_SPECIAL)
+ svp = save_threadsv(op->op_targ); /* per-thread variable */
else
+#endif /* USE_THREADS */
+ if (op->op_targ) {
+ svp = &curpad[op->op_targ]; /* "my" variable */
+ SAVESPTR(*svp);
+ }
+ else {
svp = &GvSV((GV*)POPs); /* symbol table variable */
-
- SAVESPTR(*svp);
+ SAVESPTR(*svp);
+ }
ENTER;
diff --git a/pp_hot.c b/pp_hot.c
index d05f57840a..46715aef9e 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -759,7 +759,7 @@ PP(pp_match)
if (op->op_flags & OPf_STACKED)
TARG = POPs;
else {
- TARG = GvSV(defgv);
+ TARG = DEFSV;
EXTEND(SP,1);
}
PUTBACK; /* EVAL blocks need stack_sp. */
@@ -1432,7 +1432,7 @@ PP(pp_subst)
if (op->op_flags & OPf_STACKED)
TARG = POPs;
else {
- TARG = GvSV(defgv);
+ TARG = DEFSV;
EXTEND(SP,1);
}
if (SvREADONLY(TARG)
@@ -1705,7 +1705,7 @@ PP(pp_grepwhile)
src = stack_base[*markstack_ptr];
SvTEMP_off(src);
- GvSV(defgv) = src;
+ DEFSV = src;
RETURNOP(cLOGOP->op_other);
}
diff --git a/proto.h b/proto.h
index 63545ffde0..35ef574f7b 100644
--- a/proto.h
+++ b/proto.h
@@ -136,7 +136,7 @@ void dump_sub _((GV* gv));
void fbm_compile _((SV* sv));
char* fbm_instr _((unsigned char* big, unsigned char* bigend, SV* littlesv));
#ifdef USE_THREADS
-PADOFFSET find_thread_magical _((char *name));
+PADOFFSET find_threadsv _((char *name));
#endif
OP* force_list _((OP* arg));
OP* fold_constants _((OP* arg));
@@ -443,6 +443,7 @@ SV* save_scalar _((GV* gv));
void save_pptr _((char** pptr));
void save_sptr _((SV** sptr));
SV* save_svref _((SV** sptr));
+SV** save_threadsv _((PADOFFSET i));
OP* sawparens _((OP* o));
OP* scalar _((OP* o));
OP* scalarkids _((OP* o));
diff --git a/scope.c b/scope.c
index cc5c9c88ce..43820724ab 100644
--- a/scope.c
+++ b/scope.c
@@ -330,6 +330,22 @@ save_sptr(SV **sptr)
SSPUSHINT(SAVEt_SPTR);
}
+SV **
+save_threadsv(PADOFFSET i)
+{
+#ifdef USE_THREADS
+ dTHR;
+ SV **svp = av_fetch(thr->threadsv, i, FALSE);
+ DEBUG_L(PerlIO_printf(PerlIO_stderr(), "save_threadsv %u: %p %p:%s\n",
+ i, svp, *svp, SvPEEK(*svp)));
+ save_svref(svp);
+ return svp;
+#else
+ croak("panic: save_threadsv called in non-threaded perl");
+ return 0;
+#endif /* USE_THREADS */
+}
+
void
save_nogv(GV *gv)
{
@@ -475,6 +491,9 @@ leave_scope(I32 base)
ptr = SSPOPPTR;
restore_sv:
sv = *(SV**)ptr;
+ DEBUG_L(PerlIO_printf(PerlIO_stderr(),
+ "restore svref: %p %p:%s -> %p:%s\n",
+ ptr, sv, SvPEEK(sv), value, SvPEEK(value)));
if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv) &&
SvTYPE(sv) != SVt_PVGV)
{
diff --git a/sv.h b/sv.h
index fcf92975f4..42a6a1bc95 100644
--- a/sv.h
+++ b/sv.h
@@ -492,8 +492,6 @@ struct xpvio {
#define SvTAINT(sv) STMT_START{ if(tainted){SvTAINTED_on(sv);} }STMT_END
-#ifdef CRIPPLED_CC
-
#define SvPV_force(sv, lp) sv_pvn_force(sv, &lp)
#define SvPV(sv, lp) sv_pvn(sv, &lp)
#define SvIVx(sv) sv_iv(sv)
@@ -508,7 +506,8 @@ struct xpvio {
#define SvUV(sv) SvIVx(sv)
#define SvTRUE(sv) SvTRUEx(sv)
-#else /* !CRIPPLED_CC */
+#ifndef CRIPPLED_CC
+/* redefine some things to more efficient inlined versions */
#undef SvIV
#define SvIV(sv) (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv))
@@ -528,15 +527,26 @@ struct xpvio {
((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \
? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_pvn_force(sv, &lp))
-#undef SvTRUE
-#define SvTRUE(sv) ( \
+#ifdef __GNUC__
+# undef SvIVx
+# undef SvUVx
+# undef SvNVx
+# undef SvPVx
+# undef SvTRUE
+# undef SvTRUEx
+# define SvIVx(sv) ({SV *nsv = (SV*)(sv); SvIV(nsv); })
+# define SvUVx(sv) ({SV *nsv = (SV*)(sv); SvUV(nsv); })
+# define SvNVx(sv) ({SV *nsv = (SV*)(sv); SvNV(nsv); })
+# define SvPVx(sv, lp) ({SV *nsv = (sv); SvPV(nsv, lp); })
+# define SvTRUE(sv) ( \
!sv \
? 0 \
: SvPOK(sv) \
- ? ((Xpv = (XPV*)SvANY(sv)) && \
- (*Xpv->xpv_pv > '0' || \
- Xpv->xpv_cur > 1 || \
- (Xpv->xpv_cur && *Xpv->xpv_pv != '0')) \
+ ? (({XPV *nxpv = (XPV*)SvANY(sv); \
+ nxpv && \
+ (*nxpv->xpv_pv > '0' || \
+ nxpv->xpv_cur > 1 || \
+ (nxpv->xpv_cur && *nxpv->xpv_pv != '0')); }) \
? 1 \
: 0) \
: \
@@ -545,22 +555,42 @@ struct xpvio {
: SvNOK(sv) \
? SvNVX(sv) != 0.0 \
: sv_2bool(sv) )
-
-#ifdef __GNUC__
-# define SvIVx(sv) ({SV *nsv = (SV*)(sv); SvIV(nsv); })
-# define SvUVx(sv) ({SV *nsv = (SV*)(sv); SvUV(nsv); })
-# define SvNVx(sv) ({SV *nsv = (SV*)(sv); SvNV(nsv); })
-# define SvPVx(sv, lp) ({SV *nsv = (sv); SvPV(nsv, lp); })
-#else
+# define SvTRUEx(sv) ({SV *nsv = (sv); SvTRUE(nsv); })
+#else /* __GNUC__ */
+#ifndef USE_THREADS
+/* These inlined macros use globals, which will require a thread
+ * declaration in user code, so we avoid them under threads */
+
+# undef SvIVx
+# undef SvUVx
+# undef SvNVx
+# undef SvPVx
+# undef SvTRUE
+# undef SvTRUEx
# define SvIVx(sv) ((Sv = (sv)), SvIV(Sv))
# define SvUVx(sv) ((Sv = (sv)), SvUV(Sv))
# define SvNVx(sv) ((Sv = (sv)), SvNV(Sv))
# define SvPVx(sv, lp) ((Sv = (sv)), SvPV(Sv, lp))
-#endif /* __GNUC__ */
-
-#define SvTRUEx(sv) ((Sv = (sv)), SvTRUE(Sv))
-
-#endif /* CRIPPLED_CC */
+# define SvTRUE(sv) ( \
+ !sv \
+ ? 0 \
+ : SvPOK(sv) \
+ ? ((Xpv = (XPV*)SvANY(sv)) && \
+ (*Xpv->xpv_pv > '0' || \
+ Xpv->xpv_cur > 1 || \
+ (Xpv->xpv_cur && *Xpv->xpv_pv != '0')) \
+ ? 1 \
+ : 0) \
+ : \
+ SvIOK(sv) \
+ ? SvIVX(sv) != 0 \
+ : SvNOK(sv) \
+ ? SvNVX(sv) != 0.0 \
+ : sv_2bool(sv) )
+# define SvTRUEx(sv) ((Sv = (sv)), SvTRUE(Sv))
+#endif /* !USE_THREADS */
+#endif /* !__GNU__ */
+#endif /* !CRIPPLED_CC */
#define newRV_inc(sv) newRV(sv)
#ifdef __GNUC__
diff --git a/t/lib/english.t b/t/lib/english.t
index 68a587091f..1a96c772fe 100755
--- a/t/lib/english.t
+++ b/t/lib/english.t
@@ -5,19 +5,23 @@ print "1..16\n";
BEGIN { @INC = '../lib' }
use English;
use Config;
-my $threads = $Config{'ccflags'} =~ /-DUSE_THREADS\b/;
+my $threads = $Config{archname} =~ /-thread$/;
print $PID == $$ ? "ok 1\n" : "not ok 1\n";
$_ = 1;
-print $ARG == $_ ? "ok 2\n" : "not ok 2\n";
+print $ARG == $_ || $threads ? "ok 2\n" : "not ok 2\n";
sub foo {
print $ARG[0] == $_[0] || $threads ? "ok 3\n" : "not ok 3\n";
}
&foo(1);
-$ARG = "ok 4\nok 5\nok 6\n";
+if ($threads) {
+ $_ = "ok 4\nok 5\nok 6\n";
+} else {
+ $ARG = "ok 4\nok 5\nok 6\n";
+}
/ok 5\n/;
print $PREMATCH, $MATCH, $POSTMATCH;
diff --git a/t/op/misc.t b/t/op/misc.t
index c529830123..326273aff1 100755
--- a/t/op/misc.t
+++ b/t/op/misc.t
@@ -345,3 +345,14 @@ EXPECT
Unmatched right bracket at (re_eval 1) line 1, at end of line
syntax error at (re_eval 1) line 1, near ""{"}"
Compilation failed in regexp at - line 1.
+########
+BEGIN { @ARGV = qw(a b c) }
+BEGIN { print "argv <@ARGV>\nbegin <",shift,">\n" }
+END { print "end <",shift,">\nargv <@ARGV>\n" }
+INIT { print "init <",shift,">\n" }
+EXPECT
+argv <a b c>
+begin <a>
+init <b>
+end <c>
+argv <>
diff --git a/thread.h b/thread.h
index 2b8e636966..79059db8fc 100644
--- a/thread.h
+++ b/thread.h
@@ -218,7 +218,7 @@ struct thread {
HV * cvcache;
perl_thread self; /* Underlying thread object */
U32 flags;
- AV * magicals; /* Per-thread magicals */
+ AV * threadsv; /* Per-thread SVs ($_, $@ etc.) */
AV * specific; /* Thread-specific user data */
SV * errsv; /* Backing SV for $@ */
HV * errhv; /* HV for what was %@ in pp_ctl.c */
diff --git a/toke.c b/toke.c
index f643732a7f..f10c39fada 100644
--- a/toke.c
+++ b/toke.c
@@ -1122,9 +1122,8 @@ filter_del(filter_t funcp)
if (!rsfp_filters || AvFILL(rsfp_filters)<0)
return;
/* if filter is on top of stack (usual case) just pop it off */
- if (IoDIRP(FILTER_DATA(0)) == (void*)funcp){
- /* sv_free(av_pop(rsfp_filters)); */
- sv_free(av_shift(rsfp_filters));
+ if (IoDIRP(FILTER_DATA(AvFILL(rsfp_filters))) == (void*)funcp){
+ sv_free(av_pop(rsfp_filters));
return;
}
@@ -1246,10 +1245,10 @@ yylex(void)
if (!strchr(tokenbuf,':')) {
#ifdef USE_THREADS
- /* Check for single character per-thread magicals */
+ /* Check for single character per-thread SVs */
if (tokenbuf[0] == '$' && tokenbuf[2] == '\0'
- && !isALPHA(tokenbuf[1]) /* Rule out obvious non-magicals */
- && (tmp = find_thread_magical(&tokenbuf[1])) != NOT_IN_PAD)
+ && !isALPHA(tokenbuf[1]) /* Rule out obvious non-threadsvs */
+ && (tmp = find_threadsv(&tokenbuf[1])) != NOT_IN_PAD)
{
yylval.opval = newOP(OP_THREADSV, 0);
yylval.opval->op_targ = tmp;
@@ -1393,7 +1392,7 @@ yylex(void)
force_next(',');
#ifdef USE_THREADS
nextval[nexttoke].opval = newOP(OP_THREADSV, 0);
- nextval[nexttoke].opval->op_targ = find_thread_magical("\"");
+ nextval[nexttoke].opval->op_targ = find_threadsv("\"");
force_next(PRIVATEREF);
#else
force_ident("\"", '$');
diff --git a/util.c b/util.c
index bc90b55e7a..e771cbc28d 100644
--- a/util.c
+++ b/util.c
@@ -2465,7 +2465,7 @@ new_struct_thread(struct thread *t)
curcop = &compiling;
thr->cvcache = newHV();
- thr->magicals = newAV();
+ thr->threadsv = newAV();
thr->specific = newAV();
thr->errsv = newSVpv("", 0);
thr->errhv = newHV();
@@ -2506,16 +2506,15 @@ new_struct_thread(struct thread *t)
bodytarget = newSVsv(t->Tbodytarget);
toptarget = newSVsv(t->Ttoptarget);
- /* Initialise all per-thread magicals that the template thread used */
- svp = AvARRAY(t->magicals);
- for (i = 0; i <= AvFILL(t->magicals); i++, svp++) {
+ /* Initialise all per-thread SVs that the template thread used */
+ svp = AvARRAY(t->threadsv);
+ for (i = 0; i <= AvFILL(t->threadsv); i++, svp++) {
if (*svp && *svp != &sv_undef) {
SV *sv = newSVsv(*svp);
- av_store(thr->magicals, i, sv);
- sv_magic(sv, 0, 0, &per_thread_magicals[i], 1);
+ av_store(thr->threadsv, i, sv);
+ sv_magic(sv, 0, 0, &threadsv_names[i], 1);
DEBUG_L(PerlIO_printf(PerlIO_stderr(),
- "new_struct_thread: copied magical %d %p->%p\n",i,
- t, thr));
+ "new_struct_thread: copied threadsv %d %p->%p\n",i, t, thr));
}
}
diff --git a/vms/perly_c.vms b/vms/perly_c.vms
index 1344fae31e..e3c100b45d 100644
--- a/vms/perly_c.vms
+++ b/vms/perly_c.vms
@@ -8,7 +8,7 @@ static char yysccsid[] = "@(#)yaccpar 1.8 (Berkeley) 01/20/91";
#include "perl.h"
static void
-dep()
+dep(void)
{
deprecate("\"do\" to call subroutines");
}
@@ -1304,8 +1304,7 @@ struct ysv {
};
void
-yydestruct(ptr)
-void* ptr;
+yydestruct(void *ptr)
{
struct ysv* ysave = (struct ysv*)ptr;
if (ysave->yyss) Safefree(ysave->yyss);
@@ -1320,7 +1319,7 @@ void* ptr;
}
int
-yyparse()
+yyparse(void)
{
register int yym, yyn, yystate;
register short *yyssp;
@@ -1331,10 +1330,12 @@ yyparse()
int retval = 0;
#if YYDEBUG
register char *yys;
+#ifndef __cplusplus
# ifndef getenv
extern char *getenv();
# endif
#endif
+#endif
struct ysv *ysave = (struct ysv*)safemalloc(sizeof(struct ysv));
SAVEDESTRUCTOR(yydestruct, ysave);
@@ -1769,7 +1770,7 @@ case 56:
{ char *name = SvPV(((SVOP*)yyvsp[0].opval)->op_sv, na);
if (strEQ(name, "BEGIN") || strEQ(name, "END")
|| strEQ(name, "INIT"))
- CvUNIQUE_on(compcv);
+ { CvUNIQUE_on(compcv); subline = -subline; }
yyval.opval = yyvsp[0].opval; }
break;
case 57:
diff --git a/win32/win32sck.c b/win32/win32sck.c
index b4f40f0de1..559691a350 100644
--- a/win32/win32sck.c
+++ b/win32/win32sck.c
@@ -9,6 +9,7 @@
*/
#define WIN32IO_IS_STDIO
+#define WIN32SCK_IS_STDSCK
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "EXTERN.h"
@@ -19,50 +20,6 @@
#include <assert.h>
#include <io.h>
-#undef htonl
-#undef htons
-#undef ntohl
-#undef ntohs
-#undef inet_addr
-#undef inet_ntoa
-#undef socket
-#undef bind
-#undef listen
-#undef accept
-#undef connect
-#undef send
-#undef sendto
-#undef recv
-#undef recvfrom
-#undef shutdown
-#undef closesocket
-#undef ioctlsocket
-#undef setsockopt
-#undef getsockopt
-#undef getpeername
-#undef getsockname
-#undef gethostname
-#undef gethostbyname
-#undef gethostbyaddr
-#undef getprotobyname
-#undef getprotobynumber
-#undef getservbyname
-#undef getservbyport
-#undef select
-#undef endhostent
-#undef endnetent
-#undef endprotoent
-#undef endservent
-#undef getnetent
-#undef getnetbyname
-#undef getnetbyaddr
-#undef getprotoent
-#undef getservent
-#undef sethostent
-#undef setnetent
-#undef setprotoent
-#undef setservent
-
/* thanks to Beverly Brown (beverly@datacube.com) */
#ifdef USE_SOCKETS_AS_HANDLES
# define OPEN_SOCKET(x) _open_osfhandle(x,O_RDWR|O_BINARY)
@@ -292,13 +249,15 @@ win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, i
/* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */
int
-win32_select(int nfds, int* rd, int* wr, int* ex, const struct timeval* timeout)
+win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout)
{
- long r;
- int dummy = 0;
+ int r;
+#ifdef USE_SOCKETS_AS_HANDLES
+ Perl_fd_set dummy;
int i, fd, bit, offset;
- FD_SET nrd, nwr, nex,*prd,*pwr,*pex;
+ FD_SET nrd, nwr, nex, *prd, *pwr, *pex;
+ PERL_FD_ZERO(&dummy);
if (!rd)
rd = &dummy, prd = NULL;
else
@@ -317,13 +276,11 @@ win32_select(int nfds, int* rd, int* wr, int* ex, const struct timeval* timeout)
FD_ZERO(&nex);
for (i = 0; i < nfds; i++) {
fd = TO_SOCKET(i);
- bit = 1L<<(i % (sizeof(int)*8));
- offset = i / (sizeof(int)*8);
- if (rd[offset] & bit)
+ if (PERL_FD_ISSET(i,rd))
FD_SET(fd, &nrd);
- if (wr[offset] & bit)
+ if (PERL_FD_ISSET(i,wr))
FD_SET(fd, &nwr);
- if (ex[offset] & bit)
+ if (PERL_FD_ISSET(i,ex))
FD_SET(fd, &nex);
}
@@ -331,21 +288,16 @@ win32_select(int nfds, int* rd, int* wr, int* ex, const struct timeval* timeout)
for (i = 0; i < nfds; i++) {
fd = TO_SOCKET(i);
- bit = 1L<<(i % (sizeof(int)*8));
- offset = i / (sizeof(int)*8);
- if (rd[offset] & bit) {
- if (!__WSAFDIsSet(fd, &nrd))
- rd[offset] &= ~bit;
- }
- if (wr[offset] & bit) {
- if (!__WSAFDIsSet(fd, &nwr))
- wr[offset] &= ~bit;
- }
- if (ex[offset] & bit) {
- if (!__WSAFDIsSet(fd, &nex))
- ex[offset] &= ~bit;
- }
+ if (PERL_FD_ISSET(i,rd) && !FD_ISSET(fd, &nrd))
+ PERL_FD_CLR(i,rd);
+ if (PERL_FD_ISSET(i,wr) && !FD_ISSET(fd, &nwr))
+ PERL_FD_CLR(i,wr);
+ if (PERL_FD_ISSET(i,ex) && !FD_ISSET(fd, &nex))
+ PERL_FD_CLR(i,ex);
}
+#else
+ SOCKET_TEST_ERROR(r = select(nfds, rd, wr, ex, timeout));
+#endif
return r;
}