From: Gurusamy Sarathy Date: Wed, 1 Dec 1999 01:00:09 +0000 (+0000) Subject: more complete pseudo-fork() support for Windows X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=7766f1371a6d2b58d0f46fbe6a60785860a39c1e;p=p5sagit%2Fp5-mst-13.2.git more complete pseudo-fork() support for Windows p4raw-id: //depot/perl@4602 --- diff --git a/MANIFEST b/MANIFEST index db6f5d6..483b3bb 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1065,6 +1065,7 @@ pod/perlfaq7.pod Frequently Asked Questions, Part 7 pod/perlfaq8.pod Frequently Asked Questions, Part 8 pod/perlfaq9.pod Frequently Asked Questions, Part 9 pod/perlfilter.pod Source filters info +pod/perlfork.pod Info about fork() pod/perlform.pod Format info pod/perlfunc.pod Function info pod/perlguts.pod Internals info @@ -1543,10 +1544,13 @@ win32/include/netdb.h Win32 port win32/include/sys/socket.h Win32 port win32/makefile.mk Win32 makefile for DMAKE (BC++, VC++ builds) win32/perlglob.c Win32 port +win32/perlhost.h Perl "host" implementation win32/perllib.c Win32 port win32/pod.mak Win32 port win32/runperl.c Win32 port win32/splittree.pl Win32 port +win32/vdir.h Perl "host" virtual directory manager +win32/vmem.h Perl "host" memory manager win32/win32.c Win32 port win32/win32.h Win32 port win32/win32iop.h Win32 port diff --git a/XSUB.h b/XSUB.h index 9eee838..e9b6dc3 100644 --- a/XSUB.h +++ b/XSUB.h @@ -238,6 +238,7 @@ # define setjmp PerlProc_setjmp # define longjmp PerlProc_longjmp # define signal PerlProc_signal +# define getpid PerlProc_getpid # define htonl PerlSock_htonl # define htons PerlSock_htons # define ntohl PerlSock_ntohl diff --git a/cop.h b/cop.h index 88627d6..ede2fce 100644 --- a/cop.h +++ b/cop.h @@ -96,19 +96,27 @@ struct block_sub { (void)SvREFCNT_inc(cx->blk_sub.dfoutgv) #ifdef USE_THREADS -#define POPSAVEARRAY() NOOP +# define POP_SAVEARRAY() NOOP #else -#define POPSAVEARRAY() \ +# define POP_SAVEARRAY() \ STMT_START { \ SvREFCNT_dec(GvAV(PL_defgv)); \ GvAV(PL_defgv) = cx->blk_sub.savearray; \ } STMT_END #endif /* USE_THREADS */ +#ifdef USE_ITHREADS + /* junk in @_ spells trouble when cloning CVs, so don't leave any */ +# define CLEAR_ARGARRAY() av_clear(cx->blk_sub.argarray) +#else +# define CLEAR_ARGARRAY() NOOP +#endif /* USE_ITHREADS */ + + #define POPSUB(cx,sv) \ STMT_START { \ if (cx->blk_sub.hasargs) { \ - POPSAVEARRAY(); \ + POP_SAVEARRAY(); \ /* abandon @_ if it got reified */ \ if (AvREAL(cx->blk_sub.argarray)) { \ SSize_t fill = AvFILLp(cx->blk_sub.argarray); \ @@ -118,6 +126,9 @@ struct block_sub { AvFLAGS(cx->blk_sub.argarray) = AVf_REIFY; \ PL_curpad[0] = (SV*)cx->blk_sub.argarray; \ } \ + else { \ + CLEAR_ARGARRAY(); \ + } \ } \ sv = (SV*)cx->blk_sub.cv; \ if (sv && (CvDEPTH((CV*)sv) = cx->blk_sub.olddepth)) \ @@ -146,14 +157,15 @@ struct block_eval { #define PUSHEVAL(cx,n,fgv) \ cx->blk_eval.old_in_eval = PL_in_eval; \ cx->blk_eval.old_op_type = PL_op->op_type; \ - cx->blk_eval.old_name = n; \ + cx->blk_eval.old_name = (n ? savepv(n) : Nullch); \ cx->blk_eval.old_eval_root = PL_eval_root; \ cx->blk_eval.cur_text = PL_linestr; #define POPEVAL(cx) \ PL_in_eval = cx->blk_eval.old_in_eval; \ optype = cx->blk_eval.old_op_type; \ - PL_eval_root = cx->blk_eval.old_eval_root; + PL_eval_root = cx->blk_eval.old_eval_root; \ + Safefree(cx->blk_eval.old_name); /* loop context */ struct block_loop { @@ -162,7 +174,11 @@ struct block_loop { OP * redo_op; OP * next_op; OP * last_op; +#ifdef USE_ITHREADS + void * iterdata; +#else SV ** itervar; +#endif SV * itersave; SV * iterlval; AV * iterary; @@ -170,23 +186,40 @@ struct block_loop { IV itermax; }; -#define PUSHLOOP(cx, ivar, s) \ +#ifdef USE_ITHREADS +# define CxITERVAR(c) \ + ((c)->blk_loop.iterdata \ + ? (CxPADLOOP(cx) \ + ? &PL_curpad[(PADOFFSET)(c)->blk_loop.iterdata] \ + : &GvSV((GV*)(c)->blk_loop.iterdata)) \ + : (SV**)NULL) +# define CX_ITERDATA_SET(cx,idata) \ + if (cx->blk_loop.iterdata = (idata)) \ + cx->blk_loop.itersave = SvREFCNT_inc(*CxITERVAR(cx)); +#else +# define CxITERVAR(c) ((c)->blk_loop.itervar) +# define CX_ITERDATA_SET(cx,ivar) \ + if (cx->blk_loop.itervar = (SV**)(ivar)) \ + cx->blk_loop.itersave = SvREFCNT_inc(*CxITERVAR(cx)); +#endif + +#define PUSHLOOP(cx, dat, s) \ cx->blk_loop.label = PL_curcop->cop_label; \ cx->blk_loop.resetsp = s - PL_stack_base; \ cx->blk_loop.redo_op = cLOOP->op_redoop; \ cx->blk_loop.next_op = cLOOP->op_nextop; \ cx->blk_loop.last_op = cLOOP->op_lastop; \ - if (cx->blk_loop.itervar = (ivar)) \ - cx->blk_loop.itersave = SvREFCNT_inc(*cx->blk_loop.itervar);\ cx->blk_loop.iterlval = Nullsv; \ cx->blk_loop.iterary = Nullav; \ - cx->blk_loop.iterix = -1; + cx->blk_loop.iterix = -1; \ + CX_ITERDATA_SET(cx,dat); #define POPLOOP(cx) \ SvREFCNT_dec(cx->blk_loop.iterlval); \ - if (cx->blk_loop.itervar) { \ - sv_2mortal(*(cx->blk_loop.itervar)); \ - *(cx->blk_loop.itervar) = cx->blk_loop.itersave; \ + if (CxITERVAR(cx)) { \ + SV **s_v_p = CxITERVAR(cx); \ + sv_2mortal(*s_v_p); \ + *s_v_p = cx->blk_loop.itersave; \ } \ if (cx->blk_loop.iterary && cx->blk_loop.iterary != PL_curstack)\ SvREFCNT_dec(cx->blk_loop.iterary); @@ -319,12 +352,23 @@ struct context { #define CXt_LOOP 3 #define CXt_SUBST 4 #define CXt_BLOCK 5 +#define CXt_FORMAT 6 /* private flags for CXt_EVAL */ #define CXp_REAL 0x00000100 /* truly eval'', not a lookalike */ +#ifdef USE_ITHREADS +/* private flags for CXt_LOOP */ +# define CXp_PADVAR 0x00000100 /* itervar lives on pad, iterdata + has pad offset; if not set, + iterdata holds GV* */ +# define CxPADLOOP(c) (((c)->cx_type & (CXt_LOOP|CXp_PADVAR)) \ + == (CXt_LOOP|CXp_PADVAR)) +#endif + #define CxTYPE(c) ((c)->cx_type & CXTYPEMASK) -#define CxREALEVAL(c) (((c)->cx_type & (CXt_EVAL|CXp_REAL)) == (CXt_EVAL|CXp_REAL)) +#define CxREALEVAL(c) (((c)->cx_type & (CXt_EVAL|CXp_REAL)) \ + == (CXt_EVAL|CXp_REAL)) #define CXINC (cxstack_ix < cxstack_max ? ++cxstack_ix : (cxstack_ix = cxinc())) diff --git a/dump.c b/dump.c index 38778d6..b8eaa54 100644 --- a/dump.c +++ b/dump.c @@ -531,6 +531,8 @@ Perl_do_op_dump(pTHX_ I32 level, PerlIO *file, OP *o) #endif break; case OP_CONST: + Perl_dump_indent(aTHX_ level, file, "SV = %s\n", SvPEEK(cSVOPo_sv)); + break; case OP_METHOD_NAMED: Perl_dump_indent(aTHX_ level, file, "SV = %s\n", SvPEEK(cSVOPo->op_sv)); break; diff --git a/embed.h b/embed.h index 55a8c88..758a0c2 100644 --- a/embed.h +++ b/embed.h @@ -45,8 +45,19 @@ #if !defined(PERL_OBJECT) #if !defined(PERL_IMPLICIT_CONTEXT) +#if defined(PERL_IMPLICIT_SYS) +#else +#endif +#if defined(USE_ITHREADS) +#endif +#if defined(MYMALLOC) +#define malloced_size Perl_malloced_size +#endif #if defined(PERL_OBJECT) #endif +#if defined(PERL_OBJECT) +#else +#endif #define amagic_call Perl_amagic_call #define Gv_AMupdate Perl_Gv_AMupdate #define append_elem Perl_append_elem @@ -355,9 +366,6 @@ #define magic_sizepack Perl_magic_sizepack #define magic_wipepack Perl_magic_wipepack #define magicname Perl_magicname -#if defined(MYMALLOC) -#define malloced_size Perl_malloced_size -#endif #define markstack_grow Perl_markstack_grow #if defined(USE_LOCALE_COLLATE) #define mem_collxfrm Perl_mem_collxfrm @@ -473,11 +481,10 @@ #define pad_swipe Perl_pad_swipe #define peep Perl_peep #if defined(PERL_OBJECT) -#else +#endif #if defined(USE_THREADS) #define new_struct_thread Perl_new_struct_thread #endif -#endif #define call_atexit Perl_call_atexit #define call_argv Perl_call_argv #define call_method Perl_call_method @@ -561,6 +568,7 @@ #define save_op Perl_save_op #define save_scalar Perl_save_scalar #define save_pptr Perl_save_pptr +#define save_vptr Perl_save_vptr #define save_re_context Perl_save_re_context #define save_sptr Perl_save_sptr #define save_svref Perl_save_svref @@ -767,6 +775,7 @@ #define cx_dup Perl_cx_dup #define si_dup Perl_si_dup #define ss_dup Perl_ss_dup +#define any_dup Perl_any_dup #define he_dup Perl_he_dup #define re_dup Perl_re_dup #define fp_dup Perl_fp_dup @@ -783,6 +792,7 @@ #define ptr_table_split Perl_ptr_table_split #endif #if defined(PERL_OBJECT) +#else #endif #if defined(PERL_IN_AV_C) || defined(PERL_DECL_PROT) #define avhv_index_sv S_avhv_index_sv @@ -1058,6 +1068,8 @@ #define xstat S_xstat # endif #endif +#if defined(PERL_OBJECT) +#endif #define ck_anoncode Perl_ck_anoncode #define ck_bitop Perl_ck_bitop #define ck_concat Perl_ck_concat @@ -1444,7 +1456,18 @@ #else /* PERL_IMPLICIT_CONTEXT */ +#if defined(PERL_IMPLICIT_SYS) +#else +#endif +#if defined(USE_ITHREADS) +#endif +#if defined(MYMALLOC) +#define malloced_size Perl_malloced_size +#endif +#if defined(PERL_OBJECT) +#endif #if defined(PERL_OBJECT) +#else #endif #define amagic_call(a,b,c,d) Perl_amagic_call(aTHX_ a,b,c,d) #define Gv_AMupdate(a) Perl_Gv_AMupdate(aTHX_ a) @@ -1737,9 +1760,6 @@ #define magic_sizepack(a,b) Perl_magic_sizepack(aTHX_ a,b) #define magic_wipepack(a,b) Perl_magic_wipepack(aTHX_ a,b) #define magicname(a,b,c) Perl_magicname(aTHX_ a,b,c) -#if defined(MYMALLOC) -#define malloced_size Perl_malloced_size -#endif #define markstack_grow() Perl_markstack_grow(aTHX) #if defined(USE_LOCALE_COLLATE) #define mem_collxfrm(a,b,c) Perl_mem_collxfrm(aTHX_ a,b,c) @@ -1853,11 +1873,10 @@ #define pad_swipe(a) Perl_pad_swipe(aTHX_ a) #define peep(a) Perl_peep(aTHX_ a) #if defined(PERL_OBJECT) -#else +#endif #if defined(USE_THREADS) #define new_struct_thread(a) Perl_new_struct_thread(aTHX_ a) #endif -#endif #define call_atexit(a,b) Perl_call_atexit(aTHX_ a,b) #define call_argv(a,b,c) Perl_call_argv(aTHX_ a,b,c) #define call_method(a,b) Perl_call_method(aTHX_ a,b) @@ -1941,6 +1960,7 @@ #define save_op() Perl_save_op(aTHX) #define save_scalar(a) Perl_save_scalar(aTHX_ a) #define save_pptr(a) Perl_save_pptr(aTHX_ a) +#define save_vptr(a) Perl_save_vptr(aTHX_ a) #define save_re_context() Perl_save_re_context(aTHX) #define save_sptr(a) Perl_save_sptr(aTHX_ a) #define save_svref(a) Perl_save_svref(aTHX_ a) @@ -2138,7 +2158,8 @@ #if defined(USE_ITHREADS) #define cx_dup(a,b,c) Perl_cx_dup(aTHX_ a,b,c) #define si_dup(a) Perl_si_dup(aTHX_ a) -#define ss_dup(a,b,c) Perl_ss_dup(aTHX_ a,b,c) +#define ss_dup(a) Perl_ss_dup(aTHX_ a) +#define any_dup(a,b) Perl_any_dup(aTHX_ a,b) #define he_dup(a,b) Perl_he_dup(aTHX_ a,b) #define re_dup(a) Perl_re_dup(aTHX_ a) #define fp_dup(a,b) Perl_fp_dup(aTHX_ a,b) @@ -2155,6 +2176,7 @@ #define ptr_table_split(a) Perl_ptr_table_split(aTHX_ a) #endif #if defined(PERL_OBJECT) +#else #endif #if defined(PERL_IN_AV_C) || defined(PERL_DECL_PROT) #define avhv_index_sv(a) S_avhv_index_sv(aTHX_ a) @@ -2429,6 +2451,8 @@ #define xstat(a) S_xstat(aTHX_ a) # endif #endif +#if defined(PERL_OBJECT) +#endif #define ck_anoncode(a) Perl_ck_anoncode(aTHX_ a) #define ck_bitop(a) Perl_ck_bitop(aTHX_ a) #define ck_concat(a) Perl_ck_concat(aTHX_ a) @@ -2816,8 +2840,23 @@ #endif /* PERL_IMPLICIT_CONTEXT */ #else /* PERL_OBJECT */ +#if defined(PERL_IMPLICIT_SYS) +#else +#endif +#if defined(USE_ITHREADS) +#endif +#if defined(MYMALLOC) +#define malloc Perl_malloc +#define calloc Perl_calloc +#define realloc Perl_realloc +#define mfree Perl_mfree +#define malloced_size Perl_malloced_size +#endif #if defined(PERL_OBJECT) #endif +#if defined(PERL_OBJECT) +#else +#endif #define Perl_amagic_call CPerlObj::Perl_amagic_call #define amagic_call Perl_amagic_call #define Perl_Gv_AMupdate CPerlObj::Perl_Gv_AMupdate @@ -3414,10 +3453,6 @@ #define magic_wipepack Perl_magic_wipepack #define Perl_magicname CPerlObj::Perl_magicname #define magicname Perl_magicname -#if defined(MYMALLOC) -#define Perl_malloced_size CPerlObj::Perl_malloced_size -#define malloced_size Perl_malloced_size -#endif #define Perl_markstack_grow CPerlObj::Perl_markstack_grow #define markstack_grow Perl_markstack_grow #if defined(USE_LOCALE_COLLATE) @@ -3633,23 +3668,16 @@ #define Perl_peep CPerlObj::Perl_peep #define peep Perl_peep #if defined(PERL_OBJECT) -#define perl_construct CPerlObj::perl_construct -#define perl_destruct CPerlObj::perl_destruct -#define perl_free CPerlObj::perl_free -#define perl_run CPerlObj::perl_run -#define perl_parse CPerlObj::perl_parse -#else -#define perl_alloc CPerlObj::perl_alloc -#define perl_construct CPerlObj::perl_construct -#define perl_destruct CPerlObj::perl_destruct -#define perl_free CPerlObj::perl_free -#define perl_run CPerlObj::perl_run -#define perl_parse CPerlObj::perl_parse +#define Perl_construct CPerlObj::Perl_construct +#define Perl_destruct CPerlObj::Perl_destruct +#define Perl_free CPerlObj::Perl_free +#define Perl_run CPerlObj::Perl_run +#define Perl_parse CPerlObj::Perl_parse +#endif #if defined(USE_THREADS) #define Perl_new_struct_thread CPerlObj::Perl_new_struct_thread #define new_struct_thread Perl_new_struct_thread #endif -#endif #define Perl_call_atexit CPerlObj::Perl_call_atexit #define call_atexit Perl_call_atexit #define Perl_call_argv CPerlObj::Perl_call_argv @@ -3814,6 +3842,8 @@ #define save_scalar Perl_save_scalar #define Perl_save_pptr CPerlObj::Perl_save_pptr #define save_pptr Perl_save_pptr +#define Perl_save_vptr CPerlObj::Perl_save_vptr +#define save_vptr Perl_save_vptr #define Perl_save_re_context CPerlObj::Perl_save_re_context #define save_re_context Perl_save_re_context #define Perl_save_sptr CPerlObj::Perl_save_sptr @@ -4092,14 +4122,6 @@ #if defined(MYMALLOC) #define Perl_dump_mstats CPerlObj::Perl_dump_mstats #define dump_mstats Perl_dump_mstats -#define Perl_malloc CPerlObj::Perl_malloc -#define malloc Perl_malloc -#define Perl_calloc CPerlObj::Perl_calloc -#define calloc Perl_calloc -#define Perl_realloc CPerlObj::Perl_realloc -#define realloc Perl_realloc -#define Perl_mfree CPerlObj::Perl_mfree -#define mfree Perl_mfree #endif #define Perl_safesysmalloc CPerlObj::Perl_safesysmalloc #define safesysmalloc Perl_safesysmalloc @@ -4216,6 +4238,8 @@ #define si_dup Perl_si_dup #define Perl_ss_dup CPerlObj::Perl_ss_dup #define ss_dup Perl_ss_dup +#define Perl_any_dup CPerlObj::Perl_any_dup +#define any_dup Perl_any_dup #define Perl_he_dup CPerlObj::Perl_he_dup #define he_dup Perl_he_dup #define Perl_re_dup CPerlObj::Perl_re_dup @@ -4242,10 +4266,9 @@ #define ptr_table_store Perl_ptr_table_store #define Perl_ptr_table_split CPerlObj::Perl_ptr_table_split #define ptr_table_split Perl_ptr_table_split -#define perl_clone CPerlObj::perl_clone -#define perl_clone_using CPerlObj::perl_clone_using #endif #if defined(PERL_OBJECT) +#else #endif #if defined(PERL_IN_AV_C) || defined(PERL_DECL_PROT) #define S_avhv_index_sv CPerlObj::S_avhv_index_sv @@ -4738,6 +4761,8 @@ #define xstat S_xstat # endif #endif +#if defined(PERL_OBJECT) +#endif #define Perl_ck_anoncode CPerlObj::Perl_ck_anoncode #define ck_anoncode Perl_ck_anoncode #define Perl_ck_bitop CPerlObj::Perl_ck_bitop diff --git a/embed.pl b/embed.pl index fff791e..b21f21f 100755 --- a/embed.pl +++ b/embed.pl @@ -31,6 +31,7 @@ sub walk_table (&@) { seek DATA, $END, 0; # so we may restart while () { chomp; + next if /^:/; while (s|\\$||) { $_ .= ; chomp; @@ -106,8 +107,7 @@ sub write_protos { my $ret = ""; if (@_ == 1) { my $arg = shift; - $ret .= "$arg\n" if $arg =~ /^#\s*(if|ifdef|else|endif)\b/ - or $arg =~ /^\s*(public|protected|private):/; + $ret .= "$arg\n"; } else { my ($flags,$retval,$func,@args) = @_; @@ -144,7 +144,7 @@ sub write_global_sym { my $ret = ""; if (@_ > 1) { my ($flags,$retval,$func,@args) = @_; - unless ($flags =~ /s/) { + unless ($flags =~ /[sx]/) { $func = "Perl_$func" if $flags =~ /p/; $ret = "$func\n"; } @@ -422,15 +422,15 @@ walk_table { else { my ($flags,$retval,$func,@args) = @_; if ($flags =~ /s/) { - $ret .= hide("S_$func","CPerlObj::S_$func"); + $ret .= hide("S_$func","CPerlObj::S_$func") if $flags !~ /j/; $ret .= hide($func,"S_$func"); } elsif ($flags =~ /p/) { - $ret .= hide("Perl_$func","CPerlObj::Perl_$func"); + $ret .= hide("Perl_$func","CPerlObj::Perl_$func") if $flags !~ /j/; $ret .= hide($func,"Perl_$func"); } else { - $ret .= hide($func,"CPerlObj::$func"); + $ret .= hide($func,"CPerlObj::$func") if $flags !~ /j/; } } $ret; @@ -597,7 +597,26 @@ print EM <<'END'; # endif /* USE_THREADS */ #else /* !MULTIPLICITY */ -/* cases 1, 4 and 6 above */ + +# if defined(PERL_OBJECT) +/* case 6 above */ + +END + +for $sym (sort keys %thread) { + print EM multon($sym,'T','aTHXo->interp.'); +} + + +for $sym (sort keys %intrp) { + print EM multon($sym,'I','aTHXo->interp.'); +} + +print EM <<'END'; + +# else /* !PERL_OBJECT */ + +/* cases 1 and 4 above */ END @@ -607,7 +626,7 @@ for $sym (sort keys %intrp) { print EM <<'END'; -# if defined(USE_THREADS) +# if defined(USE_THREADS) /* case 4 above */ END @@ -618,8 +637,8 @@ for $sym (sort keys %thread) { print EM <<'END'; -# else /* !USE_THREADS */ -/* cases 1 and 6 above */ +# else /* !USE_THREADS */ +/* case 1 above */ END @@ -629,7 +648,8 @@ for $sym (sort keys %thread) { print EM <<'END'; -# endif /* USE_THREADS */ +# endif /* USE_THREADS */ +# endif /* PERL_OBJECT */ #endif /* MULTIPLICITY */ #if defined(PERL_GLOBAL_STRUCT) @@ -716,7 +736,7 @@ walk_table { } else { my ($flags,$retval,$func,@args) = @_; - unless ($flags =~ /s/) { + unless ($flags =~ /[js]/) { if ($flags =~ /p/) { $ret .= undefine("Perl_$func") . hide("Perl_$func","pPerl->Perl_$func"); $ret .= undefine($func) . hide($func,"Perl_$func"); @@ -813,9 +833,9 @@ START_EXTERN_C #undef PERLVARI #undef PERLVARIC #define PERLVAR(v,t) t* Perl_##v##_ptr(pTHXo) \ - { return &(aTHXo->PL_##v); } + { return &(aTHXo->interp.v); } #define PERLVARA(v,n,t) PL_##v##_t* Perl_##v##_ptr(pTHXo) \ - { return &(aTHXo->PL_##v); } + { return &(aTHXo->interp.v); } #define PERLVARI(v,t,i) PERLVAR(v,t) #define PERLVARIC(v,t,i) PERLVAR(v, const t) @@ -928,7 +948,7 @@ walk_table { else { my ($flags,$retval,$func,@args) = @_; return $ret if exists $skipapi_funcs{$func}; - unless ($flags =~ /s/) { + unless ($flags =~ /[js]/) { $ret .= "\n"; my $addctx = 1 if $flags =~ /n/; if ($flags =~ /p/) { @@ -965,7 +985,7 @@ Perl_fprintf_nocontext(PerlIO *stream, const char *format, ...) dTHXo; va_list(arglist); va_start(arglist, format); - return (*pPerl->PL_StdIO->pVprintf)(pPerl->PL_StdIO, stream, format, arglist); + return (*PL_StdIO->pVprintf)(PL_StdIO, stream, format, arglist); } END_EXTERN_C @@ -975,33 +995,86 @@ EOT __END__ -# Lines are of the form: -# flags|return_type|function_name|arg1|arg2|...|argN -# -# A line may be continued on another by ending it with a backslash. -# Leading and trailing whitespace will be ignored in each component. -# -# flags are single letters with following meanings: -# s static function, should have an S_ prefix in source -# file -# n has no implicit interpreter/thread context argument -# p function has a Perl_ prefix -# r function never returns -# o has no compatibility macro (#define foo Perl_foo) -# -# Individual flags may be separated by whitespace. -# -# New global functions should be added at the end for binary compatibility -# in some configurations. -# -# TODO: 1) Add a flag to mark the functions that are part of the public API. -# 2) Add a field for documentation, so that L -# may be autogenerated. -# +: Lines are of the form: +: flags|return_type|function_name|arg1|arg2|...|argN +: +: A line may be continued on another by ending it with a backslash. +: Leading and trailing whitespace will be ignored in each component. +: +: flags are single letters with following meanings: +: s static function, should have an S_ prefix in source +: file +: n has no implicit interpreter/thread context argument +: p function has a Perl_ prefix +: r function never returns +: o has no compatibility macro (#define foo Perl_foo) +: j not a member of CPerlObj +: x not exported +: +: Individual flags may be separated by whitespace. +: +: New global functions should be added at the end for binary compatibility +: in some configurations. +: +: TODO: 1) Add a flag to mark the functions that are part of the public API. +: 2) Add a field for documentation, so that L +: may be autogenerated. +START_EXTERN_C + +#if defined(PERL_IMPLICIT_SYS) +jno |PerlInterpreter* |perl_alloc_using \ + |struct IPerlMem* m|struct IPerlMem* ms \ + |struct IPerlMem* mp|struct IPerlEnv* e \ + |struct IPerlStdIO* io|struct IPerlLIO* lio \ + |struct IPerlDir* d|struct IPerlSock* s \ + |struct IPerlProc* p +#else +jno |PerlInterpreter* |perl_alloc +#endif +jno |void |perl_construct |PerlInterpreter* interp +jno |void |perl_destruct |PerlInterpreter* interp +jno |void |perl_free |PerlInterpreter* interp +jno |int |perl_run |PerlInterpreter* interp +jno |int |perl_parse |PerlInterpreter* interp|XSINIT_t xsinit \ + |int argc|char** argv|char** env +#if defined(USE_ITHREADS) +jno |PerlInterpreter*|perl_clone|PerlInterpreter* interp, UV flags +jno |PerlInterpreter*|perl_clone_using|PerlInterpreter *interp|UV flags \ + |struct IPerlMem* m|struct IPerlMem* ms \ + |struct IPerlMem* mp|struct IPerlEnv* e \ + |struct IPerlStdIO* io|struct IPerlLIO* lio \ + |struct IPerlDir* d|struct IPerlSock* s \ + |struct IPerlProc* p +#endif + +#if defined(MYMALLOC) +jnop |Malloc_t|malloc |MEM_SIZE nbytes +jnop |Malloc_t|calloc |MEM_SIZE elements|MEM_SIZE size +jnop |Malloc_t|realloc |Malloc_t where|MEM_SIZE nbytes +jnop |Free_t |mfree |Malloc_t where +jnp |MEM_SIZE|malloced_size |void *p +#endif + +END_EXTERN_C + +/* functions with flag 'n' should come before here */ +#if defined(PERL_OBJECT) +class CPerlObj { +public: + struct interpreter interp; + CPerlObj(IPerlMem*, IPerlMem*, IPerlMem*, IPerlEnv*, IPerlStdIO*, + IPerlLIO*, IPerlDir*, IPerlSock*, IPerlProc*); + void* operator new(size_t nSize, IPerlMem *pvtbl); + static void operator delete(void* pPerl, IPerlMem *pvtbl); + int do_aspawn (void *vreally, void **vmark, void **vsp); +#endif #if defined(PERL_OBJECT) public: +#else +START_EXTERN_C #endif +# include "pp_proto.h" p |SV* |amagic_call |SV* left|SV* right|int method|int dir p |bool |Gv_AMupdate |HV* stash p |OP* |append_elem |I32 optype|OP* head|OP* tail @@ -1047,7 +1120,7 @@ p |OP* |convert |I32 optype|I32 flags|OP* o pr |void |croak |const char* pat|... pr |void |vcroak |const char* pat|va_list* args #if defined(PERL_IMPLICIT_CONTEXT) -npr |void |croak_nocontext|const char* pat|... +nrp |void |croak_nocontext|const char* pat|... np |OP* |die_nocontext |const char* pat|... np |void |deb_nocontext |const char* pat|... np |char* |form_nocontext |const char* pat|... @@ -1321,9 +1394,6 @@ p |int |magic_set_all_env|SV* sv|MAGIC* mg p |U32 |magic_sizepack |SV* sv|MAGIC* mg p |int |magic_wipepack |SV* sv|MAGIC* mg p |void |magicname |char* sym|char* name|I32 namlen -#if defined(MYMALLOC) -np |MEM_SIZE|malloced_size |void *p -#endif p |void |markstack_grow #if defined(USE_LOCALE_COLLATE) p |char* |mem_collxfrm |const char* s|STRLEN len|STRLEN* xlen @@ -1443,24 +1513,16 @@ p |void |pad_reset p |void |pad_swipe |PADOFFSET po p |void |peep |OP* o #if defined(PERL_OBJECT) -no |void |perl_construct -no |void |perl_destruct -no |void |perl_free -no |int |perl_run -no |int |perl_parse |XSINIT_t xsinit \ - |int argc|char** argv|char** env -#else -no |PerlInterpreter* |perl_alloc -no |void |perl_construct |PerlInterpreter* interp -no |void |perl_destruct |PerlInterpreter* interp -no |void |perl_free |PerlInterpreter* interp -no |int |perl_run |PerlInterpreter* interp -no |int |perl_parse |PerlInterpreter* interp|XSINIT_t xsinit \ +ox |void |Perl_construct +ox |void |Perl_destruct +ox |void |Perl_free +ox |int |Perl_run +ox |int |Perl_parse |XSINIT_t xsinit \ |int argc|char** argv|char** env +#endif #if defined(USE_THREADS) p |struct perl_thread* |new_struct_thread|struct perl_thread *t #endif -#endif p |void |call_atexit |ATEXIT_t fn|void *ptr p |I32 |call_argv |const char* sub_name|I32 flags|char** argv p |I32 |call_method |const char* methname|I32 flags @@ -1551,6 +1613,7 @@ p |void |save_nogv |GV* gv p |void |save_op p |SV* |save_scalar |GV* gv p |void |save_pptr |char** pptr +p |void |save_vptr |void* pptr p |void |save_re_context p |void |save_sptr |SV** sptr p |SV* |save_svref |SV** sptr @@ -1705,20 +1768,16 @@ p |int |yyparse p |int |yywarn |char* s #if defined(MYMALLOC) p |void |dump_mstats |char* s -pno |Malloc_t|malloc |MEM_SIZE nbytes -pno |Malloc_t|calloc |MEM_SIZE elements|MEM_SIZE size -pno |Malloc_t|realloc |Malloc_t where|MEM_SIZE nbytes -pno |Free_t |mfree |Malloc_t where #endif -pn |Malloc_t|safesysmalloc |MEM_SIZE nbytes -pn |Malloc_t|safesyscalloc |MEM_SIZE elements|MEM_SIZE size -pn |Malloc_t|safesysrealloc|Malloc_t where|MEM_SIZE nbytes -pn |Free_t |safesysfree |Malloc_t where +np |Malloc_t|safesysmalloc |MEM_SIZE nbytes +np |Malloc_t|safesyscalloc |MEM_SIZE elements|MEM_SIZE size +np |Malloc_t|safesysrealloc|Malloc_t where|MEM_SIZE nbytes +np |Free_t |safesysfree |Malloc_t where #if defined(LEAKTEST) -pn |Malloc_t|safexmalloc |I32 x|MEM_SIZE size -pn |Malloc_t|safexcalloc |I32 x|MEM_SIZE elements|MEM_SIZE size -pn |Malloc_t|safexrealloc |Malloc_t where|MEM_SIZE size -pn |void |safexfree |Malloc_t where +np |Malloc_t|safexmalloc |I32 x|MEM_SIZE size +np |Malloc_t|safexcalloc |I32 x|MEM_SIZE elements|MEM_SIZE size +np |Malloc_t|safexrealloc |Malloc_t where|MEM_SIZE size +np |void |safexfree |Malloc_t where #endif #if defined(PERL_GLOBAL_STRUCT) p |struct perl_vars *|GetVars @@ -1775,7 +1834,8 @@ p |void |boot_core_xsutils #if defined(USE_ITHREADS) p |PERL_CONTEXT*|cx_dup |PERL_CONTEXT* cx|I32 ix|I32 max p |PERL_SI*|si_dup |PERL_SI* si -p |ANY* |ss_dup |ANY* ss|I32 ix|I32 max +p |ANY* |ss_dup |PerlInterpreter* proto_perl +p |void* |any_dup |void* v|PerlInterpreter* proto_perl p |HE* |he_dup |HE* e|bool shared p |REGEXP*|re_dup |REGEXP* r p |PerlIO*|fp_dup |PerlIO* fp|char type @@ -1791,17 +1851,14 @@ p |PTR_TBL_t*|ptr_table_new p |void* |ptr_table_fetch|PTR_TBL_t *tbl|void *sv p |void |ptr_table_store|PTR_TBL_t *tbl|void *oldsv|void *newsv p |void |ptr_table_split|PTR_TBL_t *tbl -no |PerlInterpreter*|perl_clone|PerlInterpreter* interp, UV flags -no |PerlInterpreter*|perl_clone_using|PerlInterpreter *interp|UV flags \ - |struct IPerlMem* m|struct IPerlEnv* e \ - |struct IPerlStdIO* io|struct IPerlLIO* lio \ - |struct IPerlDir* d|struct IPerlSock* s \ - |struct IPerlProc* p #endif #if defined(PERL_OBJECT) protected: +#else +END_EXTERN_C #endif + #if defined(PERL_IN_AV_C) || defined(PERL_DECL_PROT) s |I32 |avhv_index_sv |SV* sv #endif @@ -2103,3 +2160,7 @@ s |SV* |mess_alloc s |void |xstat |int # endif #endif + +#if defined(PERL_OBJECT) +}; +#endif diff --git a/embedvar.h b/embedvar.h index 610f266..2ceb49e 100644 --- a/embedvar.h +++ b/embedvar.h @@ -184,6 +184,8 @@ #define PL_Env (PERL_GET_INTERP->IEnv) #define PL_LIO (PERL_GET_INTERP->ILIO) #define PL_Mem (PERL_GET_INTERP->IMem) +#define PL_MemParse (PERL_GET_INTERP->IMemParse) +#define PL_MemShared (PERL_GET_INTERP->IMemShared) #define PL_Proc (PERL_GET_INTERP->IProc) #define PL_Sock (PERL_GET_INTERP->ISock) #define PL_StdIO (PERL_GET_INTERP->IStdIO) @@ -350,6 +352,8 @@ #define PL_preambled (PERL_GET_INTERP->Ipreambled) #define PL_preprocess (PERL_GET_INTERP->Ipreprocess) #define PL_profiledata (PERL_GET_INTERP->Iprofiledata) +#define PL_psig_name (PERL_GET_INTERP->Ipsig_name) +#define PL_psig_ptr (PERL_GET_INTERP->Ipsig_ptr) #define PL_ptr_table (PERL_GET_INTERP->Iptr_table) #define PL_replgv (PERL_GET_INTERP->Ireplgv) #define PL_rsfp (PERL_GET_INTERP->Irsfp) @@ -445,6 +449,8 @@ #define PL_Env (vTHX->IEnv) #define PL_LIO (vTHX->ILIO) #define PL_Mem (vTHX->IMem) +#define PL_MemParse (vTHX->IMemParse) +#define PL_MemShared (vTHX->IMemShared) #define PL_Proc (vTHX->IProc) #define PL_Sock (vTHX->ISock) #define PL_StdIO (vTHX->IStdIO) @@ -611,6 +617,8 @@ #define PL_preambled (vTHX->Ipreambled) #define PL_preprocess (vTHX->Ipreprocess) #define PL_profiledata (vTHX->Iprofiledata) +#define PL_psig_name (vTHX->Ipsig_name) +#define PL_psig_ptr (vTHX->Ipsig_ptr) #define PL_ptr_table (vTHX->Iptr_table) #define PL_replgv (vTHX->Ireplgv) #define PL_rsfp (vTHX->Irsfp) @@ -693,7 +701,408 @@ # endif /* USE_THREADS */ #else /* !MULTIPLICITY */ -/* cases 1, 4 and 6 above */ + +# if defined(PERL_OBJECT) +/* case 6 above */ + +#define PL_Sv (aTHXo->interp.TSv) +#define PL_Xpv (aTHXo->interp.TXpv) +#define PL_av_fetch_sv (aTHXo->interp.Tav_fetch_sv) +#define PL_bodytarget (aTHXo->interp.Tbodytarget) +#define PL_bostr (aTHXo->interp.Tbostr) +#define PL_chopset (aTHXo->interp.Tchopset) +#define PL_colors (aTHXo->interp.Tcolors) +#define PL_colorset (aTHXo->interp.Tcolorset) +#define PL_curcop (aTHXo->interp.Tcurcop) +#define PL_curpad (aTHXo->interp.Tcurpad) +#define PL_curpm (aTHXo->interp.Tcurpm) +#define PL_curstack (aTHXo->interp.Tcurstack) +#define PL_curstackinfo (aTHXo->interp.Tcurstackinfo) +#define PL_curstash (aTHXo->interp.Tcurstash) +#define PL_defoutgv (aTHXo->interp.Tdefoutgv) +#define PL_defstash (aTHXo->interp.Tdefstash) +#define PL_delaymagic (aTHXo->interp.Tdelaymagic) +#define PL_dirty (aTHXo->interp.Tdirty) +#define PL_dumpindent (aTHXo->interp.Tdumpindent) +#define PL_efloatbuf (aTHXo->interp.Tefloatbuf) +#define PL_efloatsize (aTHXo->interp.Tefloatsize) +#define PL_errors (aTHXo->interp.Terrors) +#define PL_extralen (aTHXo->interp.Textralen) +#define PL_firstgv (aTHXo->interp.Tfirstgv) +#define PL_formtarget (aTHXo->interp.Tformtarget) +#define PL_hv_fetch_ent_mh (aTHXo->interp.Thv_fetch_ent_mh) +#define PL_hv_fetch_sv (aTHXo->interp.Thv_fetch_sv) +#define PL_in_eval (aTHXo->interp.Tin_eval) +#define PL_last_in_gv (aTHXo->interp.Tlast_in_gv) +#define PL_lastgotoprobe (aTHXo->interp.Tlastgotoprobe) +#define PL_lastscream (aTHXo->interp.Tlastscream) +#define PL_localizing (aTHXo->interp.Tlocalizing) +#define PL_mainstack (aTHXo->interp.Tmainstack) +#define PL_markstack (aTHXo->interp.Tmarkstack) +#define PL_markstack_max (aTHXo->interp.Tmarkstack_max) +#define PL_markstack_ptr (aTHXo->interp.Tmarkstack_ptr) +#define PL_maxscream (aTHXo->interp.Tmaxscream) +#define PL_modcount (aTHXo->interp.Tmodcount) +#define PL_na (aTHXo->interp.Tna) +#define PL_nrs (aTHXo->interp.Tnrs) +#define PL_ofs (aTHXo->interp.Tofs) +#define PL_ofslen (aTHXo->interp.Tofslen) +#define PL_op (aTHXo->interp.Top) +#define PL_opsave (aTHXo->interp.Topsave) +#define PL_protect (aTHXo->interp.Tprotect) +#define PL_reg_call_cc (aTHXo->interp.Treg_call_cc) +#define PL_reg_curpm (aTHXo->interp.Treg_curpm) +#define PL_reg_eval_set (aTHXo->interp.Treg_eval_set) +#define PL_reg_flags (aTHXo->interp.Treg_flags) +#define PL_reg_ganch (aTHXo->interp.Treg_ganch) +#define PL_reg_leftiter (aTHXo->interp.Treg_leftiter) +#define PL_reg_magic (aTHXo->interp.Treg_magic) +#define PL_reg_maxiter (aTHXo->interp.Treg_maxiter) +#define PL_reg_oldcurpm (aTHXo->interp.Treg_oldcurpm) +#define PL_reg_oldpos (aTHXo->interp.Treg_oldpos) +#define PL_reg_oldsaved (aTHXo->interp.Treg_oldsaved) +#define PL_reg_oldsavedlen (aTHXo->interp.Treg_oldsavedlen) +#define PL_reg_poscache (aTHXo->interp.Treg_poscache) +#define PL_reg_poscache_size (aTHXo->interp.Treg_poscache_size) +#define PL_reg_re (aTHXo->interp.Treg_re) +#define PL_reg_start_tmp (aTHXo->interp.Treg_start_tmp) +#define PL_reg_start_tmpl (aTHXo->interp.Treg_start_tmpl) +#define PL_reg_starttry (aTHXo->interp.Treg_starttry) +#define PL_reg_sv (aTHXo->interp.Treg_sv) +#define PL_reg_whilem_seen (aTHXo->interp.Treg_whilem_seen) +#define PL_regbol (aTHXo->interp.Tregbol) +#define PL_regcc (aTHXo->interp.Tregcc) +#define PL_regcode (aTHXo->interp.Tregcode) +#define PL_regcomp_parse (aTHXo->interp.Tregcomp_parse) +#define PL_regcomp_rx (aTHXo->interp.Tregcomp_rx) +#define PL_regcompp (aTHXo->interp.Tregcompp) +#define PL_regdata (aTHXo->interp.Tregdata) +#define PL_regdummy (aTHXo->interp.Tregdummy) +#define PL_regendp (aTHXo->interp.Tregendp) +#define PL_regeol (aTHXo->interp.Tregeol) +#define PL_regexecp (aTHXo->interp.Tregexecp) +#define PL_regflags (aTHXo->interp.Tregflags) +#define PL_regfree (aTHXo->interp.Tregfree) +#define PL_regindent (aTHXo->interp.Tregindent) +#define PL_reginput (aTHXo->interp.Treginput) +#define PL_regint_start (aTHXo->interp.Tregint_start) +#define PL_regint_string (aTHXo->interp.Tregint_string) +#define PL_reginterp_cnt (aTHXo->interp.Treginterp_cnt) +#define PL_reglastparen (aTHXo->interp.Treglastparen) +#define PL_regnarrate (aTHXo->interp.Tregnarrate) +#define PL_regnaughty (aTHXo->interp.Tregnaughty) +#define PL_regnpar (aTHXo->interp.Tregnpar) +#define PL_regprecomp (aTHXo->interp.Tregprecomp) +#define PL_regprev (aTHXo->interp.Tregprev) +#define PL_regprogram (aTHXo->interp.Tregprogram) +#define PL_regsawback (aTHXo->interp.Tregsawback) +#define PL_regseen (aTHXo->interp.Tregseen) +#define PL_regsize (aTHXo->interp.Tregsize) +#define PL_regstartp (aTHXo->interp.Tregstartp) +#define PL_regtill (aTHXo->interp.Tregtill) +#define PL_regxend (aTHXo->interp.Tregxend) +#define PL_restartop (aTHXo->interp.Trestartop) +#define PL_retstack (aTHXo->interp.Tretstack) +#define PL_retstack_ix (aTHXo->interp.Tretstack_ix) +#define PL_retstack_max (aTHXo->interp.Tretstack_max) +#define PL_rs (aTHXo->interp.Trs) +#define PL_savestack (aTHXo->interp.Tsavestack) +#define PL_savestack_ix (aTHXo->interp.Tsavestack_ix) +#define PL_savestack_max (aTHXo->interp.Tsavestack_max) +#define PL_scopestack (aTHXo->interp.Tscopestack) +#define PL_scopestack_ix (aTHXo->interp.Tscopestack_ix) +#define PL_scopestack_max (aTHXo->interp.Tscopestack_max) +#define PL_screamfirst (aTHXo->interp.Tscreamfirst) +#define PL_screamnext (aTHXo->interp.Tscreamnext) +#define PL_secondgv (aTHXo->interp.Tsecondgv) +#define PL_seen_evals (aTHXo->interp.Tseen_evals) +#define PL_seen_zerolen (aTHXo->interp.Tseen_zerolen) +#define PL_sortcop (aTHXo->interp.Tsortcop) +#define PL_sortcxix (aTHXo->interp.Tsortcxix) +#define PL_sortstash (aTHXo->interp.Tsortstash) +#define PL_stack_base (aTHXo->interp.Tstack_base) +#define PL_stack_max (aTHXo->interp.Tstack_max) +#define PL_stack_sp (aTHXo->interp.Tstack_sp) +#define PL_start_env (aTHXo->interp.Tstart_env) +#define PL_statbuf (aTHXo->interp.Tstatbuf) +#define PL_statcache (aTHXo->interp.Tstatcache) +#define PL_statgv (aTHXo->interp.Tstatgv) +#define PL_statname (aTHXo->interp.Tstatname) +#define PL_tainted (aTHXo->interp.Ttainted) +#define PL_timesbuf (aTHXo->interp.Ttimesbuf) +#define PL_tmps_floor (aTHXo->interp.Ttmps_floor) +#define PL_tmps_ix (aTHXo->interp.Ttmps_ix) +#define PL_tmps_max (aTHXo->interp.Ttmps_max) +#define PL_tmps_stack (aTHXo->interp.Ttmps_stack) +#define PL_top_env (aTHXo->interp.Ttop_env) +#define PL_toptarget (aTHXo->interp.Ttoptarget) +#define PL_watchaddr (aTHXo->interp.Twatchaddr) +#define PL_watchok (aTHXo->interp.Twatchok) +#define PL_Argv (aTHXo->interp.IArgv) +#define PL_Cmd (aTHXo->interp.ICmd) +#define PL_DBcv (aTHXo->interp.IDBcv) +#define PL_DBgv (aTHXo->interp.IDBgv) +#define PL_DBline (aTHXo->interp.IDBline) +#define PL_DBsignal (aTHXo->interp.IDBsignal) +#define PL_DBsingle (aTHXo->interp.IDBsingle) +#define PL_DBsub (aTHXo->interp.IDBsub) +#define PL_DBtrace (aTHXo->interp.IDBtrace) +#define PL_Dir (aTHXo->interp.IDir) +#define PL_Env (aTHXo->interp.IEnv) +#define PL_LIO (aTHXo->interp.ILIO) +#define PL_Mem (aTHXo->interp.IMem) +#define PL_MemParse (aTHXo->interp.IMemParse) +#define PL_MemShared (aTHXo->interp.IMemShared) +#define PL_Proc (aTHXo->interp.IProc) +#define PL_Sock (aTHXo->interp.ISock) +#define PL_StdIO (aTHXo->interp.IStdIO) +#define PL_amagic_generation (aTHXo->interp.Iamagic_generation) +#define PL_an (aTHXo->interp.Ian) +#define PL_archpat_auto (aTHXo->interp.Iarchpat_auto) +#define PL_argvgv (aTHXo->interp.Iargvgv) +#define PL_argvout_stack (aTHXo->interp.Iargvout_stack) +#define PL_argvoutgv (aTHXo->interp.Iargvoutgv) +#define PL_basetime (aTHXo->interp.Ibasetime) +#define PL_beginav (aTHXo->interp.Ibeginav) +#define PL_bitcount (aTHXo->interp.Ibitcount) +#define PL_bufend (aTHXo->interp.Ibufend) +#define PL_bufptr (aTHXo->interp.Ibufptr) +#define PL_collation_ix (aTHXo->interp.Icollation_ix) +#define PL_collation_name (aTHXo->interp.Icollation_name) +#define PL_collation_standard (aTHXo->interp.Icollation_standard) +#define PL_collxfrm_base (aTHXo->interp.Icollxfrm_base) +#define PL_collxfrm_mult (aTHXo->interp.Icollxfrm_mult) +#define PL_compcv (aTHXo->interp.Icompcv) +#define PL_compiling (aTHXo->interp.Icompiling) +#define PL_comppad (aTHXo->interp.Icomppad) +#define PL_comppad_name (aTHXo->interp.Icomppad_name) +#define PL_comppad_name_fill (aTHXo->interp.Icomppad_name_fill) +#define PL_comppad_name_floor (aTHXo->interp.Icomppad_name_floor) +#define PL_cop_seqmax (aTHXo->interp.Icop_seqmax) +#define PL_copline (aTHXo->interp.Icopline) +#define PL_cred_mutex (aTHXo->interp.Icred_mutex) +#define PL_cryptseen (aTHXo->interp.Icryptseen) +#define PL_cshlen (aTHXo->interp.Icshlen) +#define PL_cshname (aTHXo->interp.Icshname) +#define PL_curcopdb (aTHXo->interp.Icurcopdb) +#define PL_curstname (aTHXo->interp.Icurstname) +#define PL_curthr (aTHXo->interp.Icurthr) +#define PL_dbargs (aTHXo->interp.Idbargs) +#define PL_debstash (aTHXo->interp.Idebstash) +#define PL_debug (aTHXo->interp.Idebug) +#define PL_defgv (aTHXo->interp.Idefgv) +#define PL_diehook (aTHXo->interp.Idiehook) +#define PL_doextract (aTHXo->interp.Idoextract) +#define PL_doswitches (aTHXo->interp.Idoswitches) +#define PL_dowarn (aTHXo->interp.Idowarn) +#define PL_e_script (aTHXo->interp.Ie_script) +#define PL_egid (aTHXo->interp.Iegid) +#define PL_endav (aTHXo->interp.Iendav) +#define PL_envgv (aTHXo->interp.Ienvgv) +#define PL_errgv (aTHXo->interp.Ierrgv) +#define PL_error_count (aTHXo->interp.Ierror_count) +#define PL_euid (aTHXo->interp.Ieuid) +#define PL_eval_cond (aTHXo->interp.Ieval_cond) +#define PL_eval_mutex (aTHXo->interp.Ieval_mutex) +#define PL_eval_owner (aTHXo->interp.Ieval_owner) +#define PL_eval_root (aTHXo->interp.Ieval_root) +#define PL_eval_start (aTHXo->interp.Ieval_start) +#define PL_evalseq (aTHXo->interp.Ievalseq) +#define PL_exitlist (aTHXo->interp.Iexitlist) +#define PL_exitlistlen (aTHXo->interp.Iexitlistlen) +#define PL_expect (aTHXo->interp.Iexpect) +#define PL_fdpid (aTHXo->interp.Ifdpid) +#define PL_filemode (aTHXo->interp.Ifilemode) +#define PL_forkprocess (aTHXo->interp.Iforkprocess) +#define PL_formfeed (aTHXo->interp.Iformfeed) +#define PL_generation (aTHXo->interp.Igeneration) +#define PL_gensym (aTHXo->interp.Igensym) +#define PL_gid (aTHXo->interp.Igid) +#define PL_glob_index (aTHXo->interp.Iglob_index) +#define PL_globalstash (aTHXo->interp.Iglobalstash) +#define PL_he_root (aTHXo->interp.Ihe_root) +#define PL_hintgv (aTHXo->interp.Ihintgv) +#define PL_hints (aTHXo->interp.Ihints) +#define PL_in_clean_all (aTHXo->interp.Iin_clean_all) +#define PL_in_clean_objs (aTHXo->interp.Iin_clean_objs) +#define PL_in_my (aTHXo->interp.Iin_my) +#define PL_in_my_stash (aTHXo->interp.Iin_my_stash) +#define PL_incgv (aTHXo->interp.Iincgv) +#define PL_initav (aTHXo->interp.Iinitav) +#define PL_inplace (aTHXo->interp.Iinplace) +#define PL_last_lop (aTHXo->interp.Ilast_lop) +#define PL_last_lop_op (aTHXo->interp.Ilast_lop_op) +#define PL_last_swash_hv (aTHXo->interp.Ilast_swash_hv) +#define PL_last_swash_key (aTHXo->interp.Ilast_swash_key) +#define PL_last_swash_klen (aTHXo->interp.Ilast_swash_klen) +#define PL_last_swash_slen (aTHXo->interp.Ilast_swash_slen) +#define PL_last_swash_tmps (aTHXo->interp.Ilast_swash_tmps) +#define PL_last_uni (aTHXo->interp.Ilast_uni) +#define PL_lastfd (aTHXo->interp.Ilastfd) +#define PL_laststatval (aTHXo->interp.Ilaststatval) +#define PL_laststype (aTHXo->interp.Ilaststype) +#define PL_lex_brackets (aTHXo->interp.Ilex_brackets) +#define PL_lex_brackstack (aTHXo->interp.Ilex_brackstack) +#define PL_lex_casemods (aTHXo->interp.Ilex_casemods) +#define PL_lex_casestack (aTHXo->interp.Ilex_casestack) +#define PL_lex_defer (aTHXo->interp.Ilex_defer) +#define PL_lex_dojoin (aTHXo->interp.Ilex_dojoin) +#define PL_lex_expect (aTHXo->interp.Ilex_expect) +#define PL_lex_fakebrack (aTHXo->interp.Ilex_fakebrack) +#define PL_lex_formbrack (aTHXo->interp.Ilex_formbrack) +#define PL_lex_inpat (aTHXo->interp.Ilex_inpat) +#define PL_lex_inwhat (aTHXo->interp.Ilex_inwhat) +#define PL_lex_op (aTHXo->interp.Ilex_op) +#define PL_lex_repl (aTHXo->interp.Ilex_repl) +#define PL_lex_starts (aTHXo->interp.Ilex_starts) +#define PL_lex_state (aTHXo->interp.Ilex_state) +#define PL_lex_stuff (aTHXo->interp.Ilex_stuff) +#define PL_lineary (aTHXo->interp.Ilineary) +#define PL_linestart (aTHXo->interp.Ilinestart) +#define PL_linestr (aTHXo->interp.Ilinestr) +#define PL_localpatches (aTHXo->interp.Ilocalpatches) +#define PL_main_cv (aTHXo->interp.Imain_cv) +#define PL_main_root (aTHXo->interp.Imain_root) +#define PL_main_start (aTHXo->interp.Imain_start) +#define PL_max_intro_pending (aTHXo->interp.Imax_intro_pending) +#define PL_maxo (aTHXo->interp.Imaxo) +#define PL_maxsysfd (aTHXo->interp.Imaxsysfd) +#define PL_mess_sv (aTHXo->interp.Imess_sv) +#define PL_min_intro_pending (aTHXo->interp.Imin_intro_pending) +#define PL_minus_F (aTHXo->interp.Iminus_F) +#define PL_minus_a (aTHXo->interp.Iminus_a) +#define PL_minus_c (aTHXo->interp.Iminus_c) +#define PL_minus_l (aTHXo->interp.Iminus_l) +#define PL_minus_n (aTHXo->interp.Iminus_n) +#define PL_minus_p (aTHXo->interp.Iminus_p) +#define PL_modglobal (aTHXo->interp.Imodglobal) +#define PL_multi_close (aTHXo->interp.Imulti_close) +#define PL_multi_end (aTHXo->interp.Imulti_end) +#define PL_multi_open (aTHXo->interp.Imulti_open) +#define PL_multi_start (aTHXo->interp.Imulti_start) +#define PL_multiline (aTHXo->interp.Imultiline) +#define PL_nexttoke (aTHXo->interp.Inexttoke) +#define PL_nexttype (aTHXo->interp.Inexttype) +#define PL_nextval (aTHXo->interp.Inextval) +#define PL_nice_chunk (aTHXo->interp.Inice_chunk) +#define PL_nice_chunk_size (aTHXo->interp.Inice_chunk_size) +#define PL_nomemok (aTHXo->interp.Inomemok) +#define PL_nthreads (aTHXo->interp.Inthreads) +#define PL_nthreads_cond (aTHXo->interp.Inthreads_cond) +#define PL_numeric_local (aTHXo->interp.Inumeric_local) +#define PL_numeric_name (aTHXo->interp.Inumeric_name) +#define PL_numeric_radix (aTHXo->interp.Inumeric_radix) +#define PL_numeric_standard (aTHXo->interp.Inumeric_standard) +#define PL_ofmt (aTHXo->interp.Iofmt) +#define PL_oldbufptr (aTHXo->interp.Ioldbufptr) +#define PL_oldname (aTHXo->interp.Ioldname) +#define PL_oldoldbufptr (aTHXo->interp.Ioldoldbufptr) +#define PL_op_mask (aTHXo->interp.Iop_mask) +#define PL_op_seqmax (aTHXo->interp.Iop_seqmax) +#define PL_origalen (aTHXo->interp.Iorigalen) +#define PL_origargc (aTHXo->interp.Iorigargc) +#define PL_origargv (aTHXo->interp.Iorigargv) +#define PL_origenviron (aTHXo->interp.Iorigenviron) +#define PL_origfilename (aTHXo->interp.Iorigfilename) +#define PL_ors (aTHXo->interp.Iors) +#define PL_orslen (aTHXo->interp.Iorslen) +#define PL_osname (aTHXo->interp.Iosname) +#define PL_pad_reset_pending (aTHXo->interp.Ipad_reset_pending) +#define PL_padix (aTHXo->interp.Ipadix) +#define PL_padix_floor (aTHXo->interp.Ipadix_floor) +#define PL_patchlevel (aTHXo->interp.Ipatchlevel) +#define PL_pending_ident (aTHXo->interp.Ipending_ident) +#define PL_perl_destruct_level (aTHXo->interp.Iperl_destruct_level) +#define PL_perldb (aTHXo->interp.Iperldb) +#define PL_pidstatus (aTHXo->interp.Ipidstatus) +#define PL_preambleav (aTHXo->interp.Ipreambleav) +#define PL_preambled (aTHXo->interp.Ipreambled) +#define PL_preprocess (aTHXo->interp.Ipreprocess) +#define PL_profiledata (aTHXo->interp.Iprofiledata) +#define PL_psig_name (aTHXo->interp.Ipsig_name) +#define PL_psig_ptr (aTHXo->interp.Ipsig_ptr) +#define PL_ptr_table (aTHXo->interp.Iptr_table) +#define PL_replgv (aTHXo->interp.Ireplgv) +#define PL_rsfp (aTHXo->interp.Irsfp) +#define PL_rsfp_filters (aTHXo->interp.Irsfp_filters) +#define PL_runops (aTHXo->interp.Irunops) +#define PL_sawampersand (aTHXo->interp.Isawampersand) +#define PL_sh_path (aTHXo->interp.Ish_path) +#define PL_sighandlerp (aTHXo->interp.Isighandlerp) +#define PL_splitstr (aTHXo->interp.Isplitstr) +#define PL_srand_called (aTHXo->interp.Isrand_called) +#define PL_statusvalue (aTHXo->interp.Istatusvalue) +#define PL_statusvalue_vms (aTHXo->interp.Istatusvalue_vms) +#define PL_stderrgv (aTHXo->interp.Istderrgv) +#define PL_stdingv (aTHXo->interp.Istdingv) +#define PL_stopav (aTHXo->interp.Istopav) +#define PL_strtab (aTHXo->interp.Istrtab) +#define PL_strtab_mutex (aTHXo->interp.Istrtab_mutex) +#define PL_sub_generation (aTHXo->interp.Isub_generation) +#define PL_sublex_info (aTHXo->interp.Isublex_info) +#define PL_subline (aTHXo->interp.Isubline) +#define PL_subname (aTHXo->interp.Isubname) +#define PL_sv_arenaroot (aTHXo->interp.Isv_arenaroot) +#define PL_sv_count (aTHXo->interp.Isv_count) +#define PL_sv_mutex (aTHXo->interp.Isv_mutex) +#define PL_sv_no (aTHXo->interp.Isv_no) +#define PL_sv_objcount (aTHXo->interp.Isv_objcount) +#define PL_sv_root (aTHXo->interp.Isv_root) +#define PL_sv_undef (aTHXo->interp.Isv_undef) +#define PL_sv_yes (aTHXo->interp.Isv_yes) +#define PL_svref_mutex (aTHXo->interp.Isvref_mutex) +#define PL_sys_intern (aTHXo->interp.Isys_intern) +#define PL_tainting (aTHXo->interp.Itainting) +#define PL_thr_key (aTHXo->interp.Ithr_key) +#define PL_threadnum (aTHXo->interp.Ithreadnum) +#define PL_threads_mutex (aTHXo->interp.Ithreads_mutex) +#define PL_threadsv_names (aTHXo->interp.Ithreadsv_names) +#define PL_thrsv (aTHXo->interp.Ithrsv) +#define PL_tokenbuf (aTHXo->interp.Itokenbuf) +#define PL_uid (aTHXo->interp.Iuid) +#define PL_unsafe (aTHXo->interp.Iunsafe) +#define PL_utf8_alnum (aTHXo->interp.Iutf8_alnum) +#define PL_utf8_alnumc (aTHXo->interp.Iutf8_alnumc) +#define PL_utf8_alpha (aTHXo->interp.Iutf8_alpha) +#define PL_utf8_ascii (aTHXo->interp.Iutf8_ascii) +#define PL_utf8_cntrl (aTHXo->interp.Iutf8_cntrl) +#define PL_utf8_digit (aTHXo->interp.Iutf8_digit) +#define PL_utf8_graph (aTHXo->interp.Iutf8_graph) +#define PL_utf8_lower (aTHXo->interp.Iutf8_lower) +#define PL_utf8_mark (aTHXo->interp.Iutf8_mark) +#define PL_utf8_print (aTHXo->interp.Iutf8_print) +#define PL_utf8_punct (aTHXo->interp.Iutf8_punct) +#define PL_utf8_space (aTHXo->interp.Iutf8_space) +#define PL_utf8_tolower (aTHXo->interp.Iutf8_tolower) +#define PL_utf8_totitle (aTHXo->interp.Iutf8_totitle) +#define PL_utf8_toupper (aTHXo->interp.Iutf8_toupper) +#define PL_utf8_upper (aTHXo->interp.Iutf8_upper) +#define PL_utf8_xdigit (aTHXo->interp.Iutf8_xdigit) +#define PL_uudmap (aTHXo->interp.Iuudmap) +#define PL_warnhook (aTHXo->interp.Iwarnhook) +#define PL_xiv_arenaroot (aTHXo->interp.Ixiv_arenaroot) +#define PL_xiv_root (aTHXo->interp.Ixiv_root) +#define PL_xnv_root (aTHXo->interp.Ixnv_root) +#define PL_xpv_root (aTHXo->interp.Ixpv_root) +#define PL_xpvav_root (aTHXo->interp.Ixpvav_root) +#define PL_xpvbm_root (aTHXo->interp.Ixpvbm_root) +#define PL_xpvcv_root (aTHXo->interp.Ixpvcv_root) +#define PL_xpvhv_root (aTHXo->interp.Ixpvhv_root) +#define PL_xpviv_root (aTHXo->interp.Ixpviv_root) +#define PL_xpvlv_root (aTHXo->interp.Ixpvlv_root) +#define PL_xpvmg_root (aTHXo->interp.Ixpvmg_root) +#define PL_xpvnv_root (aTHXo->interp.Ixpvnv_root) +#define PL_xrv_root (aTHXo->interp.Ixrv_root) +#define PL_yychar (aTHXo->interp.Iyychar) +#define PL_yydebug (aTHXo->interp.Iyydebug) +#define PL_yyerrflag (aTHXo->interp.Iyyerrflag) +#define PL_yylval (aTHXo->interp.Iyylval) +#define PL_yynerrs (aTHXo->interp.Iyynerrs) +#define PL_yyval (aTHXo->interp.Iyyval) + +# else /* !PERL_OBJECT */ + +/* cases 1 and 4 above */ #define PL_IArgv PL_Argv #define PL_ICmd PL_Cmd @@ -708,6 +1117,8 @@ #define PL_IEnv PL_Env #define PL_ILIO PL_LIO #define PL_IMem PL_Mem +#define PL_IMemParse PL_MemParse +#define PL_IMemShared PL_MemShared #define PL_IProc PL_Proc #define PL_ISock PL_Sock #define PL_IStdIO PL_StdIO @@ -874,6 +1285,8 @@ #define PL_Ipreambled PL_preambled #define PL_Ipreprocess PL_preprocess #define PL_Iprofiledata PL_profiledata +#define PL_Ipsig_name PL_psig_name +#define PL_Ipsig_ptr PL_psig_ptr #define PL_Iptr_table PL_ptr_table #define PL_Ireplgv PL_replgv #define PL_Irsfp PL_rsfp @@ -953,7 +1366,7 @@ #define PL_Iyynerrs PL_yynerrs #define PL_Iyyval PL_yyval -# if defined(USE_THREADS) +# if defined(USE_THREADS) /* case 4 above */ #define PL_Sv (aTHX->TSv) @@ -1090,8 +1503,8 @@ #define PL_watchaddr (aTHX->Twatchaddr) #define PL_watchok (aTHX->Twatchok) -# else /* !USE_THREADS */ -/* cases 1 and 6 above */ +# else /* !USE_THREADS */ +/* case 1 above */ #define PL_TSv PL_Sv #define PL_TXpv PL_Xpv @@ -1227,7 +1640,8 @@ #define PL_Twatchaddr PL_watchaddr #define PL_Twatchok PL_watchok -# endif /* USE_THREADS */ +# endif /* USE_THREADS */ +# endif /* PERL_OBJECT */ #endif /* MULTIPLICITY */ #if defined(PERL_GLOBAL_STRUCT) diff --git a/ext/B/B/CC.pm b/ext/B/B/CC.pm index 0fe5e7d..cf0e81f 100644 --- a/ext/B/B/CC.pm +++ b/ext/B/B/CC.pm @@ -1644,8 +1644,8 @@ XS(boot_$cmodule) perl_init(); ENTER; SAVETMPS; - SAVESPTR(PL_curpad); - SAVESPTR(PL_op); + SAVEVPTR(PL_curpad); + SAVEVPTR(PL_op); PL_curpad = AvARRAY($curpad_sym); PL_op = $start; pp_main(aTHX); diff --git a/ext/Opcode/Opcode.xs b/ext/Opcode/Opcode.xs index 63ff8aa..581cbc9 100644 --- a/ext/Opcode/Opcode.xs +++ b/ext/Opcode/Opcode.xs @@ -204,7 +204,7 @@ static void opmask_addlocal(pTHX_ SV *opset, char *op_mask_buf) /* Localise PL_op_mask then opmask_add() */ { char *orig_op_mask = PL_op_mask; - SAVEPPTR(PL_op_mask); + SAVEVPTR(PL_op_mask); #if !defined(PERL_OBJECT) /* XXX casting to an ordinary function ptr from a member function ptr * is disallowed by Borland diff --git a/global.sym b/global.sym index e219030..796ab64 100644 --- a/global.sym +++ b/global.sym @@ -4,6 +4,20 @@ # and run 'make regen_headers' to effect changes. # +perl_alloc_using +perl_alloc +perl_construct +perl_destruct +perl_free +perl_run +perl_parse +perl_clone +perl_clone_using +Perl_malloc +Perl_calloc +Perl_realloc +Perl_mfree +Perl_malloced_size Perl_amagic_call Perl_Gv_AMupdate Perl_append_elem @@ -292,7 +306,6 @@ Perl_magic_set_all_env Perl_magic_sizepack Perl_magic_wipepack Perl_magicname -Perl_malloced_size Perl_markstack_grow Perl_mem_collxfrm Perl_mess @@ -393,17 +406,6 @@ Perl_pad_free Perl_pad_reset Perl_pad_swipe Perl_peep -perl_construct -perl_destruct -perl_free -perl_run -perl_parse -perl_alloc -perl_construct -perl_destruct -perl_free -perl_run -perl_parse Perl_new_struct_thread Perl_call_atexit Perl_call_argv @@ -486,6 +488,7 @@ Perl_save_nogv Perl_save_op Perl_save_scalar Perl_save_pptr +Perl_save_vptr Perl_save_re_context Perl_save_sptr Perl_save_svref @@ -619,10 +622,6 @@ Perl_yylex Perl_yyparse Perl_yywarn Perl_dump_mstats -Perl_malloc -Perl_calloc -Perl_realloc -Perl_mfree Perl_safesysmalloc Perl_safesyscalloc Perl_safesysrealloc @@ -678,6 +677,7 @@ Perl_boot_core_xsutils Perl_cx_dup Perl_si_dup Perl_ss_dup +Perl_any_dup Perl_he_dup Perl_re_dup Perl_fp_dup @@ -690,5 +690,3 @@ Perl_ptr_table_new Perl_ptr_table_fetch Perl_ptr_table_store Perl_ptr_table_split -perl_clone -perl_clone_using diff --git a/globals.c b/globals.c index 8e19d22..80c659e 100644 --- a/globals.c +++ b/globals.c @@ -9,11 +9,12 @@ #undef PERLVARA #define PERLVARA(x, n, y) #undef PERLVARI -#define PERLVARI(x, y, z) PL_##x = z; +#define PERLVARI(x, y, z) interp.x = z; #undef PERLVARIC -#define PERLVARIC(x, y, z) PL_##x = z; +#define PERLVARIC(x, y, z) interp.x = z; -CPerlObj::CPerlObj(IPerlMem* ipM, IPerlEnv* ipE, IPerlStdIO* ipStd, +CPerlObj::CPerlObj(IPerlMem* ipM, IPerlMem* ipMS, IPerlMem* ipMP, + IPerlEnv* ipE, IPerlStdIO* ipStd, IPerlLIO* ipLIO, IPerlDir* ipD, IPerlSock* ipS, IPerlProc* ipP) { @@ -21,9 +22,10 @@ CPerlObj::CPerlObj(IPerlMem* ipM, IPerlEnv* ipE, IPerlStdIO* ipStd, #include "thrdvar.h" #include "intrpvar.h" -#include "perlvars.h" PL_Mem = ipM; + PL_MemShared = ipMS; + PL_MemParse = ipMP; PL_Env = ipE; PL_StdIO = ipStd; PL_LIO = ipLIO; @@ -50,11 +52,6 @@ CPerlObj::operator delete(void *pPerl, IPerlMem *pvtbl) pvtbl->pFree(pvtbl, pPerl); } -void -CPerlObj::Init(void) -{ -} - #ifdef WIN32 /* XXX why are these needed? */ bool Perl_do_exec(char *cmd) diff --git a/globvar.sym b/globvar.sym index 3cb8ccc..0d76888 100644 --- a/globvar.sym +++ b/globvar.sym @@ -32,8 +32,6 @@ opargs ppaddr sig_name sig_num -psig_name -psig_ptr regkind simple utf8skip diff --git a/gv.c b/gv.c index f6c9744..e1e4ae0 100644 --- a/gv.c +++ b/gv.c @@ -655,10 +655,15 @@ Perl_gv_fetchpv(pTHX_ const char *nambeg, I32 add, I32 sv_type) if (strEQ(name, "SIG")) { HV *hv; I32 i; + if (!PL_psig_ptr) { + int sig_num[] = { SIG_NUM }; + New(73, PL_psig_ptr, sizeof(sig_num)/sizeof(*sig_num), SV*); + New(73, PL_psig_name, sizeof(sig_num)/sizeof(*sig_num), SV*); + } GvMULTI_on(gv); hv = GvHVn(gv); hv_magic(hv, gv, 'S'); - for(i = 1; PL_sig_name[i]; i++) { + for (i = 1; PL_sig_name[i]; i++) { SV ** init; init = hv_fetch(hv, PL_sig_name[i], strlen(PL_sig_name[i]), 1); if (init) diff --git a/hv.c b/hv.c index e38c785..c591cbf 100644 --- a/hv.c +++ b/hv.c @@ -81,8 +81,16 @@ Perl_he_dup(pTHX_ HE *e, bool shared) if (!e) return Nullhe; + /* look for it in the table first */ + ret = (HE*)ptr_table_fetch(PL_ptr_table, e); + if (ret) + return ret; + + /* create anew and remember what it is */ ret = new_he(); - HeNEXT(ret) = (HE*)NULL; + ptr_table_store(PL_ptr_table, e, ret); + + HeNEXT(ret) = he_dup(HeNEXT(e),shared); if (HeKLEN(e) == HEf_SVKEY) HeKEY_sv(ret) = SvREFCNT_inc(sv_dup(HeKEY_sv(e))); else if (shared) diff --git a/intrpvar.h b/intrpvar.h index c772d79..d7a669c 100644 --- a/intrpvar.h +++ b/intrpvar.h @@ -369,8 +369,13 @@ PERLVAR(Icred_mutex, perl_mutex) /* altered credentials in effect */ #endif /* USE_THREADS */ +PERLVAR(Ipsig_ptr, SV**) +PERLVAR(Ipsig_name, SV**) + #if defined(PERL_IMPLICIT_SYS) PERLVAR(IMem, struct IPerlMem*) +PERLVAR(IMemShared, struct IPerlMem*) +PERLVAR(IMemParse, struct IPerlMem*) PERLVAR(IEnv, struct IPerlEnv*) PERLVAR(IStdIO, struct IPerlStdIO*) PERLVAR(ILIO, struct IPerlLIO*) diff --git a/iperlsys.h b/iperlsys.h index 9404d18..222d88b 100644 --- a/iperlsys.h +++ b/iperlsys.h @@ -86,6 +86,7 @@ typedef struct _PerlIO PerlIO; /* IPerlStdIO */ struct IPerlStdIO; +struct IPerlStdIOInfo; typedef PerlIO* (*LPStdin)(struct IPerlStdIO*); typedef PerlIO* (*LPStdout)(struct IPerlStdIO*); typedef PerlIO* (*LPStderr)(struct IPerlStdIO*); @@ -132,6 +133,7 @@ typedef int (*LPSetpos)(struct IPerlStdIO*, PerlIO*, const Fpos_t*); typedef void (*LPInit)(struct IPerlStdIO*); typedef void (*LPInitOSExtras)(struct IPerlStdIO*); +typedef PerlIO* (*LPFdupopen)(struct IPerlStdIO*, PerlIO*); struct IPerlStdIO { @@ -173,6 +175,7 @@ struct IPerlStdIO LPSetpos pSetpos; LPInit pInit; LPInitOSExtras pInitOSExtras; + LPFdupopen pFdupopen; }; struct IPerlStdIOInfo @@ -283,6 +286,8 @@ struct IPerlStdIOInfo #undef init_os_extras #define init_os_extras() \ (*PL_StdIO->pInitOSExtras)(PL_StdIO) +#define PerlIO_fdupopen(f) \ + (*PL_StdIO->pFdupopen)(PL_StdIO, (f)) #else /* PERL_IMPLICIT_SYS */ @@ -465,6 +470,9 @@ extern int PerlIO_getpos (PerlIO *,Fpos_t *); #ifndef PerlIO_setpos extern int PerlIO_setpos (PerlIO *,const Fpos_t *); #endif +#ifndef PerlIO_fdupopen +extern PerlIO * PerlIO_fdupopen (PerlIO *); +#endif /* @@ -475,6 +483,7 @@ extern int PerlIO_setpos (PerlIO *,const Fpos_t *); /* IPerlDir */ struct IPerlDir; +struct IPerlDirInfo; typedef int (*LPMakedir)(struct IPerlDir*, const char*, int); typedef int (*LPChdir)(struct IPerlDir*, const char*); typedef int (*LPRmdir)(struct IPerlDir*, const char*); @@ -484,6 +493,10 @@ typedef struct direct* (*LPDirRead)(struct IPerlDir*, DIR*); typedef void (*LPDirRewind)(struct IPerlDir*, DIR*); typedef void (*LPDirSeek)(struct IPerlDir*, DIR*, long); typedef long (*LPDirTell)(struct IPerlDir*, DIR*); +#ifdef WIN32 +typedef char* (*LPDirMapPathA)(struct IPerlDir*, const char*); +typedef WCHAR* (*LPDirMapPathW)(struct IPerlDir*, const WCHAR*); +#endif struct IPerlDir { @@ -496,6 +509,10 @@ struct IPerlDir LPDirRewind pRewind; LPDirSeek pSeek; LPDirTell pTell; +#ifdef WIN32 + LPDirMapPathA pMapPathA; + LPDirMapPathW pMapPathW; +#endif }; struct IPerlDirInfo @@ -522,6 +539,12 @@ struct IPerlDirInfo (*PL_Dir->pSeek)(PL_Dir, (dir), (loc)) #define PerlDir_tell(dir) \ (*PL_Dir->pTell)(PL_Dir, (dir)) +#ifdef WIN32 +#define PerlDir_mapA(dir) \ + (*PL_Dir->pMapPathA)(PL_Dir, (dir)) +#define PerlDir_mapW(dir) \ + (*PL_Dir->pMapPathW)(PL_Dir, (dir)) +#endif #else /* PERL_IMPLICIT_SYS */ @@ -538,6 +561,10 @@ struct IPerlDirInfo #define PerlDir_rewind(dir) rewinddir((dir)) #define PerlDir_seek(dir, loc) seekdir((dir), (loc)) #define PerlDir_tell(dir) telldir((dir)) +#ifdef WIN32 +#define PerlDir_mapA(dir) dir +#define PerlDir_mapW(dir) dir +#endif #endif /* PERL_IMPLICIT_SYS */ @@ -549,6 +576,7 @@ struct IPerlDirInfo /* IPerlEnv */ struct IPerlEnv; +struct IPerlEnvInfo; typedef char* (*LPEnvGetenv)(struct IPerlEnv*, const char*); typedef int (*LPEnvPutenv)(struct IPerlEnv*, const char*); typedef char* (*LPEnvGetenv_len)(struct IPerlEnv*, @@ -641,7 +669,7 @@ struct IPerlEnvInfo #define PerlEnv_putenv(str) putenv((str)) #define PerlEnv_getenv(str) getenv((str)) #define PerlEnv_getenv_len(str,l) getenv_len((str), (l)) -#define PerlEnv_clear() clearenv() +#define PerlEnv_clearenv() clearenv() #define PerlEnv_get_childenv() get_childenv() #define PerlEnv_free_childenv(e) free_childenv((e)) #define PerlEnv_get_childdir() get_childdir() @@ -669,6 +697,7 @@ struct IPerlEnvInfo /* IPerlLIO */ struct IPerlLIO; +struct IPerlLIOInfo; typedef int (*LPLIOAccess)(struct IPerlLIO*, const char*, int); typedef int (*LPLIOChmod)(struct IPerlLIO*, const char*, int); typedef int (*LPLIOChown)(struct IPerlLIO*, const char*, uid_t, @@ -836,15 +865,24 @@ struct IPerlLIOInfo /* IPerlMem */ struct IPerlMem; +struct IPerlMemInfo; typedef void* (*LPMemMalloc)(struct IPerlMem*, size_t); typedef void* (*LPMemRealloc)(struct IPerlMem*, void*, size_t); typedef void (*LPMemFree)(struct IPerlMem*, void*); +typedef void* (*LPMemCalloc)(struct IPerlMem*, size_t, size_t); +typedef void (*LPMemGetLock)(struct IPerlMem*); +typedef void (*LPMemFreeLock)(struct IPerlMem*); +typedef int (*LPMemIsLocked)(struct IPerlMem*); struct IPerlMem { LPMemMalloc pMalloc; LPMemRealloc pRealloc; LPMemFree pFree; + LPMemCalloc pCalloc; + LPMemGetLock pGetLock; + LPMemFreeLock pFreeLock; + LPMemIsLocked pIsLocked; }; struct IPerlMemInfo @@ -853,18 +891,84 @@ struct IPerlMemInfo struct IPerlMem perlMemList; }; +/* Interpreter specific memory macros */ #define PerlMem_malloc(size) \ (*PL_Mem->pMalloc)(PL_Mem, (size)) #define PerlMem_realloc(buf, size) \ (*PL_Mem->pRealloc)(PL_Mem, (buf), (size)) #define PerlMem_free(buf) \ (*PL_Mem->pFree)(PL_Mem, (buf)) +#define PerlMem_calloc(num, size) \ + (*PL_Mem->pCalloc)(PL_Mem, (num), (size)) +#define PerlMem_get_lock() \ + (*PL_Mem->pGetLock)(PL_Mem) +#define PerlMem_free_lock() \ + (*PL_Mem->pFreeLock)(PL_Mem) +#define PerlMem_is_locked() \ + (*PL_Mem->pIsLocked)(PL_Mem) + +/* Shared memory macros */ +#define PerlMemShared_malloc(size) \ + (*PL_MemShared->pMalloc)(PL_Mem, (size)) +#define PerlMemShared_realloc(buf, size) \ + (*PL_MemShared->pRealloc)(PL_Mem, (buf), (size)) +#define PerlMemShared_free(buf) \ + (*PL_MemShared->pFree)(PL_Mem, (buf)) +#define PerlMemShared_calloc(num, size) \ + (*PL_MemShared->pCalloc)(PL_Mem, (num), (size)) +#define PerlMemShared_get_lock() \ + (*PL_MemShared->pGetLock)(PL_Mem) +#define PerlMemShared_free_lock() \ + (*PL_MemShared->pFreeLock)(PL_Mem) +#define PerlMemShared_is_locked() \ + (*PL_MemShared->pIsLocked)(PL_Mem) + + +/* Parse tree memory macros */ +#define PerlMemParse_malloc(size) \ + (*PL_MemParse->pMalloc)(PL_Mem, (size)) +#define PerlMemParse_realloc(buf, size) \ + (*PL_MemParse->pRealloc)(PL_Mem, (buf), (size)) +#define PerlMemParse_free(buf) \ + (*PL_MemParse->pFree)(PL_Mem, (buf)) +#define PerlMemParse_calloc(num, size) \ + (*PL_MemParse->pCalloc)(PL_Mem, (num), (size)) +#define PerlMemParse_get_lock() \ + (*PL_MemParse->pGetLock)(PL_Mem) +#define PerlMemParse_free_lock() \ + (*PL_MemParse->pFreeLock)(PL_Mem) +#define PerlMemParse_is_locked() \ + (*PL_MemParse->pIsLocked)(PL_Mem) + #else /* PERL_IMPLICIT_SYS */ +/* Interpreter specific memory macros */ #define PerlMem_malloc(size) malloc((size)) #define PerlMem_realloc(buf, size) realloc((buf), (size)) #define PerlMem_free(buf) free((buf)) +#define PerlMem_calloc(num, size) calloc((num), (size)) +#define PerlMem_get_lock() +#define PerlMem_free_lock() +#define PerlMem_is_locked() 0 + +/* Shared memory macros */ +#define PerlMemShared_malloc(size) malloc((size)) +#define PerlMemShared_realloc(buf, size) realloc((buf), (size)) +#define PerlMemShared_free(buf) free((buf)) +#define PerlMemShared_calloc(num, size) calloc((num), (size)) +#define PerlMemShared_get_lock() +#define PerlMemShared_free_lock() +#define PerlMemShared_is_locked() 0 + +/* Parse tree memory macros */ +#define PerlMemParse_malloc(size) malloc((size)) +#define PerlMemParse_realloc(buf, size) realloc((buf), (size)) +#define PerlMemParse_free(buf) free((buf)) +#define PerlMemParse_calloc(num, size) calloc((num), (size)) +#define PerlMemParse_get_lock() +#define PerlMemParse_free_lock() +#define PerlMemParse_is_locked() 0 #endif /* PERL_IMPLICIT_SYS */ @@ -881,6 +985,7 @@ struct IPerlMemInfo /* IPerlProc */ struct IPerlProc; +struct IPerlProcInfo; typedef void (*LPProcAbort)(struct IPerlProc*); typedef char* (*LPProcCrypt)(struct IPerlProc*, const char*, const char*); @@ -912,8 +1017,10 @@ typedef int (*LPProcTimes)(struct IPerlProc*, struct tms*); typedef int (*LPProcWait)(struct IPerlProc*, int*); typedef int (*LPProcWaitpid)(struct IPerlProc*, int, int*, int); typedef Sighandler_t (*LPProcSignal)(struct IPerlProc*, int, Sighandler_t); -typedef void* (*LPProcDynaLoader)(struct IPerlProc*, const char*); +typedef int (*LPProcFork)(struct IPerlProc*); +typedef int (*LPProcGetpid)(struct IPerlProc*); #ifdef WIN32 +typedef void* (*LPProcDynaLoader)(struct IPerlProc*, const char*); typedef void (*LPProcGetOSError)(struct IPerlProc*, SV* sv, DWORD dwErr); typedef void (*LPProcFreeBuf)(struct IPerlProc*, char*); @@ -951,6 +1058,8 @@ struct IPerlProc LPProcWait pWait; LPProcWaitpid pWaitpid; LPProcSignal pSignal; + LPProcFork pFork; + LPProcGetpid pGetpid; #ifdef WIN32 LPProcDynaLoader pDynaLoader; LPProcGetOSError pGetOSError; @@ -1017,6 +1126,10 @@ struct IPerlProcInfo (*PL_Proc->pWaitpid)(PL_Proc, (p), (s), (f)) #define PerlProc_signal(n, h) \ (*PL_Proc->pSignal)(PL_Proc, (n), (h)) +#define PerlProc_fork() \ + (*PL_Proc->pFork)(PL_Proc) +#define PerlProc_getpid() \ + (*PL_Proc->pGetpid)(PL_Proc) #define PerlProc_setjmp(b, n) Sigsetjmp((b), (n)) #define PerlProc_longjmp(b, n) Siglongjmp((b), (n)) @@ -1065,6 +1178,8 @@ struct IPerlProcInfo #define PerlProc_setjmp(b, n) Sigsetjmp((b), (n)) #define PerlProc_longjmp(b, n) Siglongjmp((b), (n)) #define PerlProc_signal(n, h) signal((n), (h)) +#define PerlProc_fork() fork() +#define PerlProc_getpid() getpid() #ifdef WIN32 #define PerlProc_DynaLoad(f) \ @@ -1082,6 +1197,7 @@ struct IPerlProcInfo /* PerlSock */ struct IPerlSock; +struct IPerlSockInfo; typedef u_long (*LPHtonl)(struct IPerlSock*, u_long); typedef u_short (*LPHtons)(struct IPerlSock*, u_short); typedef u_long (*LPNtohl)(struct IPerlSock*, u_long); diff --git a/makedef.pl b/makedef.pl index 40c9be3..4b1b84f 100644 --- a/makedef.pl +++ b/makedef.pl @@ -38,14 +38,13 @@ my %bincompat5005 = my $bincompat5005 = join("|", keys %bincompat5005); -while (@ARGV) - { - my $flag = shift; - $define{$1} = 1 if ($flag =~ /^-D(\w+)$/); - $define{$1} = $2 if ($flag =~ /^-D(\w+)=(.+)$/); - $CCTYPE = $1 if ($flag =~ /^CCTYPE=(\w+)$/); - $PLATFORM = $1 if ($flag =~ /^PLATFORM=(\w+)$/); - } +while (@ARGV) { + my $flag = shift; + $define{$1} = 1 if ($flag =~ /^-D(\w+)$/); + $define{$1} = $2 if ($flag =~ /^-D(\w+)=(.+)$/); + $CCTYPE = $1 if ($flag =~ /^CCTYPE=(\w+)$/); + $PLATFORM = $1 if ($flag =~ /^PLATFORM=(\w+)$/); +} my @PLATFORM = qw(aix win32 os2); my %PLATFORM; @@ -66,7 +65,8 @@ my $perlio_sym = "perlio.sym"; if ($PLATFORM eq 'aix') { # Nothing for now. -} elsif ($PLATFORM eq 'win32') { +} +elsif ($PLATFORM eq 'win32') { $CCTYPE = "MSVC" unless defined $CCTYPE; foreach ($thrdvar_h, $intrpvar_h, $perlvars_h, $global_sym, $pp_sym, $globvar_sym) { s!^!..\\!; @@ -75,8 +75,7 @@ if ($PLATFORM eq 'aix') { unless ($PLATFORM eq 'win32') { open(CFG,$config_sh) || die "Cannot open $config_sh: $!\n"; - while () - { + while () { if (/^(?:ccflags|optimize)='(.+)'$/) { $_ = $1; $define{$1} = 1 while /-D(\w+)/g; @@ -90,14 +89,13 @@ unless ($PLATFORM eq 'win32') { } open(CFG,$config_h) || die "Cannot open $config_h: $!\n"; -while () - { - $define{$1} = 1 if /^\s*#\s*define\s+(MYMALLOC)\b/; - $define{$1} = 1 if /^\s*#\s*define\s+(USE_THREADS)\b/; - $define{$1} = 1 if /^\s*#\s*define\s+(USE_PERLIO)\b/; - $define{$1} = 1 if /^\s*#\s*define\s+(MULTIPLICITY)\b/; - $define{$1} = 1 if /^\s*#\s*define\s+(PERL_BINCOMPAT_5005)\b/; - } +while () { + $define{$1} = 1 if /^\s*#\s*define\s+(MYMALLOC)\b/; + $define{$1} = 1 if /^\s*#\s*define\s+(USE_THREADS)\b/; + $define{$1} = 1 if /^\s*#\s*define\s+(USE_PERLIO)\b/; + $define{$1} = 1 if /^\s*#\s*define\s+(MULTIPLICITY)\b/; + $define{$1} = 1 if /^\s*#\s*define\s+(PERL_BINCOMPAT_5005)\b/; +} close(CFG); if ($PLATFORM eq 'win32') { @@ -108,7 +106,7 @@ if ($PLATFORM eq 'win32') { print "EXPORTS\n"; # output_symbol("perl_alloc"); output_symbol("perl_get_host_info"); - output_symbol("perl_alloc_using"); + output_symbol("perl_alloc_override"); # output_symbol("perl_construct"); # output_symbol("perl_destruct"); # output_symbol("perl_free"); @@ -128,7 +126,8 @@ if ($PLATFORM eq 'win32') { } print "EXPORTS\n"; } -} elsif ($PLATFORM eq 'os2') { +} +elsif ($PLATFORM eq 'os2') { ($v = $]) =~ s/(\d\.\d\d\d)(\d\d)$/$1_$2/; $v .= '-thread' if $ARCHNAME =~ /-thread/; #$sum = 0; @@ -149,7 +148,8 @@ CODE LOADONCALL DATA LOADONCALL NONSHARED MULTIPLE EXPORTS ---EOP--- -} elsif ($PLATFORM eq 'aix') { +} +elsif ($PLATFORM eq 'aix') { print "#!\n"; } @@ -176,318 +176,314 @@ sub emit_symbols { } if ($PLATFORM eq 'win32') { -skip_symbols [qw( -PL_statusvalue_vms -PL_archpat_auto -PL_cryptseen -PL_DBcv -PL_generation -PL_lastgotoprobe -PL_linestart -PL_modcount -PL_pending_ident -PL_sortcxix -PL_sublex_info -PL_timesbuf -main -Perl_ErrorNo -Perl_GetVars -Perl_do_exec3 -Perl_do_ipcctl -Perl_do_ipcget -Perl_do_msgrcv -Perl_do_msgsnd -Perl_do_semop -Perl_do_shmio -Perl_dump_fds -Perl_init_thread_intern -Perl_my_bzero -Perl_my_htonl -Perl_my_ntohl -Perl_my_swap -Perl_my_chsize -Perl_same_dirent -Perl_setenv_getix -Perl_unlnk -Perl_watch -Perl_safexcalloc -Perl_safexmalloc -Perl_safexfree -Perl_safexrealloc -Perl_my_memcmp -Perl_my_memset -PL_cshlen -PL_cshname -PL_opsave - -Perl_do_exec -Perl_getenv_len -Perl_my_pclose -Perl_my_popen -)]; -} elsif ($PLATFORM eq 'aix') { + skip_symbols [qw( + PL_statusvalue_vms + PL_archpat_auto + PL_cryptseen + PL_DBcv + PL_generation + PL_lastgotoprobe + PL_linestart + PL_modcount + PL_pending_ident + PL_sortcxix + PL_sublex_info + PL_timesbuf + main + Perl_ErrorNo + Perl_GetVars + Perl_do_exec3 + Perl_do_ipcctl + Perl_do_ipcget + Perl_do_msgrcv + Perl_do_msgsnd + Perl_do_semop + Perl_do_shmio + Perl_dump_fds + Perl_init_thread_intern + Perl_my_bzero + Perl_my_htonl + Perl_my_ntohl + Perl_my_swap + Perl_my_chsize + Perl_same_dirent + Perl_setenv_getix + Perl_unlnk + Perl_watch + Perl_safexcalloc + Perl_safexmalloc + Perl_safexfree + Perl_safexrealloc + Perl_my_memcmp + Perl_my_memset + PL_cshlen + PL_cshname + PL_opsave + Perl_do_exec + Perl_getenv_len + Perl_my_pclose + Perl_my_popen + )]; +} +elsif ($PLATFORM eq 'aix') { skip_symbols([qw( -Perl_dump_fds -Perl_ErrorNo -Perl_GetVars -Perl_my_bcopy -Perl_my_bzero -Perl_my_chsize -Perl_my_htonl -Perl_my_memcmp -Perl_my_memset -Perl_my_ntohl -Perl_my_swap -Perl_safexcalloc -Perl_safexfree -Perl_safexmalloc -Perl_safexrealloc -Perl_same_dirent -Perl_unlnk -PL_cryptseen -PL_opsave -PL_statusvalue_vms -PL_sys_intern -)]); -} - -if ($PLATFORM eq 'os2') { + Perl_dump_fds + Perl_ErrorNo + Perl_GetVars + Perl_my_bcopy + Perl_my_bzero + Perl_my_chsize + Perl_my_htonl + Perl_my_memcmp + Perl_my_memset + Perl_my_ntohl + Perl_my_swap + Perl_safexcalloc + Perl_safexfree + Perl_safexmalloc + Perl_safexrealloc + Perl_same_dirent + Perl_unlnk + PL_cryptseen + PL_opsave + PL_statusvalue_vms + PL_sys_intern + )]); +} +elsif ($PLATFORM eq 'os2') { emit_symbols([qw( -ctermid -get_sysinfo -Perl_OS2_init -OS2_Perl_data -dlopen -dlsym -dlerror -my_tmpfile -my_tmpnam -my_flock -malloc_mutex -threads_mutex -nthreads -nthreads_cond -os2_cond_wait -os2_stat -pthread_join -pthread_create -pthread_detach -XS_Cwd_change_drive -XS_Cwd_current_drive -XS_Cwd_extLibpath -XS_Cwd_extLibpath_set -XS_Cwd_sys_abspath -XS_Cwd_sys_chdir -XS_Cwd_sys_cwd -XS_Cwd_sys_is_absolute -XS_Cwd_sys_is_relative -XS_Cwd_sys_is_rooted -XS_DynaLoader_mod2fname -XS_File__Copy_syscopy -Perl_Register_MQ -Perl_Deregister_MQ -Perl_Serve_Messages -Perl_Process_Messages -init_PMWIN_entries -PMWIN_entries -Perl_hab_GET -)]); + ctermid + get_sysinfo + Perl_OS2_init + OS2_Perl_data + dlopen + dlsym + dlerror + my_tmpfile + my_tmpnam + my_flock + malloc_mutex + threads_mutex + nthreads + nthreads_cond + os2_cond_wait + os2_stat + pthread_join + pthread_create + pthread_detach + XS_Cwd_change_drive + XS_Cwd_current_drive + XS_Cwd_extLibpath + XS_Cwd_extLibpath_set + XS_Cwd_sys_abspath + XS_Cwd_sys_chdir + XS_Cwd_sys_cwd + XS_Cwd_sys_is_absolute + XS_Cwd_sys_is_relative + XS_Cwd_sys_is_rooted + XS_DynaLoader_mod2fname + XS_File__Copy_syscopy + Perl_Register_MQ + Perl_Deregister_MQ + Perl_Serve_Messages + Perl_Process_Messages + init_PMWIN_entries + PMWIN_entries + Perl_hab_GET + )]); } -if ($define{'PERL_OBJECT'}) { - skip_symbols [qw( - Perl_getenv_len - Perl_my_popen - Perl_my_pclose - )]; +unless ($define{'DEBUGGING'}) { + skip_symbols [qw( + Perl_deb + Perl_deb_growlevel + Perl_debop + Perl_debprofdump + Perl_debstack + Perl_debstackptrs + Perl_runops_debug + Perl_sv_peek + PL_block_type + PL_watchaddr + PL_watchok + )]; +} + +if ($define{'PERL_IMPLICIT_SYS'}) { + skip_symbols [qw( + Perl_getenv_len + Perl_my_popen + Perl_my_pclose + )]; +} +else { + skip_symbols [qw( + PL_Mem + PL_MemShared + PL_MemParse + PL_Env + PL_StdIO + PL_LIO + PL_Dir + PL_Sock + PL_Proc + )]; +} + +if ($define{'MYMALLOC'}) { + emit_symbols [qw( + Perl_dump_mstats + Perl_malloc + Perl_mfree + Perl_realloc + Perl_calloc + )]; } else { - skip_symbols [qw( - PL_Dir - PL_Env - PL_LIO - PL_Mem - PL_Proc - PL_Sock - PL_StdIO - )]; -} - -if ($define{'MYMALLOC'}) - { - emit_symbols [qw( - Perl_dump_mstats - Perl_malloc - Perl_mfree - Perl_realloc - Perl_calloc)]; - } -else - { - skip_symbols [qw( - Perl_dump_mstats - Perl_malloc - Perl_mfree - Perl_realloc - Perl_calloc - Perl_malloced_size)]; - } - -unless ($define{'USE_THREADS'}) - { - skip_symbols [qw( -PL_thr_key -PL_sv_mutex -PL_strtab_mutex -PL_svref_mutex -PL_malloc_mutex -PL_cred_mutex -PL_eval_mutex -PL_eval_cond -PL_eval_owner -PL_threads_mutex -PL_nthreads -PL_nthreads_cond -PL_threadnum -PL_threadsv_names -PL_thrsv -PL_vtbl_mutex -Perl_getTHR -Perl_setTHR -Perl_condpair_magic -Perl_new_struct_thread -Perl_per_thread_magicals -Perl_thread_create -Perl_find_threadsv -Perl_unlock_condpair -Perl_magic_mutexfree -)]; - } - -unless ($define{'USE_ITHREADS'}) - { - skip_symbols [qw( -PL_ptr_table -Perl_dirp_dup -Perl_cx_dup -Perl_si_dup -Perl_ss_dup -Perl_fp_dup -Perl_gp_dup -Perl_he_dup -Perl_mg_dup -Perl_re_dup -Perl_sv_dup -Perl_sys_intern_dup -Perl_ptr_table_fetch -Perl_ptr_table_new -Perl_ptr_table_split -Perl_ptr_table_store -perl_clone -perl_clone_using -)]; - } - -unless ($define{'USE_THREADS'} or $define{'PERL_IMPLICIT_CONTEXT'} - or $define{'PERL_OBJECT'}) -{ - skip_symbols [qw( - Perl_croak_nocontext - Perl_die_nocontext - Perl_deb_nocontext - Perl_form_nocontext - Perl_mess_nocontext - Perl_warn_nocontext - Perl_warner_nocontext - Perl_newSVpvf_nocontext - Perl_sv_catpvf_nocontext - Perl_sv_setpvf_nocontext - Perl_sv_catpvf_mg_nocontext - Perl_sv_setpvf_mg_nocontext - )]; - } - -unless ($define{'FAKE_THREADS'}) - { - skip_symbols [qw(PL_curthr)]; - } - -sub readvar -{ - my $file = shift; - my $proc = shift || sub { "PL_$_[2]" }; - open(VARS,$file) || die "Cannot open $file: $!\n"; - my @syms; - while () - { - # All symbols have a Perl_ prefix because that's what embed.h - # sticks in front of them. - push(@syms, &$proc($1,$2,$3)) if (/\bPERLVAR(A?I?C?)\(([IGT])(\w+)/); - } - close(VARS); - return \@syms; -} - -if ($define{'USE_THREADS'} || $define{'MULTIPLICITY'}) - { - my $thrd = readvar($thrdvar_h); - skip_symbols $thrd; - } - -if ($define{'MULTIPLICITY'}) - { - my $interp = readvar($intrpvar_h); - skip_symbols $interp; - } - -if ($define{'PERL_GLOBAL_STRUCT'}) - { - my $global = readvar($perlvars_h); - skip_symbols $global; - emit_symbol('Perl_GetVars'); - emit_symbols [qw(PL_Vars PL_VarsPtr)] unless $CCTYPE eq 'GCC'; - } - -unless ($define{'DEBUGGING'}) - { - skip_symbols [qw( - Perl_deb - Perl_deb_growlevel - Perl_debop - Perl_debprofdump - Perl_debstack - Perl_debstackptrs - Perl_runops_debug - Perl_sv_peek - PL_block_type - PL_watchaddr - PL_watchok)]; - } + skip_symbols [qw( + PL_malloc_mutex + Perl_dump_mstats + Perl_malloc + Perl_mfree + Perl_realloc + Perl_calloc + Perl_malloced_size + )]; +} + +unless ($define{'USE_THREADS'}) { + skip_symbols [qw( + PL_thr_key + PL_sv_mutex + PL_strtab_mutex + PL_svref_mutex + PL_malloc_mutex + PL_cred_mutex + PL_eval_mutex + PL_eval_cond + PL_eval_owner + PL_threads_mutex + PL_nthreads + PL_nthreads_cond + PL_threadnum + PL_threadsv_names + PL_thrsv + PL_vtbl_mutex + Perl_getTHR + Perl_setTHR + Perl_condpair_magic + Perl_new_struct_thread + Perl_per_thread_magicals + Perl_thread_create + Perl_find_threadsv + Perl_unlock_condpair + Perl_magic_mutexfree + )]; +} + +unless ($define{'USE_ITHREADS'}) { + skip_symbols [qw( + PL_ptr_table + Perl_dirp_dup + Perl_cx_dup + Perl_si_dup + Perl_any_dup + Perl_ss_dup + Perl_fp_dup + Perl_gp_dup + Perl_he_dup + Perl_mg_dup + Perl_re_dup + Perl_sv_dup + Perl_sys_intern_dup + Perl_ptr_table_fetch + Perl_ptr_table_new + Perl_ptr_table_split + Perl_ptr_table_store + perl_clone + perl_clone_using + )]; +} + +unless ($define{'PERL_IMPLICIT_CONTEXT'}) { + skip_symbols [qw( + Perl_croak_nocontext + Perl_die_nocontext + Perl_deb_nocontext + Perl_form_nocontext + Perl_mess_nocontext + Perl_warn_nocontext + Perl_warner_nocontext + Perl_newSVpvf_nocontext + Perl_sv_catpvf_nocontext + Perl_sv_setpvf_nocontext + Perl_sv_catpvf_mg_nocontext + Perl_sv_setpvf_mg_nocontext + )]; +} + +unless ($define{'PERL_IMPLICIT_SYS'}) { + skip_symbols [qw( + perl_alloc_using + )]; +} + +unless ($define{'FAKE_THREADS'}) { + skip_symbols [qw(PL_curthr)]; +} + +sub readvar { + my $file = shift; + my $proc = shift || sub { "PL_$_[2]" }; + open(VARS,$file) || die "Cannot open $file: $!\n"; + my @syms; + while () { + # All symbols have a Perl_ prefix because that's what embed.h + # sticks in front of them. + push(@syms, &$proc($1,$2,$3)) if (/\bPERLVAR(A?I?C?)\(([IGT])(\w+)/); + } + close(VARS); + return \@syms; +} + +if ($define{'USE_THREADS'} || $define{'MULTIPLICITY'}) { + my $thrd = readvar($thrdvar_h); + skip_symbols $thrd; +} + +if ($define{'MULTIPLICITY'}) { + my $interp = readvar($intrpvar_h); + skip_symbols $interp; +} + +if ($define{'PERL_GLOBAL_STRUCT'}) { + my $global = readvar($perlvars_h); + skip_symbols $global; + emit_symbol('Perl_GetVars'); + emit_symbols [qw(PL_Vars PL_VarsPtr)] unless $CCTYPE eq 'GCC'; +} # functions from *.sym files my @syms = ($global_sym, $pp_sym, $globvar_sym); -if ($define{'USE_PERLIO'}) - { +if ($define{'USE_PERLIO'}) { push @syms, $perlio_sym; - } - -for my $syms (@syms) - { - open (GLOBAL, "<$syms") || die "failed to open $syms: $!\n"; - while () - { - next if (!/^[A-Za-z]/); - # Functions have a Perl_ prefix - # Variables have a PL_ prefix - chomp($_); - my $symbol = ($syms =~ /var\.sym$/i ? "PL_" : ""); - $symbol .= $_; - emit_symbol($symbol) unless exists $skip{$symbol}; - } - close(GLOBAL); - } +} + +for my $syms (@syms) { + open (GLOBAL, "<$syms") || die "failed to open $syms: $!\n"; + while () { + next if (!/^[A-Za-z]/); + # Functions have a Perl_ prefix + # Variables have a PL_ prefix + chomp($_); + my $symbol = ($syms =~ /var\.sym$/i ? "PL_" : ""); + $symbol .= $_; + emit_symbol($symbol) unless exists $skip{$symbol}; + } + close(GLOBAL); +} # variables @@ -506,7 +502,6 @@ else { my $glob = readvar($intrpvar_h); emit_symbols $glob; } - unless ($define{'MULTIPLICITY'} || $define{'USE_THREADS'}) { my $glob = readvar($thrdvar_h); emit_symbols $glob; @@ -530,178 +525,184 @@ while () { if ($PLATFORM eq 'win32') { foreach my $symbol (qw( -boot_DynaLoader -Perl_getTHR -Perl_init_os_extras -Perl_setTHR -Perl_thread_create -Perl_win32_init -RunPerl -GetPerlInterpreter -SetPerlInterpreter -win32_errno -win32_environ -win32_stdin -win32_stdout -win32_stderr -win32_ferror -win32_feof -win32_strerror -win32_fprintf -win32_printf -win32_vfprintf -win32_vprintf -win32_fread -win32_fwrite -win32_fopen -win32_fdopen -win32_freopen -win32_fclose -win32_fputs -win32_fputc -win32_ungetc -win32_getc -win32_fileno -win32_clearerr -win32_fflush -win32_ftell -win32_fseek -win32_fgetpos -win32_fsetpos -win32_rewind -win32_tmpfile -win32_abort -win32_fstat -win32_stat -win32_pipe -win32_popen -win32_pclose -win32_rename -win32_setmode -win32_lseek -win32_tell -win32_dup -win32_dup2 -win32_open -win32_close -win32_eof -win32_read -win32_write -win32_spawnvp -win32_mkdir -win32_rmdir -win32_chdir -win32_flock -win32_execv -win32_execvp -win32_htons -win32_ntohs -win32_htonl -win32_ntohl -win32_inet_addr -win32_inet_ntoa -win32_socket -win32_bind -win32_listen -win32_accept -win32_connect -win32_send -win32_sendto -win32_recv -win32_recvfrom -win32_shutdown -win32_closesocket -win32_ioctlsocket -win32_setsockopt -win32_getsockopt -win32_getpeername -win32_getsockname -win32_gethostname -win32_gethostbyname -win32_gethostbyaddr -win32_getprotobyname -win32_getprotobynumber -win32_getservbyname -win32_getservbyport -win32_select -win32_endhostent -win32_endnetent -win32_endprotoent -win32_endservent -win32_getnetent -win32_getnetbyname -win32_getnetbyaddr -win32_getprotoent -win32_getservent -win32_sethostent -win32_setnetent -win32_setprotoent -win32_setservent -win32_getenv -win32_putenv -win32_perror -win32_setbuf -win32_setvbuf -win32_flushall -win32_fcloseall -win32_fgets -win32_gets -win32_fgetc -win32_putc -win32_puts -win32_getchar -win32_putchar -win32_malloc -win32_calloc -win32_realloc -win32_free -win32_sleep -win32_times -win32_alarm -win32_open_osfhandle -win32_get_osfhandle -win32_ioctl -win32_utime -win32_uname -win32_wait -win32_waitpid -win32_kill -win32_str_os_error -win32_opendir -win32_readdir -win32_telldir -win32_seekdir -win32_rewinddir -win32_closedir -win32_longpath -win32_os_id -win32_crypt - )) { + boot_DynaLoader + Perl_getTHR + Perl_init_os_extras + Perl_setTHR + Perl_thread_create + Perl_win32_init + RunPerl + GetPerlInterpreter + SetPerlInterpreter + win32_errno + win32_environ + win32_stdin + win32_stdout + win32_stderr + win32_ferror + win32_feof + win32_strerror + win32_fprintf + win32_printf + win32_vfprintf + win32_vprintf + win32_fread + win32_fwrite + win32_fopen + win32_fdopen + win32_freopen + win32_fclose + win32_fputs + win32_fputc + win32_ungetc + win32_getc + win32_fileno + win32_clearerr + win32_fflush + win32_ftell + win32_fseek + win32_fgetpos + win32_fsetpos + win32_rewind + win32_tmpfile + win32_abort + win32_fstat + win32_stat + win32_pipe + win32_popen + win32_pclose + win32_rename + win32_setmode + win32_lseek + win32_tell + win32_dup + win32_dup2 + win32_open + win32_close + win32_eof + win32_read + win32_write + win32_spawnvp + win32_mkdir + win32_rmdir + win32_chdir + win32_flock + win32_execv + win32_execvp + win32_htons + win32_ntohs + win32_htonl + win32_ntohl + win32_inet_addr + win32_inet_ntoa + win32_socket + win32_bind + win32_listen + win32_accept + win32_connect + win32_send + win32_sendto + win32_recv + win32_recvfrom + win32_shutdown + win32_closesocket + win32_ioctlsocket + win32_setsockopt + win32_getsockopt + win32_getpeername + win32_getsockname + win32_gethostname + win32_gethostbyname + win32_gethostbyaddr + win32_getprotobyname + win32_getprotobynumber + win32_getservbyname + win32_getservbyport + win32_select + win32_endhostent + win32_endnetent + win32_endprotoent + win32_endservent + win32_getnetent + win32_getnetbyname + win32_getnetbyaddr + win32_getprotoent + win32_getservent + win32_sethostent + win32_setnetent + win32_setprotoent + win32_setservent + win32_getenv + win32_putenv + win32_perror + win32_setbuf + win32_setvbuf + win32_flushall + win32_fcloseall + win32_fgets + win32_gets + win32_fgetc + win32_putc + win32_puts + win32_getchar + win32_putchar + win32_malloc + win32_calloc + win32_realloc + win32_free + win32_sleep + win32_times + win32_access + win32_alarm + win32_chmod + win32_open_osfhandle + win32_get_osfhandle + win32_ioctl + win32_link + win32_unlink + win32_utime + win32_uname + win32_wait + win32_waitpid + win32_kill + win32_str_os_error + win32_opendir + win32_readdir + win32_telldir + win32_seekdir + win32_rewinddir + win32_closedir + win32_longpath + win32_os_id + win32_getpid + win32_crypt + win32_dynaload + )) + { try_symbol($symbol); } } elsif ($PLATFORM eq 'os2') { - open MAP, 'miniperl.map' or die 'Cannot read miniperl.map'; - /^\s*[\da-f:]+\s+(\w+)/i and $mapped{$1}++ foreach ; - close MAP or die 'Cannot close miniperl.map'; - - @missing = grep { !exists $mapped{$_} and !exists $bincompat5005{$_} } - keys %export; - delete $export{$_} foreach @missing; + open MAP, 'miniperl.map' or die 'Cannot read miniperl.map'; + /^\s*[\da-f:]+\s+(\w+)/i and $mapped{$1}++ foreach ; + close MAP or die 'Cannot close miniperl.map'; + + @missing = grep { !exists $mapped{$_} and !exists $bincompat5005{$_} } + keys %export; + delete $export{$_} foreach @missing; } # Now all symbols should be defined because # next we are going to output them. -foreach my $symbol (sort keys %export) - { - output_symbol($symbol); - } +foreach my $symbol (sort keys %export) { + output_symbol($symbol); +} sub emit_symbol { - my $symbol = shift; - chomp($symbol); - $export{$symbol} = 1; + my $symbol = shift; + chomp($symbol); + $export{$symbol} = 1; } sub output_symbol { @@ -732,9 +733,11 @@ sub output_symbol { # print "\t$symbol\n"; # print "\t_$symbol = $symbol\n"; # } - } elsif ($PLATFORM eq 'os2') { + } + elsif ($PLATFORM eq 'os2') { print qq( "$symbol"\n); - } elsif ($PLATFORM eq 'aix') { + } + elsif ($PLATFORM eq 'aix') { print "$symbol\n"; } } @@ -743,6 +746,7 @@ sub output_symbol { __DATA__ # extra globals not included above. perl_alloc +perl_alloc_using perl_construct perl_destruct perl_free diff --git a/mg.c b/mg.c index fdaf3bb..2b35677 100644 --- a/mg.c +++ b/mg.c @@ -818,7 +818,10 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg) #if defined(VMS) Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system"); #else -# ifdef WIN32 +# ifdef PERL_IMPLICIT_SYS + PerlEnv_clearenv(); +# else +# ifdef WIN32 char *envv = GetEnvironmentStrings(); char *cur = envv; STRLEN len; @@ -834,13 +837,13 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg) cur += len+1; } FreeEnvironmentStrings(envv); -# else -# ifdef CYGWIN +# else +# ifdef CYGWIN I32 i; for (i = 0; environ[i]; i++) Safefree(environ[i]); -# else -# ifndef PERL_USE_SAFE_PUTENV +# else +# ifndef PERL_USE_SAFE_PUTENV I32 i; if (environ == PL_origenviron) @@ -848,12 +851,13 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg) else for (i = 0; environ[i]; i++) safesysfree(environ[i]); -# endif /* PERL_USE_SAFE_PUTENV */ -# endif /* CYGWIN */ +# endif /* PERL_USE_SAFE_PUTENV */ +# endif /* CYGWIN */ environ[0] = Nullch; -# endif /* WIN32 */ +# endif /* WIN32 */ +# endif /* PERL_IMPLICIT_SYS */ #endif /* VMS */ return 0; } @@ -1178,7 +1182,7 @@ Perl_magic_setdbline(pTHX_ SV *sv, MAGIC *mg) i = SvTRUE(sv); svp = av_fetch(GvAV(gv), atoi(MgPV(mg,n_a)), FALSE); - if (svp && SvIOKp(*svp) && (o = (OP*)SvSTASH(*svp))) + if (svp && SvIOKp(*svp) && (o = (OP*)SvIVX(*svp))) o->op_private = i; else if (ckWARN_d(WARN_INTERNAL)) Perl_warner(aTHX_ WARN_INTERNAL, "Can't break at that line\n"); @@ -1660,7 +1664,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) case '.': if (PL_localizing) { if (PL_localizing == 1) - save_sptr((SV**)&PL_last_in_gv); + SAVESPTR(PL_last_in_gv); } else if (SvOK(sv) && GvIO(PL_last_in_gv)) IoLINES(GvIOp(PL_last_in_gv)) = (long)SvIV(sv); diff --git a/mpeix/mpeixish.h b/mpeix/mpeixish.h index 2311171..b5e4fa4 100644 --- a/mpeix/mpeixish.h +++ b/mpeix/mpeixish.h @@ -97,7 +97,7 @@ #ifndef SIGILL # define SIGILL 6 /* blech */ #endif -#define ABORT() kill(getpid(),SIGABRT); +#define ABORT() kill(PerlProc_getpid(),SIGABRT); /* * fwrite1() should be a routine with the same calling sequence as fwrite(), diff --git a/objXSUB.h b/objXSUB.h index e8b1ffb..0884936 100644 --- a/objXSUB.h +++ b/objXSUB.h @@ -34,6 +34,10 @@ #define PL_LIO (*Perl_ILIO_ptr(aTHXo)) #undef PL_Mem #define PL_Mem (*Perl_IMem_ptr(aTHXo)) +#undef PL_MemParse +#define PL_MemParse (*Perl_IMemParse_ptr(aTHXo)) +#undef PL_MemShared +#define PL_MemShared (*Perl_IMemShared_ptr(aTHXo)) #undef PL_Proc #define PL_Proc (*Perl_IProc_ptr(aTHXo)) #undef PL_Sock @@ -366,6 +370,10 @@ #define PL_preprocess (*Perl_Ipreprocess_ptr(aTHXo)) #undef PL_profiledata #define PL_profiledata (*Perl_Iprofiledata_ptr(aTHXo)) +#undef PL_psig_name +#define PL_psig_name (*Perl_Ipsig_name_ptr(aTHXo)) +#undef PL_psig_ptr +#define PL_psig_ptr (*Perl_Ipsig_ptr_ptr(aTHXo)) #undef PL_ptr_table #define PL_ptr_table (*Perl_Iptr_table_ptr(aTHXo)) #undef PL_replgv @@ -809,7 +817,17 @@ /* XXX soon to be eliminated, only a few things in PERLCORE need these now */ +#if defined(PERL_IMPLICIT_SYS) +#else +#endif +#if defined(USE_ITHREADS) +#endif +#if defined(MYMALLOC) +#endif +#if defined(PERL_OBJECT) +#endif #if defined(PERL_OBJECT) +#else #endif #undef Perl_amagic_call #define Perl_amagic_call pPerl->Perl_amagic_call @@ -1983,12 +2001,6 @@ #define Perl_magicname pPerl->Perl_magicname #undef magicname #define magicname Perl_magicname -#if defined(MYMALLOC) -#undef Perl_malloced_size -#define Perl_malloced_size pPerl->Perl_malloced_size -#undef malloced_size -#define malloced_size Perl_malloced_size -#endif #undef Perl_markstack_grow #define Perl_markstack_grow pPerl->Perl_markstack_grow #undef markstack_grow @@ -2404,36 +2416,23 @@ #undef peep #define peep Perl_peep #if defined(PERL_OBJECT) -#undef perl_construct -#define perl_construct pPerl->perl_construct -#undef perl_destruct -#define perl_destruct pPerl->perl_destruct -#undef perl_free -#define perl_free pPerl->perl_free -#undef perl_run -#define perl_run pPerl->perl_run -#undef perl_parse -#define perl_parse pPerl->perl_parse -#else -#undef perl_alloc -#define perl_alloc pPerl->perl_alloc -#undef perl_construct -#define perl_construct pPerl->perl_construct -#undef perl_destruct -#define perl_destruct pPerl->perl_destruct -#undef perl_free -#define perl_free pPerl->perl_free -#undef perl_run -#define perl_run pPerl->perl_run -#undef perl_parse -#define perl_parse pPerl->perl_parse +#undef Perl_construct +#define Perl_construct pPerl->Perl_construct +#undef Perl_destruct +#define Perl_destruct pPerl->Perl_destruct +#undef Perl_free +#define Perl_free pPerl->Perl_free +#undef Perl_run +#define Perl_run pPerl->Perl_run +#undef Perl_parse +#define Perl_parse pPerl->Perl_parse +#endif #if defined(USE_THREADS) #undef Perl_new_struct_thread #define Perl_new_struct_thread pPerl->Perl_new_struct_thread #undef new_struct_thread #define new_struct_thread Perl_new_struct_thread #endif -#endif #undef Perl_call_atexit #define Perl_call_atexit pPerl->Perl_call_atexit #undef call_atexit @@ -2760,6 +2759,10 @@ #define Perl_save_pptr pPerl->Perl_save_pptr #undef save_pptr #define save_pptr Perl_save_pptr +#undef Perl_save_vptr +#define Perl_save_vptr pPerl->Perl_save_vptr +#undef save_vptr +#define save_vptr Perl_save_vptr #undef Perl_save_re_context #define Perl_save_re_context pPerl->Perl_save_re_context #undef save_re_context @@ -3304,22 +3307,6 @@ #define Perl_dump_mstats pPerl->Perl_dump_mstats #undef dump_mstats #define dump_mstats Perl_dump_mstats -#undef Perl_malloc -#define Perl_malloc pPerl->Perl_malloc -#undef malloc -#define malloc Perl_malloc -#undef Perl_calloc -#define Perl_calloc pPerl->Perl_calloc -#undef calloc -#define calloc Perl_calloc -#undef Perl_realloc -#define Perl_realloc pPerl->Perl_realloc -#undef realloc -#define realloc Perl_realloc -#undef Perl_mfree -#define Perl_mfree pPerl->Perl_mfree -#undef mfree -#define mfree Perl_mfree #endif #undef Perl_safesysmalloc #define Perl_safesysmalloc pPerl->Perl_safesysmalloc @@ -3546,6 +3533,10 @@ #define Perl_ss_dup pPerl->Perl_ss_dup #undef ss_dup #define ss_dup Perl_ss_dup +#undef Perl_any_dup +#define Perl_any_dup pPerl->Perl_any_dup +#undef any_dup +#define any_dup Perl_any_dup #undef Perl_he_dup #define Perl_he_dup pPerl->Perl_he_dup #undef he_dup @@ -3596,12 +3587,9 @@ #define Perl_ptr_table_split pPerl->Perl_ptr_table_split #undef ptr_table_split #define ptr_table_split Perl_ptr_table_split -#undef perl_clone -#define perl_clone pPerl->perl_clone -#undef perl_clone_using -#define perl_clone_using pPerl->perl_clone_using #endif #if defined(PERL_OBJECT) +#else #endif #if defined(PERL_IN_AV_C) || defined(PERL_DECL_PROT) #endif @@ -3660,6 +3648,8 @@ # if defined(LEAKTEST) # endif #endif +#if defined(PERL_OBJECT) +#endif #undef Perl_ck_anoncode #define Perl_ck_anoncode pPerl->Perl_ck_anoncode #undef ck_anoncode diff --git a/op.c b/op.c index 73c9634..7824c22 100644 --- a/op.c +++ b/op.c @@ -105,7 +105,7 @@ S_no_bareword_allowed(pTHX_ OP *o) { qerror(Perl_mess(aTHX_ "Bareword \"%s\" not allowed while \"strict subs\" in use", - SvPV_nolen(cSVOPo->op_sv))); + SvPV_nolen(cSVOPo_sv))); } /* "register" allocation */ @@ -319,6 +319,7 @@ S_pad_findlex(pTHX_ char *name, PADOFFSET newoff, U32 seq, CV* startcv, return 0; } break; + case CXt_FORMAT: case CXt_SUB: if (!saweval) return 0; @@ -498,7 +499,7 @@ Perl_pad_free(pTHX_ PADOFFSET po) Perl_croak(aTHX_ "panic: pad_free po"); #ifdef USE_THREADS DEBUG_X(PerlIO_printf(Perl_debug_log, - "0x%"UVxf" Pad 0x%"UVxf" free %"IVd"\n", + "0x%"UVxf" Pad 0x%"UVxf" free %"IVdf"\n", PTR2UV(thr), PTR2UV(PL_curpad), (IV)po)); #else DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%"UVxf" free %"IVdf"\n", @@ -1069,7 +1070,7 @@ Perl_scalarvoid(pTHX_ OP *o) break; case OP_CONST: - sv = cSVOPo->op_sv; + sv = cSVOPo_sv; if (cSVOPo->op_private & OPpCONST_STRICT) no_bareword_allowed(o); else { @@ -1299,7 +1300,7 @@ Perl_mod(pTHX_ OP *o, I32 type) if (!(o->op_private & (OPpCONST_ARYBASE))) goto nomod; if (PL_eval_start && PL_eval_start->op_type == OP_CONST) { - PL_compiling.cop_arybase = (I32)SvIV(((SVOP*)PL_eval_start)->op_sv); + PL_compiling.cop_arybase = (I32)SvIV(cSVOPx(PL_eval_start)->op_sv); PL_eval_start = 0; } else if (!type) { @@ -1979,7 +1980,7 @@ Perl_block_start(pTHX_ int full) PL_pad_reset_pending = FALSE; SAVEHINTS(); PL_hints &= ~HINT_BLOCK_SCOPE; - SAVEPPTR(PL_compiling.cop_warnings); + SAVESPTR(PL_compiling.cop_warnings); if (! specialWARN(PL_compiling.cop_warnings)) { PL_compiling.cop_warnings = newSVsv(PL_compiling.cop_warnings) ; SAVEFREESV(PL_compiling.cop_warnings) ; @@ -2948,7 +2949,9 @@ Perl_newPADOP(pTHX_ I32 type, I32 flags, SV *sv) padop->op_type = type; padop->op_ppaddr = PL_ppaddr[type]; padop->op_padix = pad_alloc(type, SVs_PADTMP); + SvREFCNT_dec(PL_curpad[padop->op_padix]); PL_curpad[padop->op_padix] = sv; + SvPADTMP_on(sv); padop->op_next = (OP*)padop; padop->op_flags = flags; if (PL_opargs[type] & OA_RETSCALAR) @@ -3362,13 +3365,7 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o) SV **svp = av_fetch(CopFILEAV(PL_curcop), (I32)CopLINE(cop), FALSE); if (svp && *svp != &PL_sv_undef && !SvIOK(*svp)) { (void)SvIOK_on(*svp); - SvIVX(*svp) = 1; -#ifndef USE_ITHREADS - /* XXX This nameless kludge interferes with cloning SVs. :-( - * What's more, it seems entirely redundant when considering - * PL_DBsingle exists to do the same thing */ - SvSTASH(*svp) = (HV*)cop; -#endif + SvIVX(*svp) = (IV)cop; } } @@ -3907,7 +3904,7 @@ Perl_cv_undef(pTHX_ CV *cv) #endif /* USE_THREADS */ ENTER; - SAVESPTR(PL_curpad); + SAVEVPTR(PL_curpad); PL_curpad = 0; if (!CvCLONED(cv)) @@ -4010,7 +4007,7 @@ S_cv_clone2(pTHX_ CV *proto, CV *outside) assert(!CvUNIQUE(proto)); ENTER; - SAVESPTR(PL_curpad); + SAVEVPTR(PL_curpad); SAVESPTR(PL_comppad); SAVESPTR(PL_comppad_name); SAVESPTR(PL_compcv); @@ -4085,7 +4082,7 @@ S_cv_clone2(pTHX_ CV *proto, CV *outside) PL_curpad[ix] = sv; } } - else if (IS_PADGV(ppad[ix])) { + else if (IS_PADGV(ppad[ix]) || IS_PADCONST(ppad[ix])) { PL_curpad[ix] = SvREFCNT_inc(ppad[ix]); } else { @@ -4191,9 +4188,9 @@ Perl_op_const_sv(pTHX_ OP *o, CV *cv) break; if (sv) return Nullsv; - if (type == OP_CONST) + if (type == OP_CONST && cSVOPo->op_sv) sv = cSVOPo->op_sv; - else if (type == OP_PADSV && cv) { + else if ((type == OP_PADSV || type == OP_CONST) && cv) { AV* padav = (AV*)(AvARRAY(CvPADLIST(cv))[1]); sv = padav ? AvARRAY(padav)[o->op_targ] : Nullsv; if (!sv || (!SvREADONLY(sv) && SvREFCNT(sv) > 1)) @@ -4397,12 +4394,25 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) if (AvFILLp(PL_comppad_name) < AvFILLp(PL_comppad)) av_store(PL_comppad_name, AvFILLp(PL_comppad), Nullsv); + if (CvLVALUE(cv)) { + CvROOT(cv) = newUNOP(OP_LEAVESUBLV, 0, scalarseq(block)); + } + else { + CvROOT(cv) = newUNOP(OP_LEAVESUB, 0, scalarseq(block)); + } + CvROOT(cv)->op_private |= OPpREFCOUNTED; + OpREFCNT_set(CvROOT(cv), 1); + CvSTART(cv) = LINKLIST(CvROOT(cv)); + CvROOT(cv)->op_next = 0; + peep(CvSTART(cv)); + + /* now that optimizer has done its work, adjust pad values */ if (CvCLONE(cv)) { SV **namep = AvARRAY(PL_comppad_name); for (ix = AvFILLp(PL_comppad); ix > 0; ix--) { SV *namesv; - if (SvIMMORTAL(PL_curpad[ix]) || IS_PADGV(PL_curpad[ix])) + if (SvIMMORTAL(PL_curpad[ix]) || IS_PADGV(PL_curpad[ix]) || IS_PADCONST(PL_curpad[ix])) continue; /* * The only things that a clonable function needs in its @@ -4426,25 +4436,13 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) AvFLAGS(av) = AVf_REIFY; for (ix = AvFILLp(PL_comppad); ix > 0; ix--) { - if (SvIMMORTAL(PL_curpad[ix]) || IS_PADGV(PL_curpad[ix])) + if (SvIMMORTAL(PL_curpad[ix]) || IS_PADGV(PL_curpad[ix]) || IS_PADCONST(PL_curpad[ix])) continue; if (!SvPADMY(PL_curpad[ix])) SvPADTMP_on(PL_curpad[ix]); } } - if (CvLVALUE(cv)) { - CvROOT(cv) = newUNOP(OP_LEAVESUBLV, 0, scalarseq(block)); - } - else { - CvROOT(cv) = newUNOP(OP_LEAVESUB, 0, scalarseq(block)); - } - CvROOT(cv)->op_private |= OPpREFCOUNTED; - OpREFCNT_set(CvROOT(cv), 1); - CvSTART(cv) = LINKLIST(CvROOT(cv)); - CvROOT(cv)->op_next = 0; - peep(CvSTART(cv)); - if (name) { char *s; @@ -6140,7 +6138,7 @@ Perl_peep(pTHX_ register OP *o) return; ENTER; SAVEOP(); - SAVESPTR(PL_curcop); + SAVEVPTR(PL_curcop); for (; o; o = o->op_next) { if (o->op_seq) break; @@ -6159,6 +6157,19 @@ Perl_peep(pTHX_ register OP *o) case OP_CONST: if (cSVOPo->op_private & OPpCONST_STRICT) no_bareword_allowed(o); +#ifdef USE_ITHREADS + /* Relocate sv to the pad for thread safety. + * Despite being a "constant", the SV is written to, + * for reference counts, sv_upgrade() etc. */ + if (cSVOP->op_sv) { + PADOFFSET ix = pad_alloc(OP_CONST, SVs_PADTMP); + SvREFCNT_dec(PL_curpad[ix]); + SvPADTMP_on(cSVOPo->op_sv); + PL_curpad[ix] = cSVOPo->op_sv; + cSVOPo->op_sv = Nullsv; + o->op_targ = ix; + } +#endif /* FALL THROUGH */ case OP_UC: case OP_UCFIRST: @@ -6337,7 +6348,7 @@ Perl_peep(pTHX_ register OP *o) fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE); if (!fields || !GvHV(*fields)) break; - svp = &((SVOP*)((BINOP*)o)->op_last)->op_sv; + svp = &cSVOPx_sv(((BINOP*)o)->op_last); key = SvPV(*svp, keylen); indsvp = hv_fetch(GvHV(*fields), key, keylen, FALSE); if (!indsvp) { diff --git a/op.h b/op.h index 95ecf87..454cbf7 100644 --- a/op.h +++ b/op.h @@ -313,6 +313,9 @@ struct loop { # define cGVOPo_set(v) (PL_curpad[cPADOPo->op_padix] = (SV*)(v)) # define kGVOP_set(v) (PL_curpad[kPADOP->op_padix] = (SV*)(v)) # define IS_PADGV(v) (v && SvTYPE(v) == SVt_PVGV && GvIN_PAD(v)) +# define IS_PADCONST(v) (v && SvREADONLY(v)) +# define cSVOPx_sv(v) (cSVOPx(v)->op_sv \ + ? cSVOPx(v)->op_sv : PL_curpad[(v)->op_targ]) #else # define cGVOPx(o) ((GV*)cSVOPx(o)->op_sv) # define cGVOP ((GV*)cSVOP->op_sv) @@ -322,8 +325,14 @@ struct loop { # define cGVOPo_set(v) (cPADOPo->op_sv = (SV*)(v)) # define kGVOP_set(v) (kPADOP->op_sv = (SV*)(v)) # define IS_PADGV(v) FALSE +# define IS_PADCONST(v) FALSE +# define cSVOPx_sv(v) (cSVOPx(v)->op_sv) #endif +#define cSVOP_sv cSVOPx_sv(PL_op) +#define cSVOPo_sv cSVOPx_sv(o) +#define kSVOP_sv cSVOPx_sv(kid) + #define Nullop Null(OP*) /* Lowest byte of PL_opargs */ diff --git a/os2/os2ish.h b/os2/os2ish.h index 3d7a6fd..f254b5c 100644 --- a/os2/os2ish.h +++ b/os2/os2ish.h @@ -64,7 +64,7 @@ #ifndef SIGILL # define SIGILL 6 /* blech */ #endif -#define ABORT() kill(getpid(),SIGABRT); +#define ABORT() kill(PerlProc_getpid(),SIGABRT); #define BIT_BUCKET "/dev/nul" /* Will this work? */ diff --git a/perl.c b/perl.c index 9f3a8ae..0fb2f35 100644 --- a/perl.c +++ b/perl.c @@ -47,40 +47,42 @@ static I32 read_e_script(pTHXo_ int idx, SV *buf_sv, int maxlen); #endif #ifdef PERL_OBJECT -CPerlObj* -perl_alloc(struct IPerlMem* ipM, struct IPerlEnv* ipE, - struct IPerlStdIO* ipStd, struct IPerlLIO* ipLIO, - struct IPerlDir* ipD, struct IPerlSock* ipS, - struct IPerlProc* ipP) -{ - CPerlObj* pPerl = new(ipM) CPerlObj(ipM, ipE, ipStd, ipLIO, ipD, ipS, ipP); - if (pPerl != NULL) - pPerl->Init(); - - return pPerl; -} -#else +#define perl_construct Perl_construct +#define perl_parse Perl_parse +#define perl_run Perl_run +#define perl_destruct Perl_destruct +#define perl_free Perl_free +#endif #ifdef PERL_IMPLICIT_SYS PerlInterpreter * -perl_alloc_using(struct IPerlMem* ipM, struct IPerlEnv* ipE, +perl_alloc_using(struct IPerlMem* ipM, struct IPerlMem* ipMS, + struct IPerlMem* ipMP, struct IPerlEnv* ipE, struct IPerlStdIO* ipStd, struct IPerlLIO* ipLIO, struct IPerlDir* ipD, struct IPerlSock* ipS, struct IPerlProc* ipP) { PerlInterpreter *my_perl; - +#ifdef PERL_OBJECT + my_perl = (PerlInterpreter*)new(ipM) CPerlObj(ipM, ipMS, ipMP, ipE, ipStd, + ipLIO, ipD, ipS, ipP); + PERL_SET_INTERP(my_perl); +#else /* New() needs interpreter, so call malloc() instead */ my_perl = (PerlInterpreter*)(*ipM->pMalloc)(ipM, sizeof(PerlInterpreter)); PERL_SET_INTERP(my_perl); Zero(my_perl, 1, PerlInterpreter); PL_Mem = ipM; + PL_MemShared = ipMS; + PL_MemParse = ipMP; PL_Env = ipE; PL_StdIO = ipStd; PL_LIO = ipLIO; PL_Dir = ipD; PL_Sock = ipS; PL_Proc = ipP; +#endif + return my_perl; } #else @@ -95,7 +97,6 @@ perl_alloc(void) return my_perl; } #endif /* PERL_IMPLICIT_SYS */ -#endif /* PERL_OBJECT */ void perl_construct(pTHXx) @@ -235,6 +236,9 @@ perl_destruct(pTHXx) dTHX; #endif /* USE_THREADS */ + /* wait for all pseudo-forked children to finish */ + PERL_WAIT_FOR_CHILDREN; + #ifdef USE_THREADS #ifndef FAKE_THREADS /* Pass 1 on any remaining threads: detach joinables, join zombies */ @@ -2873,7 +2877,7 @@ S_init_postdump_symbols(pTHX_ register int argc, register char **argv, register } TAINT_NOT; if (tmpgv = gv_fetchpv("$",TRUE, SVt_PV)) - sv_setiv(GvSV(tmpgv), (IV)getpid()); + sv_setiv(GvSV(tmpgv), (IV)PerlProc_getpid()); } STATIC void diff --git a/perl.h b/perl.h index 3fe64a8..f0dcf1e 100644 --- a/perl.h +++ b/perl.h @@ -30,22 +30,12 @@ # ifndef PERL_IMPLICIT_CONTEXT # define PERL_IMPLICIT_CONTEXT # endif -# ifndef PERL_IMPLICIT_SYS -# if defined(WIN32) && !defined(__MINGW32__) -# define PERL_IMPLICIT_SYS /* XXX not implemented everywhere yet */ -# endif -# endif #endif #if defined(MULTIPLICITY) # ifndef PERL_IMPLICIT_CONTEXT # define PERL_IMPLICIT_CONTEXT # endif -# ifndef PERL_IMPLICIT_SYS -# if defined(WIN32) && !defined(__MINGW32__) -# define PERL_IMPLICIT_SYS /* XXX not implemented everywhere yet */ -# endif -# endif #endif #ifdef PERL_CAPI @@ -146,7 +136,7 @@ class CPerlObj; #define STATIC #define CPERLscope(x) CPerlObj::x -#define CALL_FPTR(fptr) (this->*fptr) +#define CALL_FPTR(fptr) (aTHXo->*fptr) #define pTHXo CPerlObj *pPerl #define pTHXo_ pTHXo, @@ -1621,6 +1611,10 @@ typedef pthread_key_t perl_key; # endif #endif +#ifndef PERL_WAIT_FOR_CHILDREN +# define PERL_WAIT_FOR_CHILDREN NOOP +#endif + /* the traditional thread-unsafe notion of "current interpreter". * XXX todo: a thread-safe version that fetches it from TLS (akin to THR) * needs to be defined elsewhere (conditional on pthread_getspecific() @@ -2144,13 +2138,9 @@ EXTCONST char PL_uuemap[65] #ifdef DOINIT EXT char *PL_sig_name[] = { SIG_NAME }; EXT int PL_sig_num[] = { SIG_NUM }; -EXT SV * PL_psig_ptr[sizeof(PL_sig_num)/sizeof(*PL_sig_num)]; -EXT SV * PL_psig_name[sizeof(PL_sig_num)/sizeof(*PL_sig_num)]; #else EXT char *PL_sig_name[]; EXT int PL_sig_num[]; -EXT SV * PL_psig_ptr[]; -EXT SV * PL_psig_name[]; #endif /* fast case folding tables */ @@ -2487,44 +2477,25 @@ typedef struct exitlistentry { void *ptr; } PerlExitListEntry; -#ifdef PERL_OBJECT -#undef perl_alloc -#define perl_alloc Perl_alloc -CPerlObj* Perl_alloc (IPerlMem*, IPerlEnv*, IPerlStdIO*, IPerlLIO*, IPerlDir*, IPerlSock*, IPerlProc*); - -#undef EXT -#define EXT -#undef EXTCONST -#define EXTCONST -#undef INIT -#define INIT(x) - -class CPerlObj { -public: - CPerlObj(IPerlMem*, IPerlEnv*, IPerlStdIO*, IPerlLIO*, IPerlDir*, IPerlSock*, IPerlProc*); - void Init(void); - void* operator new(size_t nSize, IPerlMem *pvtbl); - static void operator delete(void* pPerl, IPerlMem *pvtbl); -#endif /* PERL_OBJECT */ - #ifdef PERL_GLOBAL_STRUCT struct perl_vars { -#include "perlvars.h" +# include "perlvars.h" }; -#ifdef PERL_CORE +# ifdef PERL_CORE EXT struct perl_vars PL_Vars; EXT struct perl_vars *PL_VarsPtr INIT(&PL_Vars); -#else /* PERL_CORE */ -#if !defined(__GNUC__) || !defined(WIN32) +# else /* PERL_CORE */ +# if !defined(__GNUC__) || !defined(WIN32) EXT -#endif /* WIN32 */ +# endif /* WIN32 */ struct perl_vars *PL_VarsPtr; -#define PL_Vars (*((PL_VarsPtr) ? PL_VarsPtr : (PL_VarsPtr = Perl_GetVars(aTHX)))) -#endif /* PERL_CORE */ +# define PL_Vars (*((PL_VarsPtr) \ + ? PL_VarsPtr : (PL_VarsPtr = Perl_GetVars(aTHX)))) +# endif /* PERL_CORE */ #endif /* PERL_GLOBAL_STRUCT */ -#ifdef MULTIPLICITY +#if defined(MULTIPLICITY) || defined(PERL_OBJECT) /* If we have multiple interpreters define a struct holding variables which must be per-interpreter If we don't have threads anything that would have @@ -2532,17 +2503,22 @@ struct perl_vars *PL_VarsPtr; */ struct interpreter { -#ifndef USE_THREADS -# include "thrdvar.h" -#endif -#include "intrpvar.h" +# ifndef USE_THREADS +# include "thrdvar.h" +# endif +# include "intrpvar.h" +/* + * The following is a buffer where new variables must + * be defined to maintain binary compatibility with PERL_OBJECT + */ +PERLVARA(object_compatibility,30, char) }; #else struct interpreter { char broiled; }; -#endif +#endif /* MULTIPLICITY || PERL_OBJECT */ #ifdef USE_THREADS /* If we have threads define a struct with all the variables @@ -2583,25 +2559,18 @@ typedef void *Thread; #endif #ifdef PERL_OBJECT -#define PERL_DECL_PROT -#define perl_alloc Perl_alloc +# define PERL_DECL_PROT #endif -#include "proto.h" - #undef PERL_CKDEF #undef PERL_PPDEF #define PERL_CKDEF(s) OP *s (pTHX_ OP *o); #define PERL_PPDEF(s) OP *s (pTHX); -#ifdef PERL_OBJECT -public: -#endif -#include "pp_proto.h" +#include "proto.h" #ifdef PERL_OBJECT -int CPerlObj::do_aspawn (void *vreally, void **vmark, void **vsp); -#undef PERL_DECL_PROT +# undef PERL_DECL_PROT #endif #ifndef PERL_OBJECT @@ -2625,29 +2594,17 @@ int CPerlObj::do_aspawn (void *vreally, void **vmark, void **vsp); #define PERLVARI(var,type,init) EXT type PL_##var INIT(init); #define PERLVARIC(var,type,init) EXTCONST type PL_##var INIT(init); -#ifndef MULTIPLICITY - +#if !defined(MULTIPLICITY) && !defined(PERL_OBJECT) +START_EXTERN_C # include "intrpvar.h" # ifndef USE_THREADS # include "thrdvar.h" # endif - +END_EXTERN_C #endif #ifdef PERL_OBJECT -/* - * The following is a buffer where new variables must - * be defined to maintain binary compatibility with PERL_OBJECT - * for 5.005 - */ -PERLVARA(object_compatibility,30, char) -}; - - # include "embed.h" -# if defined(WIN32) && !defined(WIN32IO_IS_STDIO) -# define errno CPerlObj::ErrorNo() -# endif # ifdef DOINIT # include "INTERN.h" diff --git a/perlapi.c b/perlapi.c index 02795ad..2f902f8 100644 --- a/perlapi.c +++ b/perlapi.c @@ -17,9 +17,9 @@ START_EXTERN_C #undef PERLVARI #undef PERLVARIC #define PERLVAR(v,t) t* Perl_##v##_ptr(pTHXo) \ - { return &(aTHXo->PL_##v); } + { return &(aTHXo->interp.v); } #define PERLVARA(v,n,t) PL_##v##_t* Perl_##v##_ptr(pTHXo) \ - { return &(aTHXo->PL_##v); } + { return &(aTHXo->interp.v); } #define PERLVARI(v,t,i) PERLVAR(v,t) #define PERLVARIC(v,t,i) PERLVAR(v, const t) @@ -39,8 +39,18 @@ START_EXTERN_C #undef PERLVARI #undef PERLVARIC +#if defined(PERL_IMPLICIT_SYS) +#else +#endif +#if defined(USE_ITHREADS) +#endif +#if defined(MYMALLOC) +#endif #if defined(PERL_OBJECT) #endif +#if defined(PERL_OBJECT) +#else +#endif #undef Perl_amagic_call SV* @@ -2150,16 +2160,6 @@ Perl_magicname(pTHXo_ char* sym, char* name, I32 namlen) { ((CPerlObj*)pPerl)->Perl_magicname(sym, name, namlen); } -#if defined(MYMALLOC) - -#undef Perl_malloced_size -MEM_SIZE -Perl_malloced_size(void *p) -{ - dTHXo; - return ((CPerlObj*)pPerl)->Perl_malloced_size(p); -} -#endif #undef Perl_markstack_grow void @@ -2887,15 +2887,42 @@ Perl_peep(pTHXo_ OP* o) ((CPerlObj*)pPerl)->Perl_peep(o); } #if defined(PERL_OBJECT) -#else -#undef perl_alloc -PerlInterpreter* -perl_alloc() +#undef Perl_construct +void +Perl_construct(pTHXo) { - dTHXo; - return ((CPerlObj*)pPerl)->perl_alloc(); + ((CPerlObj*)pPerl)->Perl_construct(); +} + +#undef Perl_destruct +void +Perl_destruct(pTHXo) +{ + ((CPerlObj*)pPerl)->Perl_destruct(); +} + +#undef Perl_free +void +Perl_free(pTHXo) +{ + ((CPerlObj*)pPerl)->Perl_free(); } + +#undef Perl_run +int +Perl_run(pTHXo) +{ + return ((CPerlObj*)pPerl)->Perl_run(); +} + +#undef Perl_parse +int +Perl_parse(pTHXo_ XSINIT_t xsinit, int argc, char** argv, char** env) +{ + return ((CPerlObj*)pPerl)->Perl_parse(xsinit, argc, argv, env); +} +#endif #if defined(USE_THREADS) #undef Perl_new_struct_thread @@ -2905,7 +2932,6 @@ Perl_new_struct_thread(pTHXo_ struct perl_thread *t) return ((CPerlObj*)pPerl)->Perl_new_struct_thread(t); } #endif -#endif #undef Perl_call_atexit void @@ -3476,6 +3502,13 @@ Perl_save_pptr(pTHXo_ char** pptr) ((CPerlObj*)pPerl)->Perl_save_pptr(pptr); } +#undef Perl_save_vptr +void +Perl_save_vptr(pTHXo_ void* pptr) +{ + ((CPerlObj*)pPerl)->Perl_save_vptr(pptr); +} + #undef Perl_save_re_context void Perl_save_re_context(pTHXo) @@ -4431,38 +4464,6 @@ Perl_dump_mstats(pTHXo_ char* s) { ((CPerlObj*)pPerl)->Perl_dump_mstats(s); } - -#undef Perl_malloc -Malloc_t -Perl_malloc(MEM_SIZE nbytes) -{ - dTHXo; - return ((CPerlObj*)pPerl)->Perl_malloc(nbytes); -} - -#undef Perl_calloc -Malloc_t -Perl_calloc(MEM_SIZE elements, MEM_SIZE size) -{ - dTHXo; - return ((CPerlObj*)pPerl)->Perl_calloc(elements, size); -} - -#undef Perl_realloc -Malloc_t -Perl_realloc(Malloc_t where, MEM_SIZE nbytes) -{ - dTHXo; - return ((CPerlObj*)pPerl)->Perl_realloc(where, nbytes); -} - -#undef Perl_mfree -Free_t -Perl_mfree(Malloc_t where) -{ - dTHXo; - ((CPerlObj*)pPerl)->Perl_mfree(where); -} #endif #undef Perl_safesysmalloc @@ -4873,9 +4874,16 @@ Perl_si_dup(pTHXo_ PERL_SI* si) #undef Perl_ss_dup ANY* -Perl_ss_dup(pTHXo_ ANY* ss, I32 ix, I32 max) +Perl_ss_dup(pTHXo_ PerlInterpreter* proto_perl) { - return ((CPerlObj*)pPerl)->Perl_ss_dup(ss, ix, max); + return ((CPerlObj*)pPerl)->Perl_ss_dup(proto_perl); +} + +#undef Perl_any_dup +void* +Perl_any_dup(pTHXo_ void* v, PerlInterpreter* proto_perl) +{ + return ((CPerlObj*)pPerl)->Perl_any_dup(v, proto_perl); } #undef Perl_he_dup @@ -4963,24 +4971,9 @@ Perl_ptr_table_split(pTHXo_ PTR_TBL_t *tbl) { ((CPerlObj*)pPerl)->Perl_ptr_table_split(tbl); } - -#undef perl_clone -PerlInterpreter* -perl_clone(PerlInterpreter* interp, UV flags) -{ - dTHXo; - return ((CPerlObj*)pPerl)->perl_clone(flags); -} - -#undef perl_clone_using -PerlInterpreter* -perl_clone_using(PerlInterpreter *interp, UV flags, struct IPerlMem* m, struct IPerlEnv* e, struct IPerlStdIO* io, struct IPerlLIO* lio, struct IPerlDir* d, struct IPerlSock* s, struct IPerlProc* p) -{ - dTHXo; - return ((CPerlObj*)pPerl)->perl_clone_using(interp, flags, m, e, io, lio, d, s, p); -} #endif #if defined(PERL_OBJECT) +#else #endif #if defined(PERL_IN_AV_C) || defined(PERL_DECL_PROT) #endif @@ -5039,6 +5032,8 @@ perl_clone_using(PerlInterpreter *interp, UV flags, struct IPerlMem* m, struct I # if defined(LEAKTEST) # endif #endif +#if defined(PERL_OBJECT) +#endif #undef Perl_ck_anoncode OP * @@ -7728,7 +7723,7 @@ Perl_fprintf_nocontext(PerlIO *stream, const char *format, ...) dTHXo; va_list(arglist); va_start(arglist, format); - return (*pPerl->PL_StdIO->pVprintf)(pPerl->PL_StdIO, stream, format, arglist); + return (*PL_StdIO->pVprintf)(PL_StdIO, stream, format, arglist); } END_EXTERN_C diff --git a/plan9/plan9ish.h b/plan9/plan9ish.h index 06a30fe..bac6a92 100644 --- a/plan9/plan9ish.h +++ b/plan9/plan9ish.h @@ -103,7 +103,7 @@ #ifndef SIGILL # define SIGILL 6 /* blech */ #endif -#define ABORT() kill(getpid(),SIGABRT); +#define ABORT() kill(PerlProc_getpid(),SIGABRT); #define BIT_BUCKET "/dev/null" #define PERL_SYS_INIT(c,v) MALLOC_INIT diff --git a/pod/Makefile b/pod/Makefile index a4b405c..3aadd9e 100644 --- a/pod/Makefile +++ b/pod/Makefile @@ -31,6 +31,7 @@ POD = \ perlmod.pod \ perlmodlib.pod \ perlmodinstall.pod \ + perlfork.pod \ perlform.pod \ perllocale.pod \ perlref.pod \ @@ -92,6 +93,7 @@ MAN = \ perlmod.man \ perlmodlib.man \ perlmodinstall.man \ + perlfork.man \ perlform.man \ perllocale.man \ perlref.man \ @@ -153,6 +155,7 @@ HTML = \ perlmod.html \ perlmodlib.html \ perlmodinstall.html \ + perlfork.html \ perlform.html \ perllocale.html \ perlref.html \ @@ -214,6 +217,7 @@ TEX = \ perlmod.tex \ perlmodlib.tex \ perlmodinstall.tex \ + perlfork.tex \ perlform.tex \ perllocale.tex \ perlref.tex \ diff --git a/pod/buildtoc b/pod/buildtoc index 1a9a24b..41cb76d 100644 --- a/pod/buildtoc +++ b/pod/buildtoc @@ -8,7 +8,7 @@ sub output ($); perl perlfaq perlfaq1 perlfaq2 perlfaq3 perlfaq4 perlfaq5 perlfaq6 perlfaq7 perlfaq8 perlfaq9 perldelta perldata perlsyn perlop perlre perlrun perlfunc perlvar perlsub - perlmod perlmodlib perlmodinstall perlform perllocale + perlmod perlmodlib perlmodinstall perlfork perlform perllocale perlref perlreftut perldsc perllol perltoot perltootc perlobj perltie perlbot perlipc perldbmfilter perldebug diff --git a/pod/perl.pod b/pod/perl.pod index 6e3921e..dc97764 100644 --- a/pod/perl.pod +++ b/pod/perl.pod @@ -47,6 +47,7 @@ sections: perltie Perl objects hidden behind simple variables perlbot Perl OO tricks and examples perlipc Perl interprocess communication + perlfork Perl fork() information perlthrtut Perl threads tutorial perldbmfilter Perl DBM Filters diff --git a/pod/perlfork.pod b/pod/perlfork.pod new file mode 100644 index 0000000..68a3242 --- /dev/null +++ b/pod/perlfork.pod @@ -0,0 +1,224 @@ +=head1 NAME + +perlfork - Perl's fork() emulation + +=head1 SYNOPSIS + +Perl provides a fork() keyword that corresponds to the Unix system call +of the same name. On most Unix-like platforms where the fork() system +call is available, Perl's fork() simply calls it. + +On some platforms such as Windows where the fork() system call is not +available, Perl can be built to emulate fork() at the interpreter level. +While the emulation is designed to be as compatible as possible with the +real fork() at the the level of the Perl program, there are certain +important differences that stem from the fact that all the pseudo child +"processes" created this way live in the same real process as far as the +operating system is concerned. + +This document provides a general overview of the capabilities and +limitations of the fork() emulation. Note that the issues discussed here +are not applicable to platforms where a real fork() is available and Perl +has been configured to use it. + +=head1 DESCRIPTION + +The fork() emulation is implemented at the level of the Perl interpreter. +What this means in general is that running fork() will actually clone the +running interpreter and all its state, and run the cloned interpreter in +a separate thread, beginning execution in the new thread just after the +point where the fork() was called in the parent. We will refer to the +thread that implements this child "process" as the pseudo-process. + +To the Perl program that called fork(), all this is designed to be +transparent. The parent returns from the fork() with a pseudo-process +ID that can be subsequently used in any process manipulation functions; +the child returns from the fork() with a value of C<0> to signify that +it is the child pseudo-process. + +=head2 Behavior of other Perl features in forked pseudo-processes + +Most Perl features behave in a natural way within pseudo-processes. + +=over 8 + +=item $$ or $PROCESS_ID + +This special variable is correctly set to the pseudo-process ID. +It can be used to identify pseudo-processes within a particular +session. Note that this value is subject to recycling if any +pseudo-processes are launched after others have been wait()-ed on. + +=item %ENV + +Each pseudo-process maintains its own virtual enviroment. Modifications +to %ENV affect the virtual environment, and are only visible within that +pseudo-process, and in any processes (or pseudo-processes) launched from +it. + +=item chdir() and all other builtins that accept filenames + +Each pseudo-process maintains its own virtual idea of the current directory. +Modifications to the current directory using chdir() are only visible within +that pseudo-process, and in any processes (or pseudo-processes) launched from +it. All file and directory accesses from the pseudo-process will correctly +map the virtual working directory to the real working directory appropriately. + +=item wait() and waitpid() + +wait() and waitpid() can be passed a pseudo-process ID returned by fork(). +These calls will properly wait for the termination of the pseudo-process +and return its status. + +=item kill() + +kill() can be used to terminate a pseudo-process by passing it the ID returned +by fork(). This should not be used except under dire circumstances, because +the operating system may not guarantee integrity of the process resources +when a running thread is terminated. Note that using kill() on a +pseudo-process() may typically cause memory leaks, because the thread that +implements the pseudo-process does not get a chance to clean up its resources. + +=item exec() + +Calling exec() within a pseudo-process actually spawns the requested +executable in a separate process and waits for it to complete before +exiting with the same exit status as that process. This means that the +process ID reported within the running executable will be different from +what the earlier Perl fork() might have returned. Similarly, any process +manipulation functions applied to the ID returned by fork() will affect the +waiting pseudo-process that called exec(), not the real process it is +waiting for after the exec(). + +=item exit() + +exit() always exits just the executing pseudo-process, after automatically +wait()-ing for any outstanding child pseudo-processes. Note that this means +that the process as a whole will not exit unless all running pseudo-processes +have exited. + +=item Open handles to files, directories and network sockets + +All open handles are dup()-ed in pseudo-processes, so that closing +any handles in one process does not affect the others. See below for +some limitations. + +=back + +=head2 Resource limits + +In the eyes of the operating system, pseudo-processes created via the fork() +emulation are simply threads in the same process. This means that any +process-level limits imposed by the operating system apply to all +pseudo-processes taken together. This includes any limits imposed by the +operating system on the number of open file, directory and socket handles, +limits on disk space usage, limits on memory size, limits on CPU utilization +etc. + +=head2 Killing the parent process + +If the parent process is killed (either using Perl's kill() builtin, or +using some external means) all the pseudo-processes are killed as well, +and the whole process exits. + +=head2 Lifetime of the parent process and pseudo-processes + +During the normal course of events, the parent process and every +pseudo-process started by it will wait for their respective pseudo-children +to complete before they exit. This means that the parent and every +pseudo-child created by it that is also a pseudo-parent will only exit +after their pseudo-children have exited. + +A way to mark a pseudo-processes as running detached from their parent (so +that the parent would not have to wait() for them if it doesn't want to) +will be provided in future. + +=head2 CAVEATS AND LIMITATIONS + +=over 8 + +=item BEGIN blocks + +The fork() emulation will not work entirely correctly when called from +within a BEGIN block. The forked copy will run the contents of the +BEGIN block, but will not continue parsing the source stream after the +BEGIN block. For example, consider the following code: + + BEGIN { + fork and exit; # fork child and exit the parent + print "inner\n"; + } + print "outer\n"; + +This will print: + + inner + +rather than the expected: + + inner + outer + +This limitation arises from fundamental technical difficulties in +cloning and restarting the stacks used by the Perl parser in the +middle of a parse. + +=item Open filehandles + +Any filehandles open at the time of the fork() will be dup()-ed. Thus, +the files can be closed independently in the parent and child, but beware +that the dup()-ed handles will still share the same seek pointer. Changing +the seek position in the parent will change it in the child and vice-versa. +One can avoid this by opening files that need distinct seek pointers +separately in the child. + +=item Global state maintained by XSUBs + +External subroutines (XSUBs) that maintain their own global state may +not work correctly. Such XSUBs will either need to maintain locks to +protect simultaneous access to global data from different pseudo-processes, +or maintain all their state on the Perl symbol table, which is copied +naturally when fork() is called. A callback mechanism that provides +extensions an opportunity to clone their state will be provided in the +near future. + +=item Interpreter embedded in larger application + +The fork() emulation may not behave as expected when it is executed in an +application which embeds a Perl interpreter and calls Perl APIs that can +evaluate bits of Perl code. This stems from the fact that the emulation +only has knowledge about the Perl interpreter's own data structures and +knows nothing about the containing application's state. For example, any +state carried on the application's own call stack is out of reach. + +=back + +=head1 BUGS + +=over 8 + +=item * + +Having pseudo-process IDs be negative integers breaks down for the integer +C<-1> because the wait() and waitpid() functions treat this number as +being special. The tacit assumption in the current implementation is that +the system never allocates a thread ID of C<1> for user threads. A better +representation for pseudo-process IDs will be implemented in future. + +=item * + +This document may be incomplete in some respects. + +=head1 AUTHOR + +Support for the fork() emulation was implemented by ActiveState, supported +by funding from Microsoft Corporation. + +This document is authored and maintained by Gurusamy Sarathy +Egsar@activestate.comE. + +=head1 SEE ALSO + +L, L + +=cut diff --git a/pod/roffitall b/pod/roffitall index 9c9daeb..7ddffe7 100644 --- a/pod/roffitall +++ b/pod/roffitall @@ -42,6 +42,7 @@ toroff=` $mandir/perlmod.1 \ $mandir/perlmodlib.1 \ $mandir/perlmodinstall.1 \ + $mandir/perlfork.1 \ $mandir/perlform.1 \ $mandir/perllocale.1 \ $mandir/perlref.1 \ diff --git a/pp.c b/pp.c index e7c966f..529fa9d 100644 --- a/pp.c +++ b/pp.c @@ -1789,7 +1789,7 @@ S_seed(pTHX) u = (U32)SEED_C1 * when; # endif #endif - u += SEED_C3 * (U32)getpid(); + u += SEED_C3 * (U32)PerlProc_getpid(); u += SEED_C4 * (U32)PTR2UV(PL_stack_sp); #ifndef PLAN9 /* XXX Plan9 assembler chokes on this; fix needed */ u += SEED_C5 * (U32)PTR2UV(&when); diff --git a/pp_ctl.c b/pp_ctl.c index bc2a361..b1f71a3 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -686,7 +686,7 @@ PP(pp_grepstart) /* SAVE_DEFSV does *not* suffice here for USE_THREADS */ SAVESPTR(DEFSV); ENTER; /* enter inner scope */ - SAVESPTR(PL_curpm); + SAVEVPTR(PL_curpm); src = PL_stack_base[*PL_markstack_ptr]; SvTEMP_off(src); @@ -756,7 +756,7 @@ PP(pp_mapwhile) SV *src; ENTER; /* enter inner scope */ - SAVESPTR(PL_curpm); + SAVEVPTR(PL_curpm); src = PL_stack_base[PL_markstack_ptr[-1]]; SvTEMP_off(src); @@ -785,7 +785,7 @@ PP(pp_sort) } ENTER; - SAVEPPTR(PL_sortcop); + SAVEVPTR(PL_sortcop); if (PL_op->op_flags & OPf_STACKED) { if (PL_op->op_flags & OPf_SPECIAL) { OP *kid = cLISTOP->op_first->op_sibling; /* pass pushmark */ @@ -813,10 +813,10 @@ PP(pp_sort) DIE(aTHX_ "Not a CODE reference in sort"); } PL_sortcop = CvSTART(cv); - SAVESPTR(CvROOT(cv)->op_ppaddr); + SAVEVPTR(CvROOT(cv)->op_ppaddr); CvROOT(cv)->op_ppaddr = PL_ppaddr[OP_NULL]; - SAVESPTR(PL_curpad); + SAVEVPTR(PL_curpad); PL_curpad = AvARRAY((AV*)AvARRAY(CvPADLIST(cv))[1]); } } @@ -1040,6 +1040,11 @@ S_dopoptolabel(pTHX_ char *label) Perl_warner(aTHX_ WARN_UNSAFE, "Exiting subroutine via %s", PL_op_name[PL_op->op_type]); break; + case CXt_FORMAT: + if (ckWARN(WARN_UNSAFE)) + Perl_warner(aTHX_ WARN_UNSAFE, "Exiting format via %s", + PL_op_name[PL_op->op_type]); + break; case CXt_EVAL: if (ckWARN(WARN_UNSAFE)) Perl_warner(aTHX_ WARN_UNSAFE, "Exiting eval via %s", @@ -1115,6 +1120,7 @@ S_dopoptosub_at(pTHX_ PERL_CONTEXT *cxstk, I32 startingblock) continue; case CXt_EVAL: case CXt_SUB: + case CXt_FORMAT: DEBUG_l( Perl_deb(aTHX_ "(Found sub #%ld)\n", (long)i)); return i; } @@ -1160,6 +1166,11 @@ S_dopoptoloop(pTHX_ I32 startingblock) Perl_warner(aTHX_ WARN_UNSAFE, "Exiting subroutine via %s", PL_op_name[PL_op->op_type]); break; + case CXt_FORMAT: + if (ckWARN(WARN_UNSAFE)) + Perl_warner(aTHX_ WARN_UNSAFE, "Exiting format via %s", + PL_op_name[PL_op->op_type]); + break; case CXt_EVAL: if (ckWARN(WARN_UNSAFE)) Perl_warner(aTHX_ WARN_UNSAFE, "Exiting eval via %s", @@ -1208,6 +1219,9 @@ Perl_dounwind(pTHX_ I32 cxix) break; case CXt_NULL: break; + case CXt_FORMAT: + POPFORMAT(cx); + break; } cxstack_ix--; } @@ -1420,7 +1434,7 @@ PP(pp_caller) } cx = &ccstack[cxix]; - if (CxTYPE(cx) == CXt_SUB) { + if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) { dbcxix = dopoptosub_at(ccstack, cxix - 1); /* We expect that ccstack[dbcxix] is CXt_SUB, anyway, the field below is defined for any cx. */ @@ -1448,7 +1462,8 @@ PP(pp_caller) PUSHs(sv_2mortal(newSViv((I32)CopLINE(cx->blk_oldcop)))); if (!MAXARG) RETURN; - if (CxTYPE(cx) == CXt_SUB) { /* So is ccstack[dbcxix]. */ + if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) { + /* So is ccstack[dbcxix]. */ sv = NEWSV(49, 0); gv_efullname3(sv, CvGV(ccstack[cxix].blk_sub.cv), Nullch); PUSHs(sv_2mortal(sv)); @@ -1563,7 +1578,7 @@ PP(pp_dbstate) PUSHSUB(cx); CvDEPTH(cv)++; (void)SvREFCNT_inc(cv); - SAVESPTR(PL_curpad); + SAVEVPTR(PL_curpad); PL_curpad = AvARRAY((AV*)*av_fetch(CvPADLIST(cv),1,FALSE)); RETURNOP(CvSTART(cv)); } @@ -1582,6 +1597,10 @@ PP(pp_enteriter) register PERL_CONTEXT *cx; I32 gimme = GIMME_V; SV **svp; + U32 cxtype = CXt_LOOP; +#ifdef USE_ITHREADS + void *iterdata; +#endif ENTER; SAVETMPS; @@ -1598,17 +1617,29 @@ PP(pp_enteriter) if (PL_op->op_targ) { svp = &PL_curpad[PL_op->op_targ]; /* "my" variable */ SAVESPTR(*svp); +#ifdef USE_ITHREADS + iterdata = (void*)PL_op->op_targ; + cxtype |= CXp_PADVAR; +#endif } else { - svp = &GvSV((GV*)POPs); /* symbol table variable */ + GV *gv = (GV*)POPs; + svp = &GvSV(gv); /* symbol table variable */ SAVEGENERICSV(*svp); *svp = NEWSV(0,0); +#ifdef USE_ITHREADS + iterdata = (void*)gv; +#endif } ENTER; - PUSHBLOCK(cx, CXt_LOOP, SP); + PUSHBLOCK(cx, cxtype, SP); +#ifdef USE_ITHREADS + PUSHLOOP(cx, iterdata, MARK); +#else PUSHLOOP(cx, svp, MARK); +#endif if (PL_op->op_flags & OPf_STACKED) { cx->blk_loop.iterary = (AV*)SvREFCNT_inc(POPs); if (SvTYPE(cx->blk_loop.iterary) != SVt_PVAV) { @@ -1703,7 +1734,9 @@ PP(pp_return) SV *sv; if (PL_curstackinfo->si_type == PERLSI_SORT) { - if (cxstack_ix == PL_sortcxix || dopoptosub(cxstack_ix) <= PL_sortcxix) { + if (cxstack_ix == PL_sortcxix + || dopoptosub(cxstack_ix) <= PL_sortcxix) + { if (cxstack_ix > PL_sortcxix) dounwind(PL_sortcxix); AvARRAY(PL_curstack)[1] = *SP; @@ -1737,6 +1770,9 @@ PP(pp_return) DIE(aTHX_ "%s did not return a true value", name); } break; + case CXt_FORMAT: + POPFORMAT(cx); + break; default: DIE(aTHX_ "panic: return"); } @@ -1826,6 +1862,10 @@ PP(pp_last) POPEVAL(cx); nextop = pop_return(); break; + case CXt_FORMAT: + POPFORMAT(cx); + nextop = pop_return(); + break; default: DIE(aTHX_ "panic: last"); } @@ -2072,7 +2112,7 @@ PP(pp_goto) SP[1] = SP[0]; SP--; } - fp3 = (I32(*)(int,int,int)))CvXSUB(cv; + fp3 = (I32(*)(int,int,int))CvXSUB(cv); items = (*fp3)(CvXSUBANY(cv).any_i32, mark - PL_stack_base + 1, items); @@ -2116,9 +2156,10 @@ PP(pp_goto) AV *newpad = newAV(); SV **oldpad = AvARRAY(svp[CvDEPTH(cv)-1]); I32 ix = AvFILLp((AV*)svp[1]); + I32 names_fill = AvFILLp((AV*)svp[0]); svp = AvARRAY(svp[0]); for ( ;ix > 0; ix--) { - if (svp[ix] != &PL_sv_undef) { + if (names_fill >= ix && svp[ix] != &PL_sv_undef) { char *name = SvPVX(svp[ix]); if ((SvFLAGS(svp[ix]) & SVf_FAKE) || *name == '&') @@ -2137,7 +2178,7 @@ PP(pp_goto) SvPADMY_on(sv); } } - else if (IS_PADGV(oldpad[ix])) { + else if (IS_PADGV(oldpad[ix]) || IS_PADCONST(oldpad[ix])) { av_store(newpad, ix, sv = SvREFCNT_inc(oldpad[ix])); } else { @@ -2170,7 +2211,7 @@ PP(pp_goto) } } #endif /* USE_THREADS */ - SAVESPTR(PL_curpad); + SAVEVPTR(PL_curpad); PL_curpad = AvARRAY((AV*)svp[CvDEPTH(cv)]); #ifndef USE_THREADS if (cx->blk_sub.hasargs) @@ -2275,6 +2316,7 @@ PP(pp_goto) break; } /* FALL THROUGH */ + case CXt_FORMAT: case CXt_NULL: DIE(aTHX_ "Can't \"goto\" outside a block"); default: @@ -2506,7 +2548,7 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, char *code, AV** avp) #ifdef OP_IN_REGISTER PL_opsave = op; #else - SAVEPPTR(PL_op); + SAVEVPTR(PL_op); #endif PL_hints = 0; @@ -2549,7 +2591,7 @@ S_doeval(pTHX_ int gimme, OP** startop) /* set up a scratch pad */ SAVEI32(PL_padix); - SAVESPTR(PL_curpad); + SAVEVPTR(PL_curpad); SAVESPTR(PL_comppad); SAVESPTR(PL_comppad_name); SAVEI32(PL_comppad_name_fill); @@ -2561,7 +2603,7 @@ S_doeval(pTHX_ int gimme, OP** startop) PERL_CONTEXT *cx = &cxstack[i]; if (CxTYPE(cx) == CXt_EVAL) break; - else if (CxTYPE(cx) == CXt_SUB) { + else if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) { caller = cx->blk_sub.cv; break; } @@ -2970,11 +3012,9 @@ PP(pp_require) PL_rsfp_filters = Nullav; PL_rsfp = tryrsfp; - name = savepv(name); - SAVEFREEPV(name); SAVEHINTS(); PL_hints = 0; - SAVEPPTR(PL_compiling.cop_warnings); + SAVESPTR(PL_compiling.cop_warnings); if (PL_dowarn & G_WARN_ALL_ON) PL_compiling.cop_warnings = WARN_ALL ; else if (PL_dowarn & G_WARN_ALL_OFF) @@ -3049,7 +3089,7 @@ PP(pp_entereval) SAVEDELETE(PL_defstash, safestr, strlen(safestr)); SAVEHINTS(); PL_hints = PL_op->op_targ; - SAVEPPTR(PL_compiling.cop_warnings); + SAVESPTR(PL_compiling.cop_warnings); if (!specialWARN(PL_compiling.cop_warnings)) { PL_compiling.cop_warnings = newSVsv(PL_compiling.cop_warnings) ; SAVEFREESV(PL_compiling.cop_warnings) ; diff --git a/pp_hot.c b/pp_hot.c index 421b099..690abea 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -40,7 +40,7 @@ static void unset_cvowner(pTHXo_ void *cvarg); PP(pp_const) { djSP; - XPUSHs(cSVOP->op_sv); + XPUSHs(cSVOP_sv); RETURN; } @@ -1509,12 +1509,14 @@ PP(pp_iter) register PERL_CONTEXT *cx; SV* sv; AV* av; + SV **itersvp; EXTEND(SP, 1); cx = &cxstack[cxstack_ix]; if (CxTYPE(cx) != CXt_LOOP) DIE(aTHX_ "panic: pp_iter"); + itersvp = CxITERVAR(cx); av = cx->blk_loop.iterary; if (SvTYPE(av) != SVt_PVAV) { /* iterate ($min .. $max) */ @@ -1525,11 +1527,9 @@ PP(pp_iter) char *max = SvPV((SV*)av, maxlen); if (!SvNIOK(cur) && SvCUR(cur) <= maxlen) { #ifndef USE_THREADS /* don't risk potential race */ - if (SvREFCNT(*cx->blk_loop.itervar) == 1 - && !SvMAGICAL(*cx->blk_loop.itervar)) - { + if (SvREFCNT(*itersvp) == 1 && !SvMAGICAL(*itersvp)) { /* safe to reuse old SV */ - sv_setsv(*cx->blk_loop.itervar, cur); + sv_setsv(*itersvp, cur); } else #endif @@ -1537,8 +1537,8 @@ PP(pp_iter) /* we need a fresh SV every time so that loop body sees a * completely new SV for closures/references to work as * they used to */ - SvREFCNT_dec(*cx->blk_loop.itervar); - *cx->blk_loop.itervar = newSVsv(cur); + SvREFCNT_dec(*itersvp); + *itersvp = newSVsv(cur); } if (strEQ(SvPVX(cur), max)) sv_setiv(cur, 0); /* terminate next time */ @@ -1553,11 +1553,9 @@ PP(pp_iter) RETPUSHNO; #ifndef USE_THREADS /* don't risk potential race */ - if (SvREFCNT(*cx->blk_loop.itervar) == 1 - && !SvMAGICAL(*cx->blk_loop.itervar)) - { + if (SvREFCNT(*itersvp) == 1 && !SvMAGICAL(*itersvp)) { /* safe to reuse old SV */ - sv_setiv(*cx->blk_loop.itervar, cx->blk_loop.iterix++); + sv_setiv(*itersvp, cx->blk_loop.iterix++); } else #endif @@ -1565,8 +1563,8 @@ PP(pp_iter) /* we need a fresh SV every time so that loop body sees a * completely new SV for closures/references to work as they * used to */ - SvREFCNT_dec(*cx->blk_loop.itervar); - *cx->blk_loop.itervar = newSViv(cx->blk_loop.iterix++); + SvREFCNT_dec(*itersvp); + *itersvp = newSViv(cx->blk_loop.iterix++); } RETPUSHYES; } @@ -1575,7 +1573,7 @@ PP(pp_iter) if (cx->blk_loop.iterix >= (av == PL_curstack ? cx->blk_oldsp : AvFILL(av))) RETPUSHNO; - SvREFCNT_dec(*cx->blk_loop.itervar); + SvREFCNT_dec(*itersvp); if (sv = (SvMAGICAL(av)) ? *av_fetch(av, ++cx->blk_loop.iterix, FALSE) @@ -1603,7 +1601,7 @@ PP(pp_iter) sv = (SV*)lv; } - *cx->blk_loop.itervar = SvREFCNT_inc(sv); + *itersvp = SvREFCNT_inc(sv); RETPUSHYES; } @@ -1900,7 +1898,7 @@ PP(pp_grepwhile) SV *src; ENTER; /* enter inner scope */ - SAVESPTR(PL_curpm); + SAVEVPTR(PL_curpm); src = PL_stack_base[*PL_markstack_ptr]; SvTEMP_off(src); @@ -2403,7 +2401,7 @@ try_autoload: SP--; } PL_stack_sp = mark + 1; - fp3 = (I32(*)(int,int,int)))CvXSUB(cv; + fp3 = (I32(*)(int,int,int))CvXSUB(cv); items = (*fp3)(CvXSUBANY(cv).any_i32, MARK - PL_stack_base + 1, items); @@ -2439,7 +2437,7 @@ try_autoload: } /* We assume first XSUB in &DB::sub is the called one. */ if (PL_curcopdb) { - SAVESPTR(PL_curcop); + SAVEVPTR(PL_curcop); PL_curcop = PL_curcopdb; PL_curcopdb = NULL; } @@ -2481,9 +2479,10 @@ try_autoload: AV *newpad = newAV(); SV **oldpad = AvARRAY(svp[CvDEPTH(cv)-1]); I32 ix = AvFILLp((AV*)svp[1]); + I32 names_fill = AvFILLp((AV*)svp[0]); svp = AvARRAY(svp[0]); for ( ;ix > 0; ix--) { - if (svp[ix] != &PL_sv_undef) { + if (names_fill >= ix && svp[ix] != &PL_sv_undef) { char *name = SvPVX(svp[ix]); if ((SvFLAGS(svp[ix]) & SVf_FAKE) /* outer lexical? */ || *name == '&') /* anonymous code? */ @@ -2500,7 +2499,7 @@ try_autoload: SvPADMY_on(sv); } } - else if (IS_PADGV(oldpad[ix])) { + else if (IS_PADGV(oldpad[ix]) || IS_PADCONST(oldpad[ix])) { av_store(newpad, ix, sv = SvREFCNT_inc(oldpad[ix])); } else { @@ -2531,7 +2530,7 @@ try_autoload: } } #endif /* USE_THREADS */ - SAVESPTR(PL_curpad); + SAVEVPTR(PL_curpad); PL_curpad = AvARRAY((AV*)svp[CvDEPTH(cv)]); #ifndef USE_THREADS if (hasargs) diff --git a/pp_sys.c b/pp_sys.c index ebc5e27..48fb5e4 100644 --- a/pp_sys.c +++ b/pp_sys.c @@ -1138,9 +1138,9 @@ S_doform(pTHX_ CV *cv, GV *gv, OP *retop) SAVETMPS; push_return(retop); - PUSHBLOCK(cx, CXt_SUB, PL_stack_sp); + PUSHBLOCK(cx, CXt_FORMAT, PL_stack_sp); PUSHFORMAT(cx); - SAVESPTR(PL_curpad); + SAVEVPTR(PL_curpad); PL_curpad = AvARRAY((AV*)svp[1]); setdefout(gv); /* locally select filehandle so $% et al work */ @@ -2990,9 +2990,11 @@ PP(pp_fttext) len = 512; } else { - if (ckWARN(WARN_UNOPENED)) + if (ckWARN(WARN_UNOPENED)) { + gv = cGVOP; Perl_warner(aTHX_ WARN_UNOPENED, "Test on unopened file <%s>", - GvENAME(cGVOP)); + GvENAME(gv)); + } SETERRNO(EBADF,RMS$_IFI); RETPUSHUNDEF; } @@ -3576,24 +3578,20 @@ PP(pp_fork) if (!childpid) { /*SUPPRESS 560*/ if (tmpgv = gv_fetchpv("$", TRUE, SVt_PV)) - sv_setiv(GvSV(tmpgv), (IV)getpid()); + sv_setiv(GvSV(tmpgv), (IV)PerlProc_getpid()); hv_clear(PL_pidstatus); /* no kids, so don't wait for 'em */ } PUSHi(childpid); RETURN; #else -# ifdef USE_ITHREADS - /* XXXXXX testing */ +# if defined(USE_ITHREADS) && defined(WIN32) djSP; dTARGET; - /* XXX this just an approximation of what will eventually be run - * in a different thread */ - PerlInterpreter *new_perl = perl_clone(my_perl, 0); - Perl_pp_enter(new_perl); - new_perl->Top = new_perl->Top->op_next; /* continue from next op */ - CALLRUNOPS(new_perl); - - /* parent returns with negative pseudo-pid */ - PUSHi(-1); + Pid_t childpid; + + EXTEND(SP, 1); + PERL_FLUSHALL_FOR_CHILD; + childpid = PerlProc_fork(); + PUSHi(childpid); RETURN; # else DIE(aTHX_ PL_no_func, "Unsupported function fork"); @@ -3783,6 +3781,12 @@ PP(pp_exec) # endif #endif } + +#ifdef USE_ITHREADS + if (value >= 0) + my_exit(value); +#endif + SP = ORIGMARK; PUSHi(value); RETURN; @@ -3827,7 +3831,7 @@ PP(pp_getpgrp) #ifdef BSD_GETPGRP pgrp = (I32)BSD_GETPGRP(pid); #else - if (pid != 0 && pid != getpid()) + if (pid != 0 && pid != PerlProc_getpid()) DIE(aTHX_ "POSIX getpgrp can't take an argument"); pgrp = getpgrp(); #endif @@ -3857,8 +3861,11 @@ PP(pp_setpgrp) #ifdef BSD_SETPGRP SETi( BSD_SETPGRP(pid, pgrp) >= 0 ); #else - if ((pgrp != 0 && pgrp != getpid()) || (pid != 0 && pid != getpid())) + if ((pgrp != 0 && pgrp != PerlProc_getpid()) + || (pid != 0 && pid != PerlProc_getpid())) + { DIE(aTHX_ "setpgrp can't take arguments"); + } SETi( setpgrp() >= 0 ); #endif /* USE_BSDPGRP */ RETURN; diff --git a/proto.h b/proto.h index 1204c81..5a01615 100644 --- a/proto.h +++ b/proto.h @@ -4,9 +4,52 @@ * and run 'make regen_headers' to effect changes. */ + + +START_EXTERN_C + +#if defined(PERL_IMPLICIT_SYS) +PERL_CALLCONV PerlInterpreter* perl_alloc_using(struct IPerlMem* m, struct IPerlMem* ms, struct IPerlMem* mp, struct IPerlEnv* e, struct IPerlStdIO* io, struct IPerlLIO* lio, struct IPerlDir* d, struct IPerlSock* s, struct IPerlProc* p); +#else +PERL_CALLCONV PerlInterpreter* perl_alloc(void); +#endif +PERL_CALLCONV void perl_construct(PerlInterpreter* interp); +PERL_CALLCONV void perl_destruct(PerlInterpreter* interp); +PERL_CALLCONV void perl_free(PerlInterpreter* interp); +PERL_CALLCONV int perl_run(PerlInterpreter* interp); +PERL_CALLCONV int perl_parse(PerlInterpreter* interp, XSINIT_t xsinit, int argc, char** argv, char** env); +#if defined(USE_ITHREADS) +PERL_CALLCONV PerlInterpreter* perl_clone(PerlInterpreter* interp, UV flags); +PERL_CALLCONV PerlInterpreter* perl_clone_using(PerlInterpreter *interp, UV flags, struct IPerlMem* m, struct IPerlMem* ms, struct IPerlMem* mp, struct IPerlEnv* e, struct IPerlStdIO* io, struct IPerlLIO* lio, struct IPerlDir* d, struct IPerlSock* s, struct IPerlProc* p); +#endif + +#if defined(MYMALLOC) +PERL_CALLCONV Malloc_t Perl_malloc(MEM_SIZE nbytes); +PERL_CALLCONV Malloc_t Perl_calloc(MEM_SIZE elements, MEM_SIZE size); +PERL_CALLCONV Malloc_t Perl_realloc(Malloc_t where, MEM_SIZE nbytes); +PERL_CALLCONV Free_t Perl_mfree(Malloc_t where); +PERL_CALLCONV MEM_SIZE Perl_malloced_size(void *p); +#endif + +END_EXTERN_C + +/* functions with flag 'n' should come before here */ #if defined(PERL_OBJECT) +class CPerlObj { public: + struct interpreter interp; + CPerlObj(IPerlMem*, IPerlMem*, IPerlMem*, IPerlEnv*, IPerlStdIO*, + IPerlLIO*, IPerlDir*, IPerlSock*, IPerlProc*); + void* operator new(size_t nSize, IPerlMem *pvtbl); + static void operator delete(void* pPerl, IPerlMem *pvtbl); + int do_aspawn (void *vreally, void **vmark, void **vsp); #endif +#if defined(PERL_OBJECT) +public: +#else +START_EXTERN_C +#endif +# include "pp_proto.h" PERL_CALLCONV SV* Perl_amagic_call(pTHX_ SV* left, SV* right, int method, int dir); PERL_CALLCONV bool Perl_Gv_AMupdate(pTHX_ HV* stash); PERL_CALLCONV OP* Perl_append_elem(pTHX_ I32 optype, OP* head, OP* tail); @@ -315,9 +358,6 @@ PERL_CALLCONV int Perl_magic_set_all_env(pTHX_ SV* sv, MAGIC* mg); PERL_CALLCONV U32 Perl_magic_sizepack(pTHX_ SV* sv, MAGIC* mg); PERL_CALLCONV int Perl_magic_wipepack(pTHX_ SV* sv, MAGIC* mg); PERL_CALLCONV void Perl_magicname(pTHX_ char* sym, char* name, I32 namlen); -#if defined(MYMALLOC) -PERL_CALLCONV MEM_SIZE Perl_malloced_size(void *p); -#endif PERL_CALLCONV void Perl_markstack_grow(pTHX); #if defined(USE_LOCALE_COLLATE) PERL_CALLCONV char* Perl_mem_collxfrm(pTHX_ const char* s, STRLEN len, STRLEN* xlen); @@ -415,6 +455,7 @@ PERL_CALLCONV SV* Perl_newSVrv(pTHX_ SV* rv, const char* classname); PERL_CALLCONV SV* Perl_newSVsv(pTHX_ SV* old); PERL_CALLCONV OP* Perl_newUNOP(pTHX_ I32 type, I32 flags, OP* first); PERL_CALLCONV OP* Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP* loop, I32 whileline, OP* expr, OP* block, OP* cont); + PERL_CALLCONV PERL_SI* Perl_new_stackinfo(pTHX_ I32 stitems, I32 cxitems); PERL_CALLCONV PerlIO* Perl_nextargv(pTHX_ GV* gv); PERL_CALLCONV char* Perl_ninstr(pTHX_ const char* big, const char* bigend, const char* little, const char* lend); @@ -433,22 +474,15 @@ PERL_CALLCONV void Perl_pad_reset(pTHX); PERL_CALLCONV void Perl_pad_swipe(pTHX_ PADOFFSET po); PERL_CALLCONV void Perl_peep(pTHX_ OP* o); #if defined(PERL_OBJECT) -PERL_CALLCONV void perl_construct(void); -PERL_CALLCONV void perl_destruct(void); -PERL_CALLCONV void perl_free(void); -PERL_CALLCONV int perl_run(void); -PERL_CALLCONV int perl_parse(XSINIT_t xsinit, int argc, char** argv, char** env); -#else -PERL_CALLCONV PerlInterpreter* perl_alloc(void); -PERL_CALLCONV void perl_construct(PerlInterpreter* interp); -PERL_CALLCONV void perl_destruct(PerlInterpreter* interp); -PERL_CALLCONV void perl_free(PerlInterpreter* interp); -PERL_CALLCONV int perl_run(PerlInterpreter* interp); -PERL_CALLCONV int perl_parse(PerlInterpreter* interp, XSINIT_t xsinit, int argc, char** argv, char** env); +PERL_CALLCONV void Perl_construct(pTHX); +PERL_CALLCONV void Perl_destruct(pTHX); +PERL_CALLCONV void Perl_free(pTHX); +PERL_CALLCONV int Perl_run(pTHX); +PERL_CALLCONV int Perl_parse(pTHX_ XSINIT_t xsinit, int argc, char** argv, char** env); +#endif #if defined(USE_THREADS) PERL_CALLCONV struct perl_thread* Perl_new_struct_thread(pTHX_ struct perl_thread *t); #endif -#endif PERL_CALLCONV void Perl_call_atexit(pTHX_ ATEXIT_t fn, void *ptr); PERL_CALLCONV I32 Perl_call_argv(pTHX_ const char* sub_name, I32 flags, char** argv); PERL_CALLCONV I32 Perl_call_method(pTHX_ const char* methname, I32 flags); @@ -532,6 +566,7 @@ PERL_CALLCONV void Perl_save_nogv(pTHX_ GV* gv); PERL_CALLCONV void Perl_save_op(pTHX); PERL_CALLCONV SV* Perl_save_scalar(pTHX_ GV* gv); PERL_CALLCONV void Perl_save_pptr(pTHX_ char** pptr); +PERL_CALLCONV void Perl_save_vptr(pTHX_ void* pptr); PERL_CALLCONV void Perl_save_re_context(pTHX); PERL_CALLCONV void Perl_save_sptr(pTHX_ SV** sptr); PERL_CALLCONV SV* Perl_save_svref(pTHX_ SV** sptr); @@ -677,10 +712,6 @@ PERL_CALLCONV int Perl_yyparse(pTHX); PERL_CALLCONV int Perl_yywarn(pTHX_ char* s); #if defined(MYMALLOC) PERL_CALLCONV void Perl_dump_mstats(pTHX_ char* s); -PERL_CALLCONV Malloc_t Perl_malloc(MEM_SIZE nbytes); -PERL_CALLCONV Malloc_t Perl_calloc(MEM_SIZE elements, MEM_SIZE size); -PERL_CALLCONV Malloc_t Perl_realloc(Malloc_t where, MEM_SIZE nbytes); -PERL_CALLCONV Free_t Perl_mfree(Malloc_t where); #endif PERL_CALLCONV Malloc_t Perl_safesysmalloc(MEM_SIZE nbytes); PERL_CALLCONV Malloc_t Perl_safesyscalloc(MEM_SIZE elements, MEM_SIZE size); @@ -741,7 +772,8 @@ PERL_CALLCONV void Perl_boot_core_xsutils(pTHX); #if defined(USE_ITHREADS) PERL_CALLCONV PERL_CONTEXT* Perl_cx_dup(pTHX_ PERL_CONTEXT* cx, I32 ix, I32 max); PERL_CALLCONV PERL_SI* Perl_si_dup(pTHX_ PERL_SI* si); -PERL_CALLCONV ANY* Perl_ss_dup(pTHX_ ANY* ss, I32 ix, I32 max); +PERL_CALLCONV ANY* Perl_ss_dup(pTHX_ PerlInterpreter* proto_perl); +PERL_CALLCONV void* Perl_any_dup(pTHX_ void* v, PerlInterpreter* proto_perl); PERL_CALLCONV HE* Perl_he_dup(pTHX_ HE* e, bool shared); PERL_CALLCONV REGEXP* Perl_re_dup(pTHX_ REGEXP* r); PERL_CALLCONV PerlIO* Perl_fp_dup(pTHX_ PerlIO* fp, char type); @@ -756,15 +788,18 @@ PERL_CALLCONV PTR_TBL_t* Perl_ptr_table_new(pTHX); PERL_CALLCONV void* Perl_ptr_table_fetch(pTHX_ PTR_TBL_t *tbl, void *sv); PERL_CALLCONV void Perl_ptr_table_store(pTHX_ PTR_TBL_t *tbl, void *oldsv, void *newsv); PERL_CALLCONV void Perl_ptr_table_split(pTHX_ PTR_TBL_t *tbl); -PERL_CALLCONV PerlInterpreter* perl_clone(PerlInterpreter* interp, UV flags); -PERL_CALLCONV PerlInterpreter* perl_clone_using(PerlInterpreter *interp, UV flags, struct IPerlMem* m, struct IPerlEnv* e, struct IPerlStdIO* io, struct IPerlLIO* lio, struct IPerlDir* d, struct IPerlSock* s, struct IPerlProc* p); #endif + #if defined(PERL_OBJECT) protected: +#else +END_EXTERN_C #endif + #if defined(PERL_IN_AV_C) || defined(PERL_DECL_PROT) STATIC I32 S_avhv_index_sv(pTHX_ SV* sv); #endif + #if defined(PERL_IN_DOOP_C) || defined(PERL_DECL_PROT) STATIC I32 S_do_trans_CC_simple(pTHX_ SV *sv); STATIC I32 S_do_trans_CC_count(pTHX_ SV *sv); @@ -777,9 +812,11 @@ STATIC I32 S_do_trans_CU_simple(pTHX_ SV *sv); STATIC I32 S_do_trans_UC_trivial(pTHX_ SV *sv); STATIC I32 S_do_trans_CU_trivial(pTHX_ SV *sv); #endif + #if defined(PERL_IN_GV_C) || defined(PERL_DECL_PROT) STATIC void S_gv_init_sv(pTHX_ GV *gv, I32 sv_type); #endif + #if defined(PERL_IN_HV_C) || defined(PERL_DECL_PROT) STATIC void S_hsplit(pTHX_ HV *hv); STATIC void S_hfreeentries(pTHX_ HV *hv); @@ -789,11 +826,13 @@ STATIC void S_del_he(pTHX_ HE *p); STATIC HEK* S_save_hek(pTHX_ const char *str, I32 len, U32 hash); STATIC void S_hv_magic_check(pTHX_ HV *hv, bool *needs_copy, bool *needs_store); #endif + #if defined(PERL_IN_MG_C) || defined(PERL_DECL_PROT) STATIC void S_save_magic(pTHX_ I32 mgs_ix, SV *sv); STATIC int S_magic_methpack(pTHX_ SV *sv, MAGIC *mg, char *meth); STATIC int S_magic_methcall(pTHX_ SV *sv, MAGIC *mg, char *meth, I32 f, int n, SV *val); #endif + #if defined(PERL_IN_OP_C) || defined(PERL_DECL_PROT) STATIC I32 S_list_assignment(pTHX_ OP *o); STATIC void S_bad_type(pTHX_ I32 n, char *t, char *name, OP *kid); @@ -822,6 +861,7 @@ STATIC void S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs); STATIC void* S_Slab_Alloc(pTHX_ int m, size_t sz); # endif #endif + #if defined(PERL_IN_PERL_C) || defined(PERL_DECL_PROT) STATIC void S_find_beginning(pTHX); STATIC void S_forbid_setid(pTHX_ char *); @@ -850,6 +890,7 @@ STATIC void* S_call_list_body(pTHX_ va_list args); STATIC struct perl_thread * S_init_main_thread(pTHX); # endif #endif + #if defined(PERL_IN_PP_C) || defined(PERL_DECL_PROT) STATIC void S_doencodes(pTHX_ SV* sv, char* s, I32 len); STATIC SV* S_refto(pTHX_ SV* sv); @@ -858,6 +899,7 @@ STATIC SV* S_mul128(pTHX_ SV *sv, U8 m); STATIC SV* S_is_an_int(pTHX_ char *s, STRLEN l); STATIC int S_div128(pTHX_ SV *pnum, bool *done); #endif + #if defined(PERL_IN_PP_CTL_C) || defined(PERL_DECL_PROT) STATIC OP* S_docatch(pTHX_ OP *o); STATIC void* S_docatch_body(pTHX_ va_list args); @@ -874,10 +916,12 @@ STATIC OP* S_doeval(pTHX_ int gimme, OP** startop); STATIC PerlIO * S_doopen_pmc(pTHX_ const char *name, const char *mode); STATIC void S_qsortsv(pTHX_ SV ** array, size_t num_elts, SVCOMPARE_t f); #endif + #if defined(PERL_IN_PP_HOT_C) || defined(PERL_DECL_PROT) STATIC CV* S_get_db_sub(pTHX_ SV **svp, CV *cv); STATIC SV* S_method_common(pTHX_ SV* meth, U32* hashp); #endif + #if defined(PERL_IN_PP_SYS_C) || defined(PERL_DECL_PROT) STATIC OP* S_doform(pTHX_ CV *cv, GV *gv, OP *retop); STATIC int S_emulate_eaccess(pTHX_ const char* path, Mode_t mode); @@ -885,6 +929,7 @@ STATIC int S_emulate_eaccess(pTHX_ const char* path, Mode_t mode); STATIC int S_dooneliner(pTHX_ char *cmd, char *filename); # endif #endif + #if defined(PERL_IN_REGCOMP_C) || defined(PERL_DECL_PROT) STATIC regnode* S_reg(pTHX_ I32, I32 *); STATIC regnode* S_reganode(pTHX_ U8, U32); @@ -909,6 +954,7 @@ STATIC void S_re_croak2(pTHX_ const char* pat1, const char* pat2, ...) __attribu STATIC I32 S_regpposixcc(pTHX_ I32 value); STATIC void S_checkposixcc(pTHX); #endif + #if defined(PERL_IN_REGEXEC_C) || defined(PERL_DECL_PROT) STATIC I32 S_regmatch(pTHX_ regnode *prog); STATIC I32 S_regrepeat(pTHX_ regnode *p, I32 max); @@ -923,12 +969,15 @@ STATIC void S_cache_re(pTHX_ regexp *prog); STATIC U8* S_reghop(pTHX_ U8 *pos, I32 off); STATIC U8* S_reghopmaybe(pTHX_ U8 *pos, I32 off); #endif + #if defined(PERL_IN_RUN_C) || defined(PERL_DECL_PROT) STATIC void S_debprof(pTHX_ OP *o); #endif + #if defined(PERL_IN_SCOPE_C) || defined(PERL_DECL_PROT) STATIC SV* S_save_scalar_at(pTHX_ SV **sptr); #endif + #if defined(PERL_IN_SV_C) || defined(PERL_DECL_PROT) STATIC IV S_asIV(pTHX_ SV* sv); STATIC UV S_asUV(pTHX_ SV* sv); @@ -984,6 +1033,7 @@ STATIC void S_sv_del_backref(pTHX_ SV *sv); STATIC void S_del_sv(pTHX_ SV *p); # endif #endif + #if defined(PERL_IN_TOKE_C) || defined(PERL_DECL_PROT) STATIC void S_check_uni(pTHX); STATIC void S_force_next(pTHX_ I32 type); @@ -1027,12 +1077,18 @@ STATIC int S_uni(pTHX_ I32 f, char *s); STATIC I32 S_win32_textfilter(pTHX_ int idx, SV *sv, int maxlen); # endif #endif + #if defined(PERL_IN_UNIVERSAL_C) || defined(PERL_DECL_PROT) STATIC SV* S_isa_lookup(pTHX_ HV *stash, const char *name, int len, int level); #endif + #if defined(PERL_IN_UTIL_C) || defined(PERL_DECL_PROT) STATIC SV* S_mess_alloc(pTHX); # if defined(LEAKTEST) STATIC void S_xstat(pTHX_ int); # endif #endif + +#if defined(PERL_OBJECT) +}; +#endif diff --git a/regcomp.c b/regcomp.c index 49e9e26..65db009 100644 --- a/regcomp.c +++ b/regcomp.c @@ -3502,39 +3502,39 @@ Perl_save_re_context(pTHX) SAVEPPTR(PL_reginput); /* String-input pointer. */ SAVEPPTR(PL_regbol); /* Beginning of input, for ^ check. */ SAVEPPTR(PL_regeol); /* End of input, for $ check. */ - SAVESPTR(PL_regstartp); /* Pointer to startp array. */ - SAVESPTR(PL_regendp); /* Ditto for endp. */ - SAVESPTR(PL_reglastparen); /* Similarly for lastparen. */ + SAVEVPTR(PL_regstartp); /* Pointer to startp array. */ + SAVEVPTR(PL_regendp); /* Ditto for endp. */ + SAVEVPTR(PL_reglastparen); /* Similarly for lastparen. */ SAVEPPTR(PL_regtill); /* How far we are required to go. */ SAVEI32(PL_regprev); /* char before regbol, \n if none */ - SAVESPTR(PL_reg_start_tmp); /* from regexec.c */ + SAVEVPTR(PL_reg_start_tmp); /* from regexec.c */ PL_reg_start_tmp = 0; SAVEFREEPV(PL_reg_start_tmp); SAVEI32(PL_reg_start_tmpl); /* from regexec.c */ PL_reg_start_tmpl = 0; - SAVESPTR(PL_regdata); + SAVEVPTR(PL_regdata); SAVEI32(PL_reg_flags); /* from regexec.c */ SAVEI32(PL_reg_eval_set); /* from regexec.c */ SAVEI32(PL_regnarrate); /* from regexec.c */ - SAVESPTR(PL_regprogram); /* from regexec.c */ + SAVEVPTR(PL_regprogram); /* from regexec.c */ SAVEINT(PL_regindent); /* from regexec.c */ - SAVESPTR(PL_regcc); /* from regexec.c */ - SAVESPTR(PL_curcop); - SAVESPTR(PL_regcomp_rx); /* from regcomp.c */ + SAVEVPTR(PL_regcc); /* from regexec.c */ + SAVEVPTR(PL_curcop); + SAVEVPTR(PL_regcomp_rx); /* from regcomp.c */ SAVEI32(PL_regseen); /* from regcomp.c */ SAVEI32(PL_regsawback); /* Did we see \1, ...? */ SAVEI32(PL_regnaughty); /* How bad is this pattern? */ - SAVESPTR(PL_regcode); /* Code-emit pointer; ®dummy = don't */ + SAVEVPTR(PL_regcode); /* Code-emit pointer; ®dummy = don't */ SAVEPPTR(PL_regxend); /* End of input for compile */ SAVEPPTR(PL_regcomp_parse); /* Input-scan pointer. */ - SAVESPTR(PL_reg_call_cc); /* from regexec.c */ - SAVESPTR(PL_reg_re); /* from regexec.c */ + SAVEVPTR(PL_reg_call_cc); /* from regexec.c */ + SAVEVPTR(PL_reg_re); /* from regexec.c */ SAVEPPTR(PL_reg_ganch); /* from regexec.c */ SAVESPTR(PL_reg_sv); /* from regexec.c */ - SAVESPTR(PL_reg_magic); /* from regexec.c */ + SAVEVPTR(PL_reg_magic); /* from regexec.c */ SAVEI32(PL_reg_oldpos); /* from regexec.c */ - SAVESPTR(PL_reg_oldcurpm); /* from regexec.c */ - SAVESPTR(PL_reg_curpm); /* from regexec.c */ + SAVEVPTR(PL_reg_oldcurpm); /* from regexec.c */ + SAVEVPTR(PL_reg_curpm); /* from regexec.c */ #ifdef DEBUGGING SAVEPPTR(PL_reg_starttry); /* from regexec.c */ #endif diff --git a/run.c b/run.c index a5e6359..9878076 100644 --- a/run.c +++ b/run.c @@ -71,7 +71,7 @@ Perl_debop(pTHX_ OP *o) Perl_deb(aTHX_ "%s", PL_op_name[o->op_type]); switch (o->op_type) { case OP_CONST: - PerlIO_printf(Perl_debug_log, "(%s)", SvPEEK(cSVOPo->op_sv)); + PerlIO_printf(Perl_debug_log, "(%s)", SvPEEK(cSVOPo_sv)); break; case OP_GVSV: case OP_GV: diff --git a/scope.c b/scope.c index 0fd3692..c0559da 100644 --- a/scope.c +++ b/scope.c @@ -428,6 +428,16 @@ Perl_save_pptr(pTHX_ char **pptr) } void +Perl_save_vptr(pTHX_ void *ptr) +{ + dTHR; + SSCHECK(3); + SSPUSHPTR(*(char**)ptr); + SSPUSHPTR(ptr); + SSPUSHINT(SAVEt_VPTR); +} + +void Perl_save_sptr(pTHX_ SV **sptr) { dTHR; @@ -749,6 +759,7 @@ Perl_leave_scope(pTHX_ I32 base) ptr = SSPOPPTR; *(SV**)ptr = (SV*)SSPOPPTR; break; + case SAVEt_VPTR: /* random* reference */ case SAVEt_PPTR: /* char* reference */ ptr = SSPOPPTR; *(char**)ptr = (char*)SSPOPPTR; @@ -936,17 +947,25 @@ Perl_cx_dump(pTHX_ PERL_CONTEXT *cx) case CXt_NULL: case CXt_BLOCK: break; - case CXt_SUB: + case CXt_FORMAT: PerlIO_printf(Perl_debug_log, "BLK_SUB.CV = 0x%"UVxf"\n", PTR2UV(cx->blk_sub.cv)); PerlIO_printf(Perl_debug_log, "BLK_SUB.GV = 0x%"UVxf"\n", PTR2UV(cx->blk_sub.gv)); PerlIO_printf(Perl_debug_log, "BLK_SUB.DFOUTGV = 0x%"UVxf"\n", PTR2UV(cx->blk_sub.dfoutgv)); + PerlIO_printf(Perl_debug_log, "BLK_SUB.HASARGS = %d\n", + (int)cx->blk_sub.hasargs); + break; + case CXt_SUB: + PerlIO_printf(Perl_debug_log, "BLK_SUB.CV = 0x%"UVxf"\n", + PTR2UV(cx->blk_sub.cv)); PerlIO_printf(Perl_debug_log, "BLK_SUB.OLDDEPTH = %ld\n", (long)cx->blk_sub.olddepth); PerlIO_printf(Perl_debug_log, "BLK_SUB.HASARGS = %d\n", (int)cx->blk_sub.hasargs); + PerlIO_printf(Perl_debug_log, "BLK_SUB.LVAL = %d\n", + (int)cx->blk_sub.lval); break; case CXt_EVAL: PerlIO_printf(Perl_debug_log, "BLK_EVAL.OLD_IN_EVAL = %ld\n", @@ -976,8 +995,8 @@ Perl_cx_dump(pTHX_ PERL_CONTEXT *cx) PerlIO_printf(Perl_debug_log, "BLK_LOOP.ITERARY = 0x%"UVxf"\n", PTR2UV(cx->blk_loop.iterary)); PerlIO_printf(Perl_debug_log, "BLK_LOOP.ITERVAR = 0x%"UVxf"\n", - PTR2UV(cx->blk_loop.itervar)); - if (cx->blk_loop.itervar) + PTR2UV(CxITERVAR(cx))); + if (CxITERVAR(cx)) PerlIO_printf(Perl_debug_log, "BLK_LOOP.ITERSAVE = 0x%"UVxf"\n", PTR2UV(cx->blk_loop.itersave)); PerlIO_printf(Perl_debug_log, "BLK_LOOP.ITERLVAL = 0x%"UVxf"\n", diff --git a/scope.h b/scope.h index 6aca9ea..6d6b013 100644 --- a/scope.h +++ b/scope.h @@ -29,6 +29,7 @@ #define SAVEt_ALLOC 28 #define SAVEt_GENERIC_SVREF 29 #define SAVEt_DESTRUCTOR_X 30 +#define SAVEt_VPTR 31 #define SSCHECK(need) if (PL_savestack_ix + need > PL_savestack_max) savestack_grow() #define SSPUSHINT(i) (PL_savestack[PL_savestack_ix++].any_i32 = (I32)(i)) @@ -77,6 +78,7 @@ #define SAVELONG(l) save_long(SOFT_CAST(long*)&(l)) #define SAVESPTR(s) save_sptr((SV**)&(s)) #define SAVEPPTR(s) save_pptr(SOFT_CAST(char**)&(s)) +#define SAVEVPTR(s) save_vptr(&(s)) #define SAVEFREESV(s) save_freesv((SV*)(s)) #define SAVEFREEOP(o) save_freeop(SOFT_CAST(OP*)(o)) #define SAVEFREEPV(p) save_freepv(SOFT_CAST(char*)(p)) diff --git a/sv.c b/sv.c index 746f929..1c6ac83 100644 --- a/sv.c +++ b/sv.c @@ -5642,11 +5642,19 @@ Perl_re_dup(pTHX_ REGEXP *r) PerlIO * Perl_fp_dup(pTHX_ PerlIO *fp, char type) { + PerlIO *ret; if (!fp) return (PerlIO*)NULL; - return fp; /* XXX */ - /* return PerlIO_fdopen(PerlIO_fileno(fp), - type == '<' ? "r" : type == '>' ? "w" : "rw"); */ + + /* look for it in the table first */ + ret = (PerlIO*)ptr_table_fetch(PL_ptr_table, fp); + if (ret) + return ret; + + /* create anew and remember what it is */ + ret = PerlIO_fdupopen(fp); + ptr_table_store(PL_ptr_table, fp, ret); + return ret; } DIR * @@ -5665,7 +5673,7 @@ Perl_gp_dup(pTHX_ GP *gp) if (!gp) return (GP*)NULL; /* look for it in the table first */ - ret = ptr_table_fetch(PL_ptr_table, gp); + ret = (GP*)ptr_table_fetch(PL_ptr_table, gp); if (ret) return ret; @@ -5696,7 +5704,10 @@ Perl_mg_dup(pTHX_ MAGIC *mg) MAGIC *mgprev; if (!mg) return (MAGIC*)NULL; - /* XXX need to handle aliases here? */ + /* look for it in the table first */ + mgret = (MAGIC*)ptr_table_fetch(PL_ptr_table, mg); + if (mgret) + return mgret; for (; mg; mg = mg->mg_moremagic) { MAGIC *nmg; @@ -5765,27 +5776,27 @@ Perl_ptr_table_fetch(pTHX_ PTR_TBL_t *tbl, void *sv) } void -Perl_ptr_table_store(pTHX_ PTR_TBL_t *tbl, void *old, void *new) +Perl_ptr_table_store(pTHX_ PTR_TBL_t *tbl, void *oldv, void *newv) { PTR_TBL_ENT_t *tblent, **otblent; /* XXX this may be pessimal on platforms where pointers aren't good * hash values e.g. if they grow faster in the most significant * bits */ - UV hash = (UV)old; + UV hash = (UV)oldv; bool i = 1; assert(tbl); otblent = &tbl->tbl_ary[hash & tbl->tbl_max]; for (tblent = *otblent; tblent; i=0, tblent = tblent->next) { - if (tblent->oldval == old) { - tblent->newval = new; + if (tblent->oldval == oldv) { + tblent->newval = newv; tbl->tbl_items++; return; } } Newz(0, tblent, 1, PTR_TBL_ENT_t); - tblent->oldval = old; - tblent->newval = new; + tblent->oldval = oldv; + tblent->newval = newv; tblent->next = *otblent; *otblent = tblent; tbl->tbl_items++; @@ -5824,7 +5835,7 @@ Perl_ptr_table_split(pTHX_ PTR_TBL_t *tbl) } #ifdef DEBUGGING -DllExport char *PL_watch_pvx; +char *PL_watch_pvx; #endif SV * @@ -5838,7 +5849,7 @@ Perl_sv_dup(pTHX_ SV *sstr) if (!sstr || SvTYPE(sstr) == SVTYPEMASK) return Nullsv; /* look for it in the table first */ - dstr = ptr_table_fetch(PL_ptr_table, sstr); + dstr = (SV*)ptr_table_fetch(PL_ptr_table, sstr); if (dstr) return dstr; @@ -5996,11 +6007,11 @@ Perl_sv_dup(pTHX_ SV *sstr) SvPVX(dstr) = SAVEPVN(SvPVX(sstr), SvLEN(sstr)-1); else SvPVX(dstr) = SvPVX(sstr); /* XXX shared string/random ptr? */ - IoIFP(dstr) = fp_dup(IoIFP(sstr), IoTYPE(sstr)); + IoIFP(dstr) = fp_dup(IoIFP(sstr), IoTYPE(sstr)); if (IoOFP(sstr) == IoIFP(sstr)) IoOFP(dstr) = IoIFP(dstr); else - IoOFP(dstr) = fp_dup(IoOFP(sstr), IoTYPE(sstr)); + IoOFP(dstr) = fp_dup(IoOFP(sstr), IoTYPE(sstr)); /* PL_rsfp_filters entries have fake IoDIRP() */ if (IoDIRP(sstr) && !(IoFLAGS(sstr) & IOf_FAKE_DIRP)) IoDIRP(dstr) = dirp_dup(IoDIRP(sstr)); @@ -6036,6 +6047,7 @@ Perl_sv_dup(pTHX_ SV *sstr) src_ary = AvARRAY((AV*)sstr); Newz(0, dst_ary, AvMAX((AV*)sstr)+1, SV*); + ptr_table_store(PL_ptr_table, src_ary, dst_ary); SvPVX(dstr) = (char*)dst_ary; AvALLOC((AV*)dstr) = dst_ary; if (AvREAL((AV*)sstr)) { @@ -6073,26 +6085,11 @@ Perl_sv_dup(pTHX_ SV *sstr) Newz(0, dxhv->xhv_array, PERL_HV_ARRAY_ALLOC_BYTES(dxhv->xhv_max+1), char); while (i <= sxhv->xhv_max) { - HE *dentry, *oentry; - entry = ((HE**)sxhv->xhv_array)[i]; - dentry = he_dup(entry, !!HvSHAREKEYS(sstr)); - ((HE**)dxhv->xhv_array)[i] = dentry; - while (entry) { - entry = HeNEXT(entry); - oentry = dentry; - dentry = he_dup(entry, !!HvSHAREKEYS(sstr)); - HeNEXT(oentry) = dentry; - } + ((HE**)dxhv->xhv_array)[i] = he_dup(((HE**)sxhv->xhv_array)[i], + !!HvSHAREKEYS(sstr)); ++i; } - if (sxhv->xhv_riter >= 0 && sxhv->xhv_eiter) { - entry = ((HE**)sxhv->xhv_array)[sxhv->xhv_riter]; - while (entry && entry != sxhv->xhv_eiter) - entry = HeNEXT(entry); - dxhv->xhv_eiter = entry; - } - else - dxhv->xhv_eiter = (HE*)NULL; + dxhv->xhv_eiter = he_dup(sxhv->xhv_eiter, !!HvSHAREKEYS(sstr)); } else { SvPVX(dstr) = Nullch; @@ -6150,26 +6147,86 @@ dup_pvcv: } PERL_CONTEXT * -Perl_cx_dup(pTHX_ PERL_CONTEXT *cx, I32 ix, I32 max) +Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max) { - PERL_CONTEXT *ncx; + PERL_CONTEXT *ncxs; - if (!cx) + if (!cxs) return (PERL_CONTEXT*)NULL; /* look for it in the table first */ - ncx = ptr_table_fetch(PL_ptr_table, cx); - if (ncx) - return ncx; + ncxs = (PERL_CONTEXT*)ptr_table_fetch(PL_ptr_table, cxs); + if (ncxs) + return ncxs; /* create anew and remember what it is */ - Newz(56, ncx, max + 1, PERL_CONTEXT); - ptr_table_store(PL_ptr_table, cx, ncx); + Newz(56, ncxs, max + 1, PERL_CONTEXT); + ptr_table_store(PL_ptr_table, cxs, ncxs); - /* XXX todo */ - /* ... */ - - return ncx; + while (ix >= 0) { + PERL_CONTEXT *cx = &cxs[ix]; + PERL_CONTEXT *ncx = &ncxs[ix]; + ncx->cx_type = cx->cx_type; + if (CxTYPE(cx) == CXt_SUBST) { + Perl_croak(aTHX_ "Cloning substitution context is unimplemented"); + } + else { + ncx->blk_oldsp = cx->blk_oldsp; + ncx->blk_oldcop = cx->blk_oldcop; + ncx->blk_oldretsp = cx->blk_oldretsp; + ncx->blk_oldmarksp = cx->blk_oldmarksp; + ncx->blk_oldscopesp = cx->blk_oldscopesp; + ncx->blk_oldpm = cx->blk_oldpm; + ncx->blk_gimme = cx->blk_gimme; + switch (CxTYPE(cx)) { + case CXt_SUB: + ncx->blk_sub.cv = (cx->blk_sub.olddepth == 0 + ? cv_dup_inc(cx->blk_sub.cv) + : cv_dup(cx->blk_sub.cv)); + ncx->blk_sub.argarray = (cx->blk_sub.hasargs + ? av_dup_inc(cx->blk_sub.argarray) + : Nullav); + ncx->blk_sub.savearray = av_dup(cx->blk_sub.savearray); + ncx->blk_sub.olddepth = cx->blk_sub.olddepth; + ncx->blk_sub.hasargs = cx->blk_sub.hasargs; + ncx->blk_sub.lval = cx->blk_sub.lval; + break; + case CXt_EVAL: + ncx->blk_eval.old_in_eval = cx->blk_eval.old_in_eval; + ncx->blk_eval.old_op_type = cx->blk_eval.old_op_type; + ncx->blk_eval.old_name = SAVEPV(cx->blk_eval.old_name); + ncx->blk_eval.old_eval_root = cx->blk_eval.old_eval_root; + ncx->blk_eval.cur_text = sv_dup(cx->blk_eval.cur_text); + break; + case CXt_LOOP: + ncx->blk_loop.label = cx->blk_loop.label; + ncx->blk_loop.resetsp = cx->blk_loop.resetsp; + ncx->blk_loop.redo_op = cx->blk_loop.redo_op; + ncx->blk_loop.next_op = cx->blk_loop.next_op; + ncx->blk_loop.last_op = cx->blk_loop.last_op; + ncx->blk_loop.iterdata = (CxPADLOOP(cx) + ? cx->blk_loop.iterdata + : gv_dup((GV*)cx->blk_loop.iterdata)); + ncx->blk_loop.itersave = sv_dup_inc(cx->blk_loop.itersave); + ncx->blk_loop.iterlval = sv_dup_inc(cx->blk_loop.iterlval); + ncx->blk_loop.iterary = av_dup_inc(cx->blk_loop.iterary); + ncx->blk_loop.iterix = cx->blk_loop.iterix; + ncx->blk_loop.itermax = cx->blk_loop.itermax; + break; + case CXt_FORMAT: + ncx->blk_sub.cv = cv_dup(cx->blk_sub.cv); + ncx->blk_sub.gv = gv_dup(cx->blk_sub.gv); + ncx->blk_sub.dfoutgv = gv_dup_inc(cx->blk_sub.dfoutgv); + ncx->blk_sub.hasargs = cx->blk_sub.hasargs; + break; + case CXt_BLOCK: + case CXt_NULL: + break; + } + } + --ix; + } + return ncxs; } PERL_SI * @@ -6181,7 +6238,7 @@ Perl_si_dup(pTHX_ PERL_SI *si) return (PERL_SI*)NULL; /* look for it in the table first */ - nsi = ptr_table_fetch(PL_ptr_table, si); + nsi = (PERL_SI*)ptr_table_fetch(PL_ptr_table, si); if (nsi) return nsi; @@ -6201,51 +6258,317 @@ Perl_si_dup(pTHX_ PERL_SI *si) return nsi; } +#define POPINT(ss,ix) ((ss)[--(ix)].any_i32) +#define TOPINT(ss,ix) ((ss)[ix].any_i32) +#define POPLONG(ss,ix) ((ss)[--(ix)].any_long) +#define TOPLONG(ss,ix) ((ss)[ix].any_long) +#define POPIV(ss,ix) ((ss)[--(ix)].any_iv) +#define TOPIV(ss,ix) ((ss)[ix].any_iv) +#define POPPTR(ss,ix) ((ss)[--(ix)].any_ptr) +#define TOPPTR(ss,ix) ((ss)[ix].any_ptr) +#define POPDPTR(ss,ix) ((ss)[--(ix)].any_dptr) +#define TOPDPTR(ss,ix) ((ss)[ix].any_dptr) +#define POPDXPTR(ss,ix) ((ss)[--(ix)].any_dxptr) +#define TOPDXPTR(ss,ix) ((ss)[ix].any_dxptr) + +/* XXXXX todo */ +#define pv_dup_inc(p) SAVEPV(p) +#define pv_dup(p) SAVEPV(p) +#define svp_dup_inc(p,pp) any_dup(p,pp) + +void * +Perl_any_dup(pTHX_ void *v, PerlInterpreter *proto_perl) +{ + void *ret; + + if (!v) + return (void*)NULL; + + /* look for it in the table first */ + ret = ptr_table_fetch(PL_ptr_table, v); + if (ret) + return ret; + + /* see if it is part of the interpreter structure */ + if (v >= (void*)proto_perl && v < (void*)(proto_perl+1)) + ret = (void*)(((char*)aTHXo) + (((char*)v) - (char*)proto_perl)); + else + ret = v; + + return ret; +} + ANY * -Perl_ss_dup(pTHX_ ANY *ss, I32 ix, I32 max) +Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl) +{ + ANY *ss = proto_perl->Tsavestack; + I32 ix = proto_perl->Tsavestack_ix; + I32 max = proto_perl->Tsavestack_max; + ANY *nss; + SV *sv; + GV *gv; + AV *av; + HV *hv; + void* ptr; + int intval; + long longval; + GP *gp; + IV iv; + I32 i; + char *c; + void (*dptr) (void*); + void (*dxptr) (pTHXo_ void*); + + Newz(54, nss, max, ANY); + + while (ix > 0) { + i = POPINT(ss,ix); + TOPINT(nss,ix) = i; + switch (i) { + case SAVEt_ITEM: /* normal string */ + sv = (SV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = sv_dup_inc(sv); + sv = (SV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = sv_dup_inc(sv); + break; + case SAVEt_SV: /* scalar reference */ + sv = (SV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = sv_dup_inc(sv); + gv = (GV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = gv_dup_inc(gv); + break; + case SAVEt_GENERIC_SVREF: /* generic sv */ + case SAVEt_SVREF: /* scalar reference */ + sv = (SV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = sv_dup_inc(sv); + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = svp_dup_inc((SV**)ptr, proto_perl);/* XXXXX */ + break; + case SAVEt_AV: /* array reference */ + av = (AV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = av_dup_inc(av); + gv = (GV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = gv_dup(gv); + break; + case SAVEt_HV: /* hash reference */ + hv = (HV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = hv_dup_inc(hv); + gv = (GV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = gv_dup(gv); + break; + case SAVEt_INT: /* int reference */ + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = any_dup(ptr, proto_perl); + intval = (int)POPINT(ss,ix); + TOPINT(nss,ix) = intval; + break; + case SAVEt_LONG: /* long reference */ + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = any_dup(ptr, proto_perl); + longval = (long)POPLONG(ss,ix); + TOPLONG(nss,ix) = longval; + break; + case SAVEt_I32: /* I32 reference */ + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = any_dup(ptr, proto_perl); + i = POPINT(ss,ix); + TOPINT(nss,ix) = i; + break; + case SAVEt_I16: /* I16 reference */ + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = any_dup(ptr, proto_perl); + i = POPINT(ss,ix); + TOPINT(nss,ix) = i; + break; + case SAVEt_IV: /* IV reference */ + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = any_dup(ptr, proto_perl); + iv = POPIV(ss,ix); + TOPIV(nss,ix) = iv; + break; + case SAVEt_SPTR: /* SV* reference */ + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = any_dup(ptr, proto_perl); + sv = (SV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = sv_dup(sv); + break; + case SAVEt_VPTR: /* random* reference */ + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = any_dup(ptr, proto_perl); + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = any_dup(ptr, proto_perl); + break; + case SAVEt_PPTR: /* char* reference */ + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = any_dup(ptr, proto_perl); + c = (char*)POPPTR(ss,ix); + TOPPTR(nss,ix) = pv_dup(c); + break; + case SAVEt_HPTR: /* HV* reference */ + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = any_dup(ptr, proto_perl); + hv = (HV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = hv_dup(hv); + break; + case SAVEt_APTR: /* AV* reference */ + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = any_dup(ptr, proto_perl); + av = (AV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = av_dup(av); + break; + case SAVEt_NSTAB: + gv = (GV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = gv_dup(gv); + break; + case SAVEt_GP: /* scalar reference */ + gp = (GP*)POPPTR(ss,ix); + TOPPTR(nss,ix) = gp = gp_dup(gp); + (void)GpREFCNT_inc(gp); + gv = (GV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = gv_dup_inc(c); + c = (char*)POPPTR(ss,ix); + TOPPTR(nss,ix) = pv_dup(c); + iv = POPIV(ss,ix); + TOPIV(nss,ix) = iv; + iv = POPIV(ss,ix); + TOPIV(nss,ix) = iv; + break; + case SAVEt_FREESV: + sv = (SV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = sv_dup_inc(sv); + break; + case SAVEt_FREEOP: + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = ptr; + break; + case SAVEt_FREEPV: + c = (char*)POPPTR(ss,ix); + TOPPTR(nss,ix) = pv_dup_inc(c); + break; + case SAVEt_CLEARSV: + longval = POPLONG(ss,ix); + TOPLONG(nss,ix) = longval; + break; + case SAVEt_DELETE: + hv = (HV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = hv_dup_inc(hv); + c = (char*)POPPTR(ss,ix); + TOPPTR(nss,ix) = pv_dup_inc(c); + i = POPINT(ss,ix); + TOPINT(nss,ix) = i; + break; + case SAVEt_DESTRUCTOR: + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = any_dup(ptr, proto_perl); /* XXX quite arbitrary */ + dptr = POPDPTR(ss,ix); + TOPDPTR(nss,ix) = (void (*)(void*))any_dup(dptr, proto_perl); + break; + case SAVEt_DESTRUCTOR_X: + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = any_dup(ptr, proto_perl); /* XXX quite arbitrary */ + dxptr = POPDXPTR(ss,ix); + TOPDXPTR(nss,ix) = (void (*)(pTHXo_ void*))any_dup(dxptr, proto_perl); + break; + case SAVEt_REGCONTEXT: + case SAVEt_ALLOC: + i = POPINT(ss,ix); + TOPINT(nss,ix) = i; + ix -= i; + break; + case SAVEt_STACK_POS: /* Position on Perl stack */ + i = POPINT(ss,ix); + TOPINT(nss,ix) = i; + break; + case SAVEt_AELEM: /* array element */ + sv = (SV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = sv_dup_inc(sv); + i = POPINT(ss,ix); + TOPINT(nss,ix) = i; + av = (AV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = av_dup_inc(av); + break; + case SAVEt_HELEM: /* hash element */ + sv = (SV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = sv_dup_inc(sv); + sv = (SV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = sv_dup_inc(sv); + hv = (HV*)POPPTR(ss,ix); + TOPPTR(nss,ix) = hv_dup_inc(hv); + break; + case SAVEt_OP: + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = ptr; + break; + case SAVEt_HINTS: + i = POPINT(ss,ix); + TOPINT(nss,ix) = i; + break; + default: + Perl_croak(aTHX_ "panic: ss_dup inconsistency"); + } + } + + return nss; +} + +#ifdef PERL_OBJECT +#include "XSUB.h" +#endif + +PerlInterpreter * +perl_clone(PerlInterpreter *my_perl, UV flags) { - /* XXX todo */ - return NULL; +#ifdef PERL_OBJECT + CPerlObj *pPerl = (CPerlObj*)my_perl; +#endif + return perl_clone_using(my_perl, flags, PL_Mem, PL_MemShared, PL_MemParse, + PL_Env, PL_StdIO, PL_LIO, PL_Dir, PL_Sock, PL_Proc); } PerlInterpreter * perl_clone_using(PerlInterpreter *proto_perl, UV flags, - struct IPerlMem* ipM, struct IPerlEnv* ipE, + struct IPerlMem* ipM, struct IPerlMem* ipMS, + struct IPerlMem* ipMP, struct IPerlEnv* ipE, struct IPerlStdIO* ipStd, struct IPerlLIO* ipLIO, struct IPerlDir* ipD, struct IPerlSock* ipS, struct IPerlProc* ipP) { + /* XXX many of the string copies here can be optimized if they're + * constants; they need to be allocated as common memory and just + * their pointers copied. */ + IV i; SV *sv; SV **svp; +#ifdef PERL_OBJECT + CPerlObj *pPerl = new(ipM) CPerlObj(ipM, ipMS, ipMP, ipE, ipStd, ipLIO, + ipD, ipS, ipP); + PERL_SET_INTERP(pPerl); +#else PerlInterpreter *my_perl = (PerlInterpreter*)(*ipM->pMalloc)(ipM, sizeof(PerlInterpreter)); PERL_SET_INTERP(my_perl); -#ifdef DEBUGGING +# ifdef DEBUGGING memset(my_perl, 0xab, sizeof(PerlInterpreter)); PL_markstack = 0; PL_scopestack = 0; PL_savestack = 0; PL_retstack = 0; -#else +# else Zero(my_perl, 1, PerlInterpreter); -# if 0 - Copy(proto_perl, my_perl, 1, PerlInterpreter); # endif -#endif - - /* XXX many of the string copies here can be optimized if they're - * constants; they need to be allocated as common memory and just - * their pointers copied. */ /* host pointers */ PL_Mem = ipM; + PL_MemShared = ipMS; + PL_MemParse = ipMP; PL_Env = ipE; PL_StdIO = ipStd; PL_LIO = ipLIO; PL_Dir = ipD; PL_Sock = ipS; PL_Proc = ipP; +#endif /* arena roots */ PL_xiv_arenaroot = NULL; @@ -6280,7 +6603,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, SvFLAGS(&PL_sv_undef) = SVf_READONLY|SVt_NULL; ptr_table_store(PL_ptr_table, &proto_perl->Isv_undef, &PL_sv_undef); +#ifdef PERL_OBJECT + SvUPGRADE(&PL_sv_no, SVt_PVNV); +#else SvANY(&PL_sv_no) = new_XPVNV(); +#endif SvREFCNT(&PL_sv_no) = (~(U32)0)/2; SvFLAGS(&PL_sv_no) = SVp_NOK|SVf_NOK|SVp_POK|SVf_POK|SVf_READONLY|SVt_PVNV; SvPVX(&PL_sv_no) = SAVEPVN(PL_No, 0); @@ -6289,7 +6616,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, SvNVX(&PL_sv_no) = 0; ptr_table_store(PL_ptr_table, &proto_perl->Isv_no, &PL_sv_no); +#ifdef PERL_OBJECT + SvUPGRADE(&PL_sv_yes, SVt_PVNV); +#else SvANY(&PL_sv_yes) = new_XPVNV(); +#endif SvREFCNT(&PL_sv_yes) = (~(U32)0)/2; SvFLAGS(&PL_sv_yes) = SVp_NOK|SVf_NOK|SVp_POK|SVf_POK|SVf_READONLY|SVt_PVNV; SvPVX(&PL_sv_yes) = SAVEPVN(PL_Yes, 1); @@ -6307,12 +6638,10 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_compiling = proto_perl->Icompiling; PL_compiling.cop_stashpv = SAVEPV(PL_compiling.cop_stashpv); PL_compiling.cop_file = SAVEPV(PL_compiling.cop_file); + ptr_table_store(PL_ptr_table, &proto_perl->Icompiling, &PL_compiling); if (!specialWARN(PL_compiling.cop_warnings)) PL_compiling.cop_warnings = sv_dup_inc(PL_compiling.cop_warnings); - if (proto_perl->Tcurcop == &proto_perl->Icompiling) - PL_curcop = &PL_compiling; - else - PL_curcop = proto_perl->Tcurcop; + PL_curcop = (COP*)any_dup(proto_perl->Tcurcop, proto_perl); /* pseudo environmental stuff */ PL_origargc = proto_perl->Iorigargc; @@ -6418,14 +6747,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_main_cv = cv_dup_inc(proto_perl->Imain_cv); PL_main_root = OpREFCNT_inc(proto_perl->Imain_root); PL_main_start = proto_perl->Imain_start; - PL_eval_root = proto_perl->Ieval_root; + PL_eval_root = OpREFCNT_inc(proto_perl->Ieval_root); PL_eval_start = proto_perl->Ieval_start; /* runtime control stuff */ - if (proto_perl->Icurcopdb == &proto_perl->Icompiling) - PL_curcopdb = &PL_compiling; - else - PL_curcopdb = proto_perl->Icurcopdb; + PL_curcopdb = (COP*)any_dup(proto_perl->Icurcopdb, proto_perl); PL_copline = proto_perl->Icopline; PL_filemode = proto_perl->Ifilemode; @@ -6464,7 +6790,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_comppad_name = av_dup(proto_perl->Icomppad_name); PL_comppad_name_fill = proto_perl->Icomppad_name_fill; PL_comppad_name_floor = proto_perl->Icomppad_name_floor; - PL_curpad = PL_comppad ? AvARRAY(PL_comppad) : (SV**)NULL; + PL_curpad = (SV**)ptr_table_fetch(PL_ptr_table, + proto_perl->Tcurpad); #ifdef HAVE_INTERP_INTERN sys_intern_dup(&proto_perl->Isys_intern, &PL_sys_intern); @@ -6610,7 +6937,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_last_swash_hv = Nullhv; /* reinits on demand */ PL_last_swash_klen = 0; PL_last_swash_key[0]= '\0'; - PL_last_swash_tmps = Nullch; + PL_last_swash_tmps = (U8*)NULL; PL_last_swash_slen = 0; /* perly.c globals */ @@ -6626,6 +6953,19 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_uudmap['M'] = 0; /* reinits on demand */ PL_bitcount = Nullch; /* reinits on demand */ + if (proto_perl->Ipsig_ptr) { + int sig_num[] = { SIG_NUM }; + Newz(0, PL_psig_ptr, sizeof(sig_num)/sizeof(*sig_num), SV*); + Newz(0, PL_psig_name, sizeof(sig_num)/sizeof(*sig_num), SV*); + for (i = 1; PL_sig_name[i]; i++) { + PL_psig_ptr[i] = sv_dup_inc(proto_perl->Ipsig_ptr[i]); + PL_psig_name[i] = sv_dup_inc(proto_perl->Ipsig_name[i]); + } + } + else { + PL_psig_ptr = (SV**)NULL; + PL_psig_name = (SV**)NULL; + } /* thrdvar.h stuff */ @@ -6658,15 +6998,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, Newz(54, PL_scopestack, PL_scopestack_max, I32); Copy(proto_perl->Tscopestack, PL_scopestack, PL_scopestack_ix, I32); - /* next SSPUSHFOO() sets PL_savestack[PL_savestack_ix] - * NOTE: unlike the others! */ - PL_savestack_ix = proto_perl->Tsavestack_ix; - PL_savestack_max = proto_perl->Tsavestack_max; - /*Newz(54, PL_savestack, PL_savestack_max, ANY);*/ - PL_savestack = ss_dup(proto_perl->Tsavestack, - PL_savestack_ix, - PL_savestack_max); - /* next push_return() sets PL_retstack[PL_retstack_ix] * NOTE: unlike the others! */ PL_retstack_ix = proto_perl->Tretstack_ix; @@ -6686,6 +7017,13 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_stack_sp = PL_stack_base + (proto_perl->Tstack_sp - proto_perl->Tstack_base); PL_stack_max = PL_stack_base + AvMAX(PL_curstack); + + /* next SSPUSHFOO() sets PL_savestack[PL_savestack_ix] + * NOTE: unlike the others! */ + PL_savestack_ix = proto_perl->Tsavestack_ix; + PL_savestack_max = proto_perl->Tsavestack_max; + /*Newz(54, PL_savestack, PL_savestack_max, ANY);*/ + PL_savestack = ss_dup(proto_perl); } else { init_stacks(); @@ -6736,10 +7074,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_lastgotoprobe = Nullop; PL_dumpindent = proto_perl->Tdumpindent; - if (proto_perl->Tsortcop == (OP*)&proto_perl->Icompiling) - PL_sortcop = (OP*)&PL_compiling; - else - PL_sortcop = proto_perl->Tsortcop; + PL_sortcop = (OP*)any_dup(proto_perl->Tsortcop, proto_perl); PL_sortstash = hv_dup(proto_perl->Tsortstash); PL_firstgv = gv_dup(proto_perl->Tfirstgv); PL_secondgv = gv_dup(proto_perl->Tsecondgv); @@ -6818,22 +7153,21 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_reginterp_cnt = 0; PL_reg_starttry = 0; +#ifdef PERL_OBJECT + return (PerlInterpreter*)pPerl; +#else return my_perl; +#endif } -PerlInterpreter * -perl_clone(pTHXx_ UV flags) -{ - return perl_clone_using(aTHXx_ flags, PL_Mem, PL_Env, PL_StdIO, PL_LIO, - PL_Dir, PL_Sock, PL_Proc); -} - -#endif /* USE_ITHREADS */ +#else /* !USE_ITHREADS */ #ifdef PERL_OBJECT #include "XSUB.h" #endif +#endif /* USE_ITHREADS */ + static void do_report_used(pTHXo_ SV *sv) { diff --git a/t/op/fork.t b/t/op/fork.t index 20c8747..be95653 100755 --- a/t/op/fork.t +++ b/t/op/fork.t @@ -1,26 +1,315 @@ #!./perl -# $RCSfile: fork.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:53 $ +# tests for both real and emulated fork() BEGIN { chdir 't' if -d 't'; unshift @INC, '../lib'; require Config; import Config; - unless ($Config{'d_fork'}) { + unless ($Config{'d_fork'} || $Config{ccflags} =~ /-DUSE_ITHREADS\b/) { print "1..0 # Skip: no fork\n"; exit 0; } + $ENV{PERL5LIB} = "../lib"; } -$| = 1; -print "1..2\n"; +$|=1; + +undef $/; +@prgs = split "\n########\n", ; +print "1..", scalar @prgs, "\n"; + +$tmpfile = "forktmp000"; +1 while -f ++$tmpfile; +END { unlink $tmpfile if $tmpfile; } + +$CAT = (($^O eq 'MSWin32') ? '.\perl -e "print <>"' : 'cat'); +for (@prgs){ + my $switch; + if (s/^\s*(-\w.*)//){ + $switch = $1; + } + my($prog,$expected) = split(/\nEXPECT\n/, $_); + $expected =~ s/\n+$//; + # results can be in any order, so sort 'em + my @expected = sort split /\n/, $expected; + open TEST, ">$tmpfile" or die "Cannot open $tmpfile: $!"; + print TEST $prog, "\n"; + close TEST or die "Cannot close $tmpfile: $!"; + my $results; + if ($^O eq 'MSWin32') { + $results = `.\\perl -I../lib $switch $tmpfile 2>&1`; + } + else { + $results = `./perl $switch $tmpfile 2>&1`; + } + $status = $?; + $results =~ s/\n+$//; + $results =~ s/at\s+forktmp\d+\s+line/at - line/g; + $results =~ s/of\s+forktmp\d+\s+aborted/of - aborted/g; +# bison says 'parse error' instead of 'syntax error', +# various yaccs may or may not capitalize 'syntax'. + $results =~ s/^(syntax|parse) error/syntax error/mig; + my @results = sort split /\n/, $results; + if ( "@results" ne "@expected" ) { + print STDERR "PROG: $switch\n$prog\n"; + print STDERR "EXPECTED:\n$expected\n"; + print STDERR "GOT:\n$results\n"; + print "not "; + } + print "ok ", ++$i, "\n"; +} + +__END__ +$| = 1; if ($cid = fork) { - sleep 2; - if ($result = (kill 9, $cid)) {print "ok 2\n";} else {print "not ok 2 $result\n";} + sleep 1; + if ($result = (kill 9, $cid)) { + print "ok 2\n"; + } + else { + print "not ok 2 $result\n"; + } + sleep 1 if $^O eq 'MSWin32'; # avoid WinNT race bug } else { - $| = 1; print "ok 1\n"; sleep 10; } +EXPECT +ok 1 +ok 2 +######## +$| = 1; +sub forkit { + print "iteration $i start\n"; + my $x = fork; + if (defined $x) { + if ($x) { + print "iteration $i parent\n"; + } + else { + print "iteration $i child\n"; + } + } + else { + print "pid $$ failed to fork\n"; + } +} +while ($i++ < 3) { do { forkit(); }; } +EXPECT +iteration 1 start +iteration 1 parent +iteration 1 child +iteration 2 start +iteration 2 parent +iteration 2 child +iteration 2 start +iteration 2 parent +iteration 2 child +iteration 3 start +iteration 3 parent +iteration 3 child +iteration 3 start +iteration 3 parent +iteration 3 child +iteration 3 start +iteration 3 parent +iteration 3 child +iteration 3 start +iteration 3 parent +iteration 3 child +######## +$| = 1; +fork() + ? (print("parent\n"),sleep(1)) + : (print("child\n"),exit) ; +EXPECT +parent +child +######## +$| = 1; +fork() + ? (print("parent\n"),exit) + : (print("child\n"),sleep(1)) ; +EXPECT +parent +child +######## +$| = 1; +@a = (1..3); +for (@a) { + if (fork) { + print "parent $_\n"; + $_ = "[$_]"; + } + else { + print "child $_\n"; + $_ = "-$_-"; + } +} +print "@a\n"; +EXPECT +parent 1 +child 1 +parent 2 +child 2 +parent 2 +child 2 +parent 3 +child 3 +parent 3 +child 3 +parent 3 +child 3 +parent 3 +child 3 +[1] [2] [3] +-1- [2] [3] +[1] -2- [3] +[1] [2] -3- +-1- -2- [3] +-1- [2] -3- +[1] -2- -3- +-1- -2- -3- +######## +use Config; +$| = 1; +$\ = "\n"; +fork() + ? print($Config{osname} eq $^O) + : print($Config{osname} eq $^O) ; +EXPECT +1 +1 +######## +$| = 1; +$\ = "\n"; +fork() + ? do { require Config; print($Config::Config{osname} eq $^O); } + : do { require Config; print($Config::Config{osname} eq $^O); } +EXPECT +1 +1 +######## +$| = 1; +use Cwd; +$\ = "\n"; +my $dir; +if (fork) { + $dir = "f$$.tst"; + mkdir $dir, 0755; + chdir $dir; + print cwd() =~ /\Q$dir/i ? "ok 1 parent" : "not ok 1 parent"; + chdir ".."; + rmdir $dir; +} +else { + sleep 2; + $dir = "f$$.tst"; + mkdir $dir, 0755; + chdir $dir; + print cwd() =~ /\Q$dir/i ? "ok 1 child" : "not ok 1 child"; + chdir ".."; + rmdir $dir; +} +EXPECT +ok 1 parent +ok 1 child +######## +$| = 1; +$\ = "\n"; +my $getenv; +if ($^O eq 'MSWin32') { + $getenv = qq[$^X -e "print \$ENV{TST}"]; +} +else { + $getenv = qq[$^X -e 'print \$ENV{TST}']; +} +if (fork) { + sleep 1; + $ENV{TST} = 'foo'; + print "parent: " . `$getenv`; +} +else { + $ENV{TST} = 'bar'; + print "child: " . `$getenv`; + sleep 1; +} +EXPECT +parent: foo +child: bar +######## +$| = 1; +$\ = "\n"; +if ($pid = fork) { + waitpid($pid,0); + print "parent got $?" +} +else { + exit(42); +} +EXPECT +parent got 10752 +######## +$| = 1; +$\ = "\n"; +my $echo = 'echo'; +if ($pid = fork) { + waitpid($pid,0); + print "parent got $?" +} +else { + exec("$echo foo"); +} +EXPECT +foo +parent got 0 +######## +if (fork) { + die "parent died"; +} +else { + die "child died"; +} +EXPECT +parent died at - line 2. +child died at - line 5. +######## +if ($pid = fork) { + eval { die "parent died" }; + print $@; +} +else { + eval { die "child died" }; + print $@; +} +EXPECT +parent died at - line 2. +child died at - line 6. +######## +if (eval q{$pid = fork}) { + eval q{ die "parent died" }; + print $@; +} +else { + eval q{ die "child died" }; + print $@; +} +EXPECT +parent died at (eval 2) line 1. +child died at (eval 2) line 1. +######## +BEGIN { + $| = 1; + fork and exit; + print "inner\n"; +} +# XXX In emulated fork(), the child will not execute anything after +# the BEGIN block, due to difficulties in recreating the parse stacks +# and restarting yyparse() midstream in the child. This can potentially +# be overcome by treating what's after the BEGIN{} as a brand new parse. +#print "outer\n" +EXPECT +inner diff --git a/toke.c b/toke.c index 4053c81..b4377d1 100644 --- a/toke.c +++ b/toke.c @@ -364,7 +364,7 @@ Perl_lex_start(pTHX_ SV *line) SAVEI32(PL_lex_casemods); SAVEI32(PL_lex_starts); SAVEI32(PL_lex_state); - SAVESPTR(PL_lex_inpat); + SAVEVPTR(PL_lex_inpat); SAVEI32(PL_lex_inwhat); SAVECOPLINE(PL_curcop); SAVEPPTR(PL_bufptr); @@ -967,7 +967,7 @@ S_sublex_push(pTHX) SAVEI32(PL_lex_casemods); SAVEI32(PL_lex_starts); SAVEI32(PL_lex_state); - SAVESPTR(PL_lex_inpat); + SAVEVPTR(PL_lex_inpat); SAVEI32(PL_lex_inwhat); SAVECOPLINE(PL_curcop); SAVEPPTR(PL_bufptr); @@ -6886,10 +6886,10 @@ Perl_start_subparse(pTHX_ I32 is_format, U32 flags) if (PL_compcv) { assert(SvTYPE(PL_compcv) == SVt_PVCV); } - save_I32(&PL_subline); + SAVEI32(PL_subline); save_item(PL_subname); SAVEI32(PL_padix); - SAVESPTR(PL_curpad); + SAVEVPTR(PL_curpad); SAVESPTR(PL_comppad); SAVESPTR(PL_comppad_name); SAVESPTR(PL_compcv); diff --git a/unixish.h b/unixish.h index 2d37fbe..f4fe177 100644 --- a/unixish.h +++ b/unixish.h @@ -99,7 +99,7 @@ #ifndef SIGILL # define SIGILL 6 /* blech */ #endif -#define ABORT() kill(getpid(),SIGABRT); +#define ABORT() kill(PerlProc_getpid(),SIGABRT); /* * fwrite1() should be a routine with the same calling sequence as fwrite(), diff --git a/util.c b/util.c index e131a5b..5eb6471 100644 --- a/util.c +++ b/util.c @@ -2302,7 +2302,7 @@ Perl_my_popen(pTHX_ char *cmd, char *mode) #endif /* defined OS2 */ /*SUPPRESS 560*/ if (tmpgv = gv_fetchpv("$",TRUE, SVt_PV)) - sv_setiv(GvSV(tmpgv), getpid()); + sv_setiv(GvSV(tmpgv), PerlProc_getpid()); PL_forkprocess = 0; hv_clear(PL_pidstatus); /* we have no children */ return Nullfp; @@ -2497,7 +2497,7 @@ Perl_rsignal_state(pTHX_ int signo) oldsig = PerlProc_signal(signo, sig_trap); PerlProc_signal(signo, oldsig); if (sig_trapped) - PerlProc_kill(getpid(), signo); + PerlProc_kill(PerlProc_getpid(), signo); return oldsig; } diff --git a/vos/vosish.h b/vos/vosish.h index fc53dc1..1648702 100644 --- a/vos/vosish.h +++ b/vos/vosish.h @@ -99,7 +99,7 @@ #ifndef SIGILL # define SIGILL 6 /* blech */ #endif -#define ABORT() kill(getpid(),SIGABRT); +#define ABORT() kill(PerlProc_getpid(),SIGABRT); /* * fwrite1() should be a routine with the same calling sequence as fwrite(), diff --git a/win32/Makefile b/win32/Makefile index c4bb568..fe38d99 100644 --- a/win32/Makefile +++ b/win32/Makefile @@ -65,6 +65,21 @@ INST_ARCH = \$(ARCHNAME) #USE_OBJECT = define # +# XXX WARNING! This option currently undergoing changes. May be broken. +# +# Beginnings of interpreter cloning/threads: still rather rough, fails +# tests. This should be enabled to get the fork() emulation. Do not +# enable unless you know what you're doing! +# +USE_ITHREADS = define + +# +# uncomment to enable the implicit "host" layer for all system calls +# made by perl. This is needed and auto-enabled by USE_OBJECT above. +# +USE_IMP_SYS = define + +# # uncomment one of the following lines if you are using either # Visual C++ 2.x or Visual C++ 6.x (aka Visual Studio 98) # @@ -84,6 +99,7 @@ INST_ARCH = \$(ARCHNAME) # and follow the directions in the package to install. # #USE_PERLCRT = define +#BUILD_FOR_WIN95 = define # # uncomment to enable linking with setargv.obj under the Visual C @@ -145,10 +161,8 @@ CCLIBDIR = $(CCHOME)\lib # #BUILDOPT = $(BUILDOPT) -DPERL_INTERNAL_GLOB -# Beginnings of interpreter cloning/threads: still rather rough, fails -# many tests. Do not enable unless you know what you're doing! -# -#BUILDOPT = $(BUILDOPT) -DUSE_ITHREADS +# Enabling this runs a cloned toplevel interpreter (fails tests) +#BUILDOPT = $(BUILDOPT) -DTOP_CLONE # specify semicolon-separated list of extra directories that modules will # look for libraries (spaces in path names need not be quoted) @@ -178,6 +192,7 @@ CRYPT_FLAG = -DHAVE_DES_FCRYPT PERL_MALLOC = undef USE_THREADS = undef USE_MULTI = undef +USE_IMP_SYS = define !ENDIF !IF "$(PERL_MALLOC)" == "" @@ -188,6 +203,10 @@ PERL_MALLOC = undef USE_THREADS = undef !ENDIF +!IF "$(USE_THREADS)" == "define" +USE_ITHREADS = undef +!ENDIF + !IF "$(USE_MULTI)" == "" USE_MULTI = undef !ENDIF @@ -196,10 +215,26 @@ USE_MULTI = undef USE_OBJECT = undef !ENDIF +!IF "$(USE_ITHREADS)" == "" +USE_ITHREADS = undef +!ENDIF + +!IF "$(USE_IMP_SYS)" == "" +USE_IMP_SYS = undef +!ENDIF + !IF "$(USE_MULTI)$(USE_THREADS)$(USE_OBJECT)" != "undefundefundef" BUILDOPT = $(BUILDOPT) -DPERL_IMPLICIT_CONTEXT !ENDIF +!IF "$(USE_ITHREADS)" != "undef" +BUILDOPT = $(BUILDOPT) -DUSE_ITHREADS +!ENDIF + +!IF "$(USE_IMP_SYS)" != "undef" +BUILDOPT = $(BUILDOPT) -DPERL_IMPLICIT_SYS +!ENDIF + !IF "$(PROCESSOR_ARCHITECTURE)" == "" PROCESSOR_ARCHITECTURE = x86 !ENDIF @@ -365,6 +400,7 @@ PERLDLL = ..\perl.dll MINIPERL = ..\miniperl.exe MINIDIR = .\mini PERLEXE = ..\perl.exe +WPERLEXE = ..\wperl.exe GLOBEXE = ..\perlglob.exe CONFIGPM = ..\lib\Config.pm MINIMOD = ..\lib\ExtUtils\Miniperl.pm @@ -404,7 +440,7 @@ MAKE = nmake -nologo CFGSH_TMPL = config.vc CFGH_TMPL = config_H.vc -!IF "$(USE_PERLCRT)" == "" +!IF "$(BUILD_FOR_WIN95)" == "define" PERL95EXE = ..\perl95.exe !ENDIF @@ -527,7 +563,10 @@ CORE_NOCFG_H = \ .\include\dirent.h \ .\include\netdb.h \ .\include\sys\socket.h \ - .\win32.h + .\win32.h \ + .\perlhost.h \ + .\vdir.h \ + .\vmem.h CORE_H = $(CORE_NOCFG_H) .\config.h @@ -727,6 +766,12 @@ $(MINICORE_OBJ) : $(CORE_NOCFG_H) $(MINIWIN32_OBJ) : $(CORE_NOCFG_H) $(CC) -c $(CFLAGS) $(OBJOUT_FLAG)$@ $(*F).c +# -DPERL_IMPLICIT_SYS needs C++ for perllib.c +!IF "$(USE_IMP_SYS)$(USE_OBJECT)" == "defineundef" +perllib$(o) : perllib.c + $(CC) -c -I. $(CFLAGS_O) $(CXX_FLAG) $(OBJOUT_FLAG)$@ perllib.c +!ENDIF + # 1. we don't want to rebuild miniperl.exe when config.h changes # 2. we don't want to rebuild miniperl.exe with non-default config.h $(MINI_OBJ) : $(CORE_NOCFG_H) @@ -781,10 +826,12 @@ perlmain$(o) : perlmain.c $(PERLEXE): $(PERLDLL) $(CONFIGPM) $(PERLEXE_OBJ) $(LINK32) -subsystem:console -out:$@ $(LINK_FLAGS) $(LIBFILES) \ $(PERLEXE_OBJ) $(SETARGV_OBJ) $(PERLIMPLIB) + copy $(PERLEXE) $(WPERLEXE) + editbin /subsystem:windows $(WPERLEXE) copy splittree.pl .. $(MINIPERL) -I..\lib ..\splittree.pl "../LIB" $(AUTODIR) -!IF "$(USE_PERLCRT)" == "" +!IF "$(BUILD_FOR_WIN95)" == "define" perl95.c : runperl.c copy runperl.c perl95.c @@ -977,9 +1024,10 @@ install : all installbare installhtml installbare : utils $(PERLEXE) ..\installperl -!IF "$(USE_PERLCRT)" == "" +!IF "$(BUILD_FOR_WIN95)" == "define" $(XCOPY) $(PERL95EXE) $(INST_BIN)\*.* !ENDIF + if exist $(WPERLEXE) $(XCOPY) $(WPERLEXE) $(INST_BIN)\*.* $(XCOPY) $(GLOBEXE) $(INST_BIN)\*.* $(XCOPY) bin\*.bat $(INST_SCRIPT)\*.* @@ -1025,6 +1073,7 @@ clean : -@erase /f config.h -@erase $(GLOBEXE) -@erase $(PERLEXE) + -@erase $(WPERLEXE) -@erase $(PERLDLL) -@erase $(CORE_OBJ) -rmdir /s /q $(MINIDIR) || rmdir /s $(MINIDIR) diff --git a/win32/makefile.mk b/win32/makefile.mk index 2550611..b5e1d19 100644 --- a/win32/makefile.mk +++ b/win32/makefile.mk @@ -70,6 +70,21 @@ INST_ARCH *= \$(ARCHNAME) #USE_OBJECT *= define # +# XXX WARNING! This option currently undergoing changes. May be broken. +# +# Beginnings of interpreter cloning/threads: still rather rough, fails +# tests. This should be enabled to get the fork() emulation. Do not +# enable unless you know what you're doing! +# +USE_ITHREADS *= define + +# +# uncomment to enable the implicit "host" layer for all system calls +# made by perl. This is needed and auto-enabled by USE_OBJECT above. +# +USE_IMP_SYS *= define + +# # uncomment exactly one of the following # # Visual C++ 2.x @@ -165,6 +180,9 @@ CCLIBDIR *= $(CCHOME)\lib # #BUILDOPT += -DPERL_INTERNAL_GLOB +# Enabling this runs a cloned toplevel interpreter (fails tests) +#BUILDOPT += -DTOP_CLONE + # # specify semicolon-separated list of extra directories that modules will # look for libraries (spaces in path names need not be quoted) @@ -200,18 +218,33 @@ CRYPT_FLAG = -DHAVE_DES_FCRYPT PERL_MALLOC != undef USE_THREADS != undef USE_MULTI != undef +USE_IMP_SYS != define .ENDIF PERL_MALLOC *= undef USE_THREADS *= undef + +.IF "$(USE_THREADS)" == "define" +USE_ITHREADS != undef +.ENDIF + USE_MULTI *= undef USE_OBJECT *= undef +USE_ITHREADS *= undef +USE_IMP_SYS *= undef .IF "$(USE_MULTI)$(USE_THREADS)$(USE_OBJECT)" != "undefundefundef" BUILDOPT += -DPERL_IMPLICIT_CONTEXT .ENDIF +.IF "$(USE_ITHREADS)" != "undef" +BUILDOPT += -DUSE_ITHREADS +.ENDIF + +.IF "$(USE_IMP_SYS)" != "undef" +BUILDOPT += -DPERL_IMPLICIT_SYS +.ENDIF .IMPORT .IGNORE : PROCESSOR_ARCHITECTURE @@ -459,6 +492,7 @@ $(o).dll: MINIPERL = ..\miniperl.exe MINIDIR = .\mini PERLEXE = ..\perl.exe +WPERLEXE = ..\wperl.exe GLOBEXE = ..\perlglob.exe CONFIGPM = ..\lib\Config.pm MINIMOD = ..\lib\ExtUtils\Miniperl.pm @@ -644,7 +678,10 @@ CORE_NOCFG_H = \ .\include\dirent.h \ .\include\netdb.h \ .\include\sys\socket.h \ - .\win32.h + .\win32.h \ + .\perlhost.h \ + .\vdir.h \ + .\vmem.h CORE_H = $(CORE_NOCFG_H) .\config.h @@ -870,6 +907,12 @@ $(MINICORE_OBJ) : $(CORE_NOCFG_H) $(MINIWIN32_OBJ) : $(CORE_NOCFG_H) $(CC) -c $(CFLAGS) $(OBJOUT_FLAG)$@ $(*B).c +# -DPERL_IMPLICIT_SYS needs C++ for perllib.c +.IF "$(USE_IMP_SYS)$(USE_OBJECT)" == "defineundef" +perllib$(o) : perllib.c + $(CC) -c -I. $(CFLAGS_O) $(CXX_FLAG) $(OBJOUT_FLAG)$@ perllib.c +.ENDIF + # 1. we don't want to rebuild miniperl.exe when config.h changes # 2. we don't want to rebuild miniperl.exe with non-default config.h $(MINI_OBJ) : $(CORE_NOCFG_H) @@ -959,6 +1002,8 @@ $(PERLEXE): $(PERLDLL) $(CONFIGPM) $(PERLEXE_OBJ) .ELSE $(LINK32) -subsystem:console -out:$@ $(LINK_FLAGS) $(LIBFILES) \ $(PERLEXE_OBJ) $(SETARGV_OBJ) $(PERLIMPLIB) + copy $(PERLEXE) $(WPERLEXE) + editbin /subsystem:windows $(WPERLEXE) .ENDIF copy splittree.pl .. $(MINIPERL) -I..\lib ..\splittree.pl "../LIB" $(AUTODIR) @@ -1137,6 +1182,7 @@ installbare : utils .IF "$(PERL95EXE)" != "" $(XCOPY) $(PERL95EXE) $(INST_BIN)\*.* .ENDIF + if exist $(WPERLEXE) $(XCOPY) $(WPERLEXE) $(INST_BIN)\*.* $(XCOPY) $(GLOBEXE) $(INST_BIN)\*.* $(XCOPY) bin\*.bat $(INST_SCRIPT)\*.* @@ -1185,6 +1231,7 @@ clean : -@erase /f config.h -@erase $(GLOBEXE) -@erase $(PERLEXE) + -@erase $(WPERLEXE) -@erase $(PERLDLL) -@erase $(CORE_OBJ) -rmdir /s /q $(MINIDIR) || rmdir /s $(MINIDIR) diff --git a/win32/perlhost.h b/win32/perlhost.h new file mode 100644 index 0000000..236a97c --- /dev/null +++ b/win32/perlhost.h @@ -0,0 +1,2283 @@ +/* perlhost.h + * + * (c) 1999 Microsoft Corporation. All rights reserved. + * Portions (c) 1999 ActiveState Tool Corp, http://www.ActiveState.com/ + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the README file. + */ + +#ifndef ___PerlHost_H___ +#define ___PerlHost_H___ + +#include "iperlsys.h" +#include "vmem.h" +#include "vdir.h" + +#if !defined(PERL_OBJECT) +START_EXTERN_C +#endif +extern char * g_win32_get_privlib(char *pl); +extern char * g_win32_get_sitelib(char *pl); +extern char * g_getlogin(void); +extern int do_spawn2(char *cmd, int exectype); +#if !defined(PERL_OBJECT) +END_EXTERN_C +#endif + +#ifdef PERL_OBJECT +extern int g_do_aspawn(void *vreally, void **vmark, void **vsp); +#define do_aspawn g_do_aspawn +#endif + +class CPerlHost +{ +public: + CPerlHost(void); + CPerlHost(struct IPerlMem** ppMem, struct IPerlMem** ppMemShared, + struct IPerlMem** ppMemParse, struct IPerlEnv** ppEnv, + struct IPerlStdIO** ppStdIO, struct IPerlLIO** ppLIO, + struct IPerlDir** ppDir, struct IPerlSock** ppSock, + struct IPerlProc** ppProc); + CPerlHost(CPerlHost& host); + ~CPerlHost(void); + + static CPerlHost* IPerlMem2Host(struct IPerlMem* piPerl); + static CPerlHost* IPerlMemShared2Host(struct IPerlMem* piPerl); + static CPerlHost* IPerlMemParse2Host(struct IPerlMem* piPerl); + static CPerlHost* IPerlEnv2Host(struct IPerlEnv* piPerl); + static CPerlHost* IPerlStdIO2Host(struct IPerlStdIO* piPerl); + static CPerlHost* IPerlLIO2Host(struct IPerlLIO* piPerl); + static CPerlHost* IPerlDir2Host(struct IPerlDir* piPerl); + static CPerlHost* IPerlSock2Host(struct IPerlSock* piPerl); + static CPerlHost* IPerlProc2Host(struct IPerlProc* piPerl); + + BOOL PerlCreate(void); + int PerlParse(int argc, char** argv, char** env); + int PerlRun(void); + void PerlDestroy(void); + +/* IPerlMem */ + inline void* Malloc(size_t size) { return m_pVMem->Malloc(size); }; + inline void* Realloc(void* ptr, size_t size) { return m_pVMem->Realloc(ptr, size); }; + inline void Free(void* ptr) { m_pVMem->Free(ptr); }; + inline void* Calloc(size_t num, size_t size) + { + size_t count = num*size; + void* lpVoid = Malloc(count); + if (lpVoid) + ZeroMemory(lpVoid, count); + return lpVoid; + }; + inline void GetLock(void) { m_pVMem->GetLock(); }; + inline void FreeLock(void) { m_pVMem->FreeLock(); }; + inline int IsLocked(void) { return m_pVMem->IsLocked(); }; + +/* IPerlMemShared */ + inline void* MallocShared(size_t size) + { + return m_pVMemShared->Malloc(size); + }; + inline void* ReallocShared(void* ptr, size_t size) { return m_pVMemShared->Realloc(ptr, size); }; + inline void FreeShared(void* ptr) { m_pVMemShared->Free(ptr); }; + inline void* CallocShared(size_t num, size_t size) + { + size_t count = num*size; + void* lpVoid = MallocShared(count); + if (lpVoid) + ZeroMemory(lpVoid, count); + return lpVoid; + }; + inline void GetLockShared(void) { m_pVMem->GetLock(); }; + inline void FreeLockShared(void) { m_pVMem->FreeLock(); }; + inline int IsLockedShared(void) { return m_pVMem->IsLocked(); }; + +/* IPerlMemParse */ + inline void* MallocParse(size_t size) { return m_pVMemParse->Malloc(size); }; + inline void* ReallocParse(void* ptr, size_t size) { return m_pVMemParse->Realloc(ptr, size); }; + inline void FreeParse(void* ptr) { m_pVMemParse->Free(ptr); }; + inline void* CallocParse(size_t num, size_t size) + { + size_t count = num*size; + void* lpVoid = MallocParse(count); + if (lpVoid) + ZeroMemory(lpVoid, count); + return lpVoid; + }; + inline void GetLockParse(void) { m_pVMem->GetLock(); }; + inline void FreeLockParse(void) { m_pVMem->FreeLock(); }; + inline int IsLockedParse(void) { return m_pVMem->IsLocked(); }; + +/* IPerlEnv */ + char *Getenv(const char *varname); + int Putenv(const char *envstring); + inline char *Getenv(const char *varname, unsigned long *len) + { + *len = 0; + char *e = Getenv(varname); + if (e) + *len = strlen(e); + return e; + } + void* CreateChildEnv(void) { return CreateLocalEnvironmentStrings(*m_pvDir); }; + void FreeChildEnv(void* pStr) { FreeLocalEnvironmentStrings((char*)pStr); }; + char* GetChildDir(void); + void FreeChildDir(char* pStr); + void Reset(void); + void Clearenv(void); + + inline LPSTR GetIndex(DWORD &dwIndex) + { + if(dwIndex < m_dwEnvCount) + { + ++dwIndex; + return m_lppEnvList[dwIndex-1]; + } + return NULL; + }; + +protected: + LPSTR Find(LPCSTR lpStr); + void Add(LPCSTR lpStr); + + LPSTR CreateLocalEnvironmentStrings(VDir &vDir); + void FreeLocalEnvironmentStrings(LPSTR lpStr); + LPSTR* Lookup(LPCSTR lpStr); + DWORD CalculateEnvironmentSpace(void); + +public: + +/* IPerlDIR */ + virtual int Chdir(const char *dirname); + +/* IPerllProc */ + void Abort(void); + void Exit(int status); + void _Exit(int status); + int Execl(const char *cmdname, const char *arg0, const char *arg1, const char *arg2, const char *arg3); + int Execv(const char *cmdname, const char *const *argv); + int Execvp(const char *cmdname, const char *const *argv); + + inline VMem* GetMemShared(void) { m_pVMemShared->AddRef(); return m_pVMemShared; }; + inline VMem* GetMemParse(void) { m_pVMemParse->AddRef(); return m_pVMemParse; }; + inline VDir* GetDir(void) { return m_pvDir; }; + +public: + + struct IPerlMem m_hostperlMem; + struct IPerlMem m_hostperlMemShared; + struct IPerlMem m_hostperlMemParse; + struct IPerlEnv m_hostperlEnv; + struct IPerlStdIO m_hostperlStdIO; + struct IPerlLIO m_hostperlLIO; + struct IPerlDir m_hostperlDir; + struct IPerlSock m_hostperlSock; + struct IPerlProc m_hostperlProc; + + struct IPerlMem* m_pHostperlMem; + struct IPerlMem* m_pHostperlMemShared; + struct IPerlMem* m_pHostperlMemParse; + struct IPerlEnv* m_pHostperlEnv; + struct IPerlStdIO* m_pHostperlStdIO; + struct IPerlLIO* m_pHostperlLIO; + struct IPerlDir* m_pHostperlDir; + struct IPerlSock* m_pHostperlSock; + struct IPerlProc* m_pHostperlProc; + + inline char* MapPathA(const char *pInName) { return m_pvDir->MapPathA(pInName); }; + inline WCHAR* MapPathW(const WCHAR *pInName) { return m_pvDir->MapPathW(pInName); }; +protected: + + VDir* m_pvDir; + VMem* m_pVMem; + VMem* m_pVMemShared; + VMem* m_pVMemParse; + + DWORD m_dwEnvCount; + LPSTR* m_lppEnvList; +}; + + +#define STRUCT2PTR(x, y) (CPerlHost*)(((LPBYTE)x)-offsetof(CPerlHost, y)) + +inline CPerlHost* IPerlMem2Host(struct IPerlMem* piPerl) +{ + return STRUCT2PTR(piPerl, m_hostperlMem); +} + +inline CPerlHost* IPerlMemShared2Host(struct IPerlMem* piPerl) +{ + return STRUCT2PTR(piPerl, m_hostperlMemShared); +} + +inline CPerlHost* IPerlMemParse2Host(struct IPerlMem* piPerl) +{ + return STRUCT2PTR(piPerl, m_hostperlMemParse); +} + +inline CPerlHost* IPerlEnv2Host(struct IPerlEnv* piPerl) +{ + return STRUCT2PTR(piPerl, m_hostperlEnv); +} + +inline CPerlHost* IPerlStdIO2Host(struct IPerlStdIO* piPerl) +{ + return STRUCT2PTR(piPerl, m_hostperlStdIO); +} + +inline CPerlHost* IPerlLIO2Host(struct IPerlLIO* piPerl) +{ + return STRUCT2PTR(piPerl, m_hostperlLIO); +} + +inline CPerlHost* IPerlDir2Host(struct IPerlDir* piPerl) +{ + return STRUCT2PTR(piPerl, m_hostperlDir); +} + +inline CPerlHost* IPerlSock2Host(struct IPerlSock* piPerl) +{ + return STRUCT2PTR(piPerl, m_hostperlSock); +} + +inline CPerlHost* IPerlProc2Host(struct IPerlProc* piPerl) +{ + return STRUCT2PTR(piPerl, m_hostperlProc); +} + + + +#undef IPERL2HOST +#define IPERL2HOST(x) IPerlMem2Host(x) + +/* IPerlMem */ +void* +PerlMemMalloc(struct IPerlMem* piPerl, size_t size) +{ + return IPERL2HOST(piPerl)->Malloc(size); +} +void* +PerlMemRealloc(struct IPerlMem* piPerl, void* ptr, size_t size) +{ + return IPERL2HOST(piPerl)->Realloc(ptr, size); +} +void +PerlMemFree(struct IPerlMem* piPerl, void* ptr) +{ + IPERL2HOST(piPerl)->Free(ptr); +} +void* +PerlMemCalloc(struct IPerlMem* piPerl, size_t num, size_t size) +{ + return IPERL2HOST(piPerl)->Calloc(num, size); +} + +void +PerlMemGetLock(struct IPerlMem* piPerl) +{ + IPERL2HOST(piPerl)->GetLock(); +} + +void +PerlMemFreeLock(struct IPerlMem* piPerl) +{ + IPERL2HOST(piPerl)->FreeLock(); +} + +int +PerlMemIsLocked(struct IPerlMem* piPerl) +{ + return IPERL2HOST(piPerl)->IsLocked(); +} + +struct IPerlMem perlMem = +{ + PerlMemMalloc, + PerlMemRealloc, + PerlMemFree, + PerlMemCalloc, + PerlMemGetLock, + PerlMemFreeLock, + PerlMemIsLocked, +}; + +#undef IPERL2HOST +#define IPERL2HOST(x) IPerlMemShared2Host(x) + +/* IPerlMemShared */ +void* +PerlMemSharedMalloc(struct IPerlMem* piPerl, size_t size) +{ + return IPERL2HOST(piPerl)->MallocShared(size); +} +void* +PerlMemSharedRealloc(struct IPerlMem* piPerl, void* ptr, size_t size) +{ + return IPERL2HOST(piPerl)->ReallocShared(ptr, size); +} +void +PerlMemSharedFree(struct IPerlMem* piPerl, void* ptr) +{ + IPERL2HOST(piPerl)->FreeShared(ptr); +} +void* +PerlMemSharedCalloc(struct IPerlMem* piPerl, size_t num, size_t size) +{ + return IPERL2HOST(piPerl)->CallocShared(num, size); +} + +void +PerlMemSharedGetLock(struct IPerlMem* piPerl) +{ + IPERL2HOST(piPerl)->GetLockShared(); +} + +void +PerlMemSharedFreeLock(struct IPerlMem* piPerl) +{ + IPERL2HOST(piPerl)->FreeLockShared(); +} + +int +PerlMemSharedIsLocked(struct IPerlMem* piPerl) +{ + return IPERL2HOST(piPerl)->IsLockedShared(); +} + +struct IPerlMem perlMemShared = +{ + PerlMemSharedMalloc, + PerlMemSharedRealloc, + PerlMemSharedFree, + PerlMemSharedCalloc, + PerlMemSharedGetLock, + PerlMemSharedFreeLock, + PerlMemSharedIsLocked, +}; + +#undef IPERL2HOST +#define IPERL2HOST(x) IPerlMemParse2Host(x) + +/* IPerlMemParse */ +void* +PerlMemParseMalloc(struct IPerlMem* piPerl, size_t size) +{ + return IPERL2HOST(piPerl)->MallocParse(size); +} +void* +PerlMemParseRealloc(struct IPerlMem* piPerl, void* ptr, size_t size) +{ + return IPERL2HOST(piPerl)->ReallocParse(ptr, size); +} +void +PerlMemParseFree(struct IPerlMem* piPerl, void* ptr) +{ + IPERL2HOST(piPerl)->FreeParse(ptr); +} +void* +PerlMemParseCalloc(struct IPerlMem* piPerl, size_t num, size_t size) +{ + return IPERL2HOST(piPerl)->CallocParse(num, size); +} + +void +PerlMemParseGetLock(struct IPerlMem* piPerl) +{ + IPERL2HOST(piPerl)->GetLockParse(); +} + +void +PerlMemParseFreeLock(struct IPerlMem* piPerl) +{ + IPERL2HOST(piPerl)->FreeLockParse(); +} + +int +PerlMemParseIsLocked(struct IPerlMem* piPerl) +{ + return IPERL2HOST(piPerl)->IsLockedParse(); +} + +struct IPerlMem perlMemParse = +{ + PerlMemParseMalloc, + PerlMemParseRealloc, + PerlMemParseFree, + PerlMemParseCalloc, + PerlMemParseGetLock, + PerlMemParseFreeLock, + PerlMemParseIsLocked, +}; + + +#undef IPERL2HOST +#define IPERL2HOST(x) IPerlEnv2Host(x) + +/* IPerlEnv */ +char* +PerlEnvGetenv(struct IPerlEnv* piPerl, const char *varname) +{ + return IPERL2HOST(piPerl)->Getenv(varname); +}; + +int +PerlEnvPutenv(struct IPerlEnv* piPerl, const char *envstring) +{ + return IPERL2HOST(piPerl)->Putenv(envstring); +}; + +char* +PerlEnvGetenv_len(struct IPerlEnv* piPerl, const char* varname, unsigned long* len) +{ + return IPERL2HOST(piPerl)->Getenv(varname, len); +} + +int +PerlEnvUname(struct IPerlEnv* piPerl, struct utsname *name) +{ + return win32_uname(name); +} + +void +PerlEnvClearenv(struct IPerlEnv* piPerl) +{ + IPERL2HOST(piPerl)->Clearenv(); +} + +void* +PerlEnvGetChildenv(struct IPerlEnv* piPerl) +{ + return IPERL2HOST(piPerl)->CreateChildEnv(); +} + +void +PerlEnvFreeChildenv(struct IPerlEnv* piPerl, void* childEnv) +{ + IPERL2HOST(piPerl)->FreeChildEnv(childEnv); +} + +char* +PerlEnvGetChilddir(struct IPerlEnv* piPerl) +{ + return IPERL2HOST(piPerl)->GetChildDir(); +} + +void +PerlEnvFreeChilddir(struct IPerlEnv* piPerl, char* childDir) +{ + IPERL2HOST(piPerl)->FreeChildDir(childDir); +} + +unsigned long +PerlEnvOsId(struct IPerlEnv* piPerl) +{ + return win32_os_id(); +} + +char* +PerlEnvLibPath(struct IPerlEnv* piPerl, char *pl) +{ + return g_win32_get_privlib(pl); +} + +char* +PerlEnvSiteLibPath(struct IPerlEnv* piPerl, char *pl) +{ + return g_win32_get_sitelib(pl); +} + +struct IPerlEnv perlEnv = +{ + PerlEnvGetenv, + PerlEnvPutenv, + PerlEnvGetenv_len, + PerlEnvUname, + PerlEnvClearenv, + PerlEnvGetChildenv, + PerlEnvFreeChildenv, + PerlEnvGetChilddir, + PerlEnvFreeChilddir, + PerlEnvOsId, + PerlEnvLibPath, + PerlEnvSiteLibPath, +}; + +#undef IPERL2HOST +#define IPERL2HOST(x) IPerlStdIO2Host(x) + +/* PerlStdIO */ +PerlIO* +PerlStdIOStdin(struct IPerlStdIO* piPerl) +{ + return (PerlIO*)win32_stdin(); +} + +PerlIO* +PerlStdIOStdout(struct IPerlStdIO* piPerl) +{ + return (PerlIO*)win32_stdout(); +} + +PerlIO* +PerlStdIOStderr(struct IPerlStdIO* piPerl) +{ + return (PerlIO*)win32_stderr(); +} + +PerlIO* +PerlStdIOOpen(struct IPerlStdIO* piPerl, const char *path, const char *mode) +{ + return (PerlIO*)win32_fopen(path, mode); +} + +int +PerlStdIOClose(struct IPerlStdIO* piPerl, PerlIO* pf) +{ + return win32_fclose(((FILE*)pf)); +} + +int +PerlStdIOEof(struct IPerlStdIO* piPerl, PerlIO* pf) +{ + return win32_feof((FILE*)pf); +} + +int +PerlStdIOError(struct IPerlStdIO* piPerl, PerlIO* pf) +{ + return win32_ferror((FILE*)pf); +} + +void +PerlStdIOClearerr(struct IPerlStdIO* piPerl, PerlIO* pf) +{ + win32_clearerr((FILE*)pf); +} + +int +PerlStdIOGetc(struct IPerlStdIO* piPerl, PerlIO* pf) +{ + return win32_getc((FILE*)pf); +} + +char* +PerlStdIOGetBase(struct IPerlStdIO* piPerl, PerlIO* pf) +{ +#ifdef FILE_base + FILE *f = (FILE*)pf; + return FILE_base(f); +#else + return Nullch; +#endif +} + +int +PerlStdIOGetBufsiz(struct IPerlStdIO* piPerl, PerlIO* pf) +{ +#ifdef FILE_bufsiz + FILE *f = (FILE*)pf; + return FILE_bufsiz(f); +#else + return (-1); +#endif +} + +int +PerlStdIOGetCnt(struct IPerlStdIO* piPerl, PerlIO* pf) +{ +#ifdef USE_STDIO_PTR + FILE *f = (FILE*)pf; + return FILE_cnt(f); +#else + return (-1); +#endif +} + +char* +PerlStdIOGetPtr(struct IPerlStdIO* piPerl, PerlIO* pf) +{ +#ifdef USE_STDIO_PTR + FILE *f = (FILE*)pf; + return FILE_ptr(f); +#else + return Nullch; +#endif +} + +char* +PerlStdIOGets(struct IPerlStdIO* piPerl, PerlIO* pf, char* s, int n) +{ + return win32_fgets(s, n, (FILE*)pf); +} + +int +PerlStdIOPutc(struct IPerlStdIO* piPerl, PerlIO* pf, int c) +{ + return win32_fputc(c, (FILE*)pf); +} + +int +PerlStdIOPuts(struct IPerlStdIO* piPerl, PerlIO* pf, const char *s) +{ + return win32_fputs(s, (FILE*)pf); +} + +int +PerlStdIOFlush(struct IPerlStdIO* piPerl, PerlIO* pf) +{ + return win32_fflush((FILE*)pf); +} + +int +PerlStdIOUngetc(struct IPerlStdIO* piPerl, PerlIO* pf,int c) +{ + return win32_ungetc(c, (FILE*)pf); +} + +int +PerlStdIOFileno(struct IPerlStdIO* piPerl, PerlIO* pf) +{ + return win32_fileno((FILE*)pf); +} + +PerlIO* +PerlStdIOFdopen(struct IPerlStdIO* piPerl, int fd, const char *mode) +{ + return (PerlIO*)win32_fdopen(fd, mode); +} + +PerlIO* +PerlStdIOReopen(struct IPerlStdIO* piPerl, const char*path, const char*mode, PerlIO* pf) +{ + return (PerlIO*)win32_freopen(path, mode, (FILE*)pf); +} + +SSize_t +PerlStdIORead(struct IPerlStdIO* piPerl, PerlIO* pf, void *buffer, Size_t size) +{ + return win32_fread(buffer, 1, size, (FILE*)pf); +} + +SSize_t +PerlStdIOWrite(struct IPerlStdIO* piPerl, PerlIO* pf, const void *buffer, Size_t size) +{ + return win32_fwrite(buffer, 1, size, (FILE*)pf); +} + +void +PerlStdIOSetBuf(struct IPerlStdIO* piPerl, PerlIO* pf, char* buffer) +{ + win32_setbuf((FILE*)pf, buffer); +} + +int +PerlStdIOSetVBuf(struct IPerlStdIO* piPerl, PerlIO* pf, char* buffer, int type, Size_t size) +{ + return win32_setvbuf((FILE*)pf, buffer, type, size); +} + +void +PerlStdIOSetCnt(struct IPerlStdIO* piPerl, PerlIO* pf, int n) +{ +#ifdef STDIO_CNT_LVALUE + FILE *f = (FILE*)pf; + FILE_cnt(f) = n; +#endif +} + +void +PerlStdIOSetPtrCnt(struct IPerlStdIO* piPerl, PerlIO* pf, char * ptr, int n) +{ +#ifdef STDIO_PTR_LVALUE + FILE *f = (FILE*)pf; + FILE_ptr(f) = ptr; + FILE_cnt(f) = n; +#endif +} + +void +PerlStdIOSetlinebuf(struct IPerlStdIO* piPerl, PerlIO* pf) +{ + win32_setvbuf((FILE*)pf, NULL, _IOLBF, 0); +} + +int +PerlStdIOPrintf(struct IPerlStdIO* piPerl, PerlIO* pf, const char *format,...) +{ + va_list(arglist); + va_start(arglist, format); + return win32_vfprintf((FILE*)pf, format, arglist); +} + +int +PerlStdIOVprintf(struct IPerlStdIO* piPerl, PerlIO* pf, const char *format, va_list arglist) +{ + return win32_vfprintf((FILE*)pf, format, arglist); +} + +long +PerlStdIOTell(struct IPerlStdIO* piPerl, PerlIO* pf) +{ + return win32_ftell((FILE*)pf); +} + +int +PerlStdIOSeek(struct IPerlStdIO* piPerl, PerlIO* pf, off_t offset, int origin) +{ + return win32_fseek((FILE*)pf, offset, origin); +} + +void +PerlStdIORewind(struct IPerlStdIO* piPerl, PerlIO* pf) +{ + win32_rewind((FILE*)pf); +} + +PerlIO* +PerlStdIOTmpfile(struct IPerlStdIO* piPerl) +{ + return (PerlIO*)win32_tmpfile(); +} + +int +PerlStdIOGetpos(struct IPerlStdIO* piPerl, PerlIO* pf, Fpos_t *p) +{ + return win32_fgetpos((FILE*)pf, p); +} + +int +PerlStdIOSetpos(struct IPerlStdIO* piPerl, PerlIO* pf, const Fpos_t *p) +{ + return win32_fsetpos((FILE*)pf, p); +} +void +PerlStdIOInit(struct IPerlStdIO* piPerl) +{ +} + +void +PerlStdIOInitOSExtras(struct IPerlStdIO* piPerl) +{ + Perl_init_os_extras(); +} + +int +PerlStdIOOpenOSfhandle(struct IPerlStdIO* piPerl, long osfhandle, int flags) +{ + return win32_open_osfhandle(osfhandle, flags); +} + +int +PerlStdIOGetOSfhandle(struct IPerlStdIO* piPerl, int filenum) +{ + return win32_get_osfhandle(filenum); +} + +PerlIO* +PerlStdIOFdupopen(struct IPerlStdIO* piPerl, PerlIO* pf) +{ + PerlIO* pfdup; + fpos_t pos; + char mode[3]; + int fileno = win32_dup(win32_fileno((FILE*)pf)); + + /* open the file in the same mode */ + if(((FILE*)pf)->_flag & _IOREAD) { + mode[0] = 'r'; + mode[1] = 0; + } + else if(((FILE*)pf)->_flag & _IOWRT) { + mode[0] = 'a'; + mode[1] = 0; + } + else if(((FILE*)pf)->_flag & _IORW) { + mode[0] = 'r'; + mode[1] = '+'; + mode[2] = 0; + } + + /* it appears that the binmode is attached to the + * file descriptor so binmode files will be handled + * correctly + */ + pfdup = (PerlIO*)win32_fdopen(fileno, mode); + + /* move the file pointer to the same position */ + if (!fgetpos((FILE*)pf, &pos)) { + fsetpos((FILE*)pfdup, &pos); + } + return pfdup; +} + +struct IPerlStdIO perlStdIO = +{ + PerlStdIOStdin, + PerlStdIOStdout, + PerlStdIOStderr, + PerlStdIOOpen, + PerlStdIOClose, + PerlStdIOEof, + PerlStdIOError, + PerlStdIOClearerr, + PerlStdIOGetc, + PerlStdIOGetBase, + PerlStdIOGetBufsiz, + PerlStdIOGetCnt, + PerlStdIOGetPtr, + PerlStdIOGets, + PerlStdIOPutc, + PerlStdIOPuts, + PerlStdIOFlush, + PerlStdIOUngetc, + PerlStdIOFileno, + PerlStdIOFdopen, + PerlStdIOReopen, + PerlStdIORead, + PerlStdIOWrite, + PerlStdIOSetBuf, + PerlStdIOSetVBuf, + PerlStdIOSetCnt, + PerlStdIOSetPtrCnt, + PerlStdIOSetlinebuf, + PerlStdIOPrintf, + PerlStdIOVprintf, + PerlStdIOTell, + PerlStdIOSeek, + PerlStdIORewind, + PerlStdIOTmpfile, + PerlStdIOGetpos, + PerlStdIOSetpos, + PerlStdIOInit, + PerlStdIOInitOSExtras, + PerlStdIOFdupopen, +}; + + +#undef IPERL2HOST +#define IPERL2HOST(x) IPerlLIO2Host(x) + +/* IPerlLIO */ +int +PerlLIOAccess(struct IPerlLIO* piPerl, const char *path, int mode) +{ + return win32_access(path, mode); +} + +int +PerlLIOChmod(struct IPerlLIO* piPerl, const char *filename, int pmode) +{ + return win32_chmod(filename, pmode); +} + +int +PerlLIOChown(struct IPerlLIO* piPerl, const char *filename, uid_t owner, gid_t group) +{ + return chown(filename, owner, group); +} + +int +PerlLIOChsize(struct IPerlLIO* piPerl, int handle, long size) +{ + return chsize(handle, size); +} + +int +PerlLIOClose(struct IPerlLIO* piPerl, int handle) +{ + return win32_close(handle); +} + +int +PerlLIODup(struct IPerlLIO* piPerl, int handle) +{ + return win32_dup(handle); +} + +int +PerlLIODup2(struct IPerlLIO* piPerl, int handle1, int handle2) +{ + return win32_dup2(handle1, handle2); +} + +int +PerlLIOFlock(struct IPerlLIO* piPerl, int fd, int oper) +{ + return win32_flock(fd, oper); +} + +int +PerlLIOFileStat(struct IPerlLIO* piPerl, int handle, struct stat *buffer) +{ + return fstat(handle, buffer); +} + +int +PerlLIOIOCtl(struct IPerlLIO* piPerl, int i, unsigned int u, char *data) +{ + return win32_ioctlsocket((SOCKET)i, (long)u, (u_long*)data); +} + +int +PerlLIOIsatty(struct IPerlLIO* piPerl, int fd) +{ + return isatty(fd); +} + +int +PerlLIOLink(struct IPerlLIO* piPerl, const char*oldname, const char *newname) +{ + return win32_link(oldname, newname); +} + +long +PerlLIOLseek(struct IPerlLIO* piPerl, int handle, long offset, int origin) +{ + return win32_lseek(handle, offset, origin); +} + +int +PerlLIOLstat(struct IPerlLIO* piPerl, const char *path, struct stat *buffer) +{ + return win32_stat(path, buffer); +} + +char* +PerlLIOMktemp(struct IPerlLIO* piPerl, char *Template) +{ + return mktemp(Template); +} + +int +PerlLIOOpen(struct IPerlLIO* piPerl, const char *filename, int oflag) +{ + return win32_open(filename, oflag); +} + +int +PerlLIOOpen3(struct IPerlLIO* piPerl, const char *filename, int oflag, int pmode) +{ + return win32_open(filename, oflag, pmode); +} + +int +PerlLIORead(struct IPerlLIO* piPerl, int handle, void *buffer, unsigned int count) +{ + return win32_read(handle, buffer, count); +} + +int +PerlLIORename(struct IPerlLIO* piPerl, const char *OldFileName, const char *newname) +{ + return win32_rename(OldFileName, newname); +} + +int +PerlLIOSetmode(struct IPerlLIO* piPerl, int handle, int mode) +{ + return win32_setmode(handle, mode); +} + +int +PerlLIONameStat(struct IPerlLIO* piPerl, const char *path, struct stat *buffer) +{ + return win32_stat(path, buffer); +} + +char* +PerlLIOTmpnam(struct IPerlLIO* piPerl, char *string) +{ + return tmpnam(string); +} + +int +PerlLIOUmask(struct IPerlLIO* piPerl, int pmode) +{ + return umask(pmode); +} + +int +PerlLIOUnlink(struct IPerlLIO* piPerl, const char *filename) +{ + return win32_unlink(filename); +} + +int +PerlLIOUtime(struct IPerlLIO* piPerl, char *filename, struct utimbuf *times) +{ + return win32_utime(filename, times); +} + +int +PerlLIOWrite(struct IPerlLIO* piPerl, int handle, const void *buffer, unsigned int count) +{ + return win32_write(handle, buffer, count); +} + +struct IPerlLIO perlLIO = +{ + PerlLIOAccess, + PerlLIOChmod, + PerlLIOChown, + PerlLIOChsize, + PerlLIOClose, + PerlLIODup, + PerlLIODup2, + PerlLIOFlock, + PerlLIOFileStat, + PerlLIOIOCtl, + PerlLIOIsatty, + PerlLIOLink, + PerlLIOLseek, + PerlLIOLstat, + PerlLIOMktemp, + PerlLIOOpen, + PerlLIOOpen3, + PerlLIORead, + PerlLIORename, + PerlLIOSetmode, + PerlLIONameStat, + PerlLIOTmpnam, + PerlLIOUmask, + PerlLIOUnlink, + PerlLIOUtime, + PerlLIOWrite, +}; + + +#undef IPERL2HOST +#define IPERL2HOST(x) IPerlDir2Host(x) + +/* IPerlDIR */ +int +PerlDirMakedir(struct IPerlDir* piPerl, const char *dirname, int mode) +{ + return win32_mkdir(dirname, mode); +} + +int +PerlDirChdir(struct IPerlDir* piPerl, const char *dirname) +{ + return IPERL2HOST(piPerl)->Chdir(dirname); +} + +int +PerlDirRmdir(struct IPerlDir* piPerl, const char *dirname) +{ + return win32_rmdir(dirname); +} + +int +PerlDirClose(struct IPerlDir* piPerl, DIR *dirp) +{ + return win32_closedir(dirp); +} + +DIR* +PerlDirOpen(struct IPerlDir* piPerl, char *filename) +{ + return win32_opendir(filename); +} + +struct direct * +PerlDirRead(struct IPerlDir* piPerl, DIR *dirp) +{ + return win32_readdir(dirp); +} + +void +PerlDirRewind(struct IPerlDir* piPerl, DIR *dirp) +{ + win32_rewinddir(dirp); +} + +void +PerlDirSeek(struct IPerlDir* piPerl, DIR *dirp, long loc) +{ + win32_seekdir(dirp, loc); +} + +long +PerlDirTell(struct IPerlDir* piPerl, DIR *dirp) +{ + return win32_telldir(dirp); +} + +char* +PerlDirMapPathA(struct IPerlDir* piPerl, const char* path) +{ + return IPERL2HOST(piPerl)->MapPathA(path); +} + +WCHAR* +PerlDirMapPathW(struct IPerlDir* piPerl, const WCHAR* path) +{ + return IPERL2HOST(piPerl)->MapPathW(path); +} + +struct IPerlDir perlDir = +{ + PerlDirMakedir, + PerlDirChdir, + PerlDirRmdir, + PerlDirClose, + PerlDirOpen, + PerlDirRead, + PerlDirRewind, + PerlDirSeek, + PerlDirTell, + PerlDirMapPathA, + PerlDirMapPathW, +}; + + +/* IPerlSock */ +u_long +PerlSockHtonl(struct IPerlSock* piPerl, u_long hostlong) +{ + return win32_htonl(hostlong); +} + +u_short +PerlSockHtons(struct IPerlSock* piPerl, u_short hostshort) +{ + return win32_htons(hostshort); +} + +u_long +PerlSockNtohl(struct IPerlSock* piPerl, u_long netlong) +{ + return win32_ntohl(netlong); +} + +u_short +PerlSockNtohs(struct IPerlSock* piPerl, u_short netshort) +{ + return win32_ntohs(netshort); +} + +SOCKET PerlSockAccept(struct IPerlSock* piPerl, SOCKET s, struct sockaddr* addr, int* addrlen) +{ + return win32_accept(s, addr, addrlen); +} + +int +PerlSockBind(struct IPerlSock* piPerl, SOCKET s, const struct sockaddr* name, int namelen) +{ + return win32_bind(s, name, namelen); +} + +int +PerlSockConnect(struct IPerlSock* piPerl, SOCKET s, const struct sockaddr* name, int namelen) +{ + return win32_connect(s, name, namelen); +} + +void +PerlSockEndhostent(struct IPerlSock* piPerl) +{ + win32_endhostent(); +} + +void +PerlSockEndnetent(struct IPerlSock* piPerl) +{ + win32_endnetent(); +} + +void +PerlSockEndprotoent(struct IPerlSock* piPerl) +{ + win32_endprotoent(); +} + +void +PerlSockEndservent(struct IPerlSock* piPerl) +{ + win32_endservent(); +} + +struct hostent* +PerlSockGethostbyaddr(struct IPerlSock* piPerl, const char* addr, int len, int type) +{ + return win32_gethostbyaddr(addr, len, type); +} + +struct hostent* +PerlSockGethostbyname(struct IPerlSock* piPerl, const char* name) +{ + return win32_gethostbyname(name); +} + +struct hostent* +PerlSockGethostent(struct IPerlSock* piPerl) +{ + dTHXo; + Perl_croak(aTHX_ "gethostent not implemented!\n"); + return NULL; +} + +int +PerlSockGethostname(struct IPerlSock* piPerl, char* name, int namelen) +{ + return win32_gethostname(name, namelen); +} + +struct netent * +PerlSockGetnetbyaddr(struct IPerlSock* piPerl, long net, int type) +{ + return win32_getnetbyaddr(net, type); +} + +struct netent * +PerlSockGetnetbyname(struct IPerlSock* piPerl, const char *name) +{ + return win32_getnetbyname((char*)name); +} + +struct netent * +PerlSockGetnetent(struct IPerlSock* piPerl) +{ + return win32_getnetent(); +} + +int PerlSockGetpeername(struct IPerlSock* piPerl, SOCKET s, struct sockaddr* name, int* namelen) +{ + return win32_getpeername(s, name, namelen); +} + +struct protoent* +PerlSockGetprotobyname(struct IPerlSock* piPerl, const char* name) +{ + return win32_getprotobyname(name); +} + +struct protoent* +PerlSockGetprotobynumber(struct IPerlSock* piPerl, int number) +{ + return win32_getprotobynumber(number); +} + +struct protoent* +PerlSockGetprotoent(struct IPerlSock* piPerl) +{ + return win32_getprotoent(); +} + +struct servent* +PerlSockGetservbyname(struct IPerlSock* piPerl, const char* name, const char* proto) +{ + return win32_getservbyname(name, proto); +} + +struct servent* +PerlSockGetservbyport(struct IPerlSock* piPerl, int port, const char* proto) +{ + return win32_getservbyport(port, proto); +} + +struct servent* +PerlSockGetservent(struct IPerlSock* piPerl) +{ + return win32_getservent(); +} + +int +PerlSockGetsockname(struct IPerlSock* piPerl, SOCKET s, struct sockaddr* name, int* namelen) +{ + return win32_getsockname(s, name, namelen); +} + +int +PerlSockGetsockopt(struct IPerlSock* piPerl, SOCKET s, int level, int optname, char* optval, int* optlen) +{ + return win32_getsockopt(s, level, optname, optval, optlen); +} + +unsigned long +PerlSockInetAddr(struct IPerlSock* piPerl, const char* cp) +{ + return win32_inet_addr(cp); +} + +char* +PerlSockInetNtoa(struct IPerlSock* piPerl, struct in_addr in) +{ + return win32_inet_ntoa(in); +} + +int +PerlSockListen(struct IPerlSock* piPerl, SOCKET s, int backlog) +{ + return win32_listen(s, backlog); +} + +int +PerlSockRecv(struct IPerlSock* piPerl, SOCKET s, char* buffer, int len, int flags) +{ + return win32_recv(s, buffer, len, flags); +} + +int +PerlSockRecvfrom(struct IPerlSock* piPerl, SOCKET s, char* buffer, int len, int flags, struct sockaddr* from, int* fromlen) +{ + return win32_recvfrom(s, buffer, len, flags, from, fromlen); +} + +int +PerlSockSelect(struct IPerlSock* piPerl, int nfds, char* readfds, char* writefds, char* exceptfds, const struct timeval* timeout) +{ + return win32_select(nfds, (Perl_fd_set*)readfds, (Perl_fd_set*)writefds, (Perl_fd_set*)exceptfds, timeout); +} + +int +PerlSockSend(struct IPerlSock* piPerl, SOCKET s, const char* buffer, int len, int flags) +{ + return win32_send(s, buffer, len, flags); +} + +int +PerlSockSendto(struct IPerlSock* piPerl, SOCKET s, const char* buffer, int len, int flags, const struct sockaddr* to, int tolen) +{ + return win32_sendto(s, buffer, len, flags, to, tolen); +} + +void +PerlSockSethostent(struct IPerlSock* piPerl, int stayopen) +{ + win32_sethostent(stayopen); +} + +void +PerlSockSetnetent(struct IPerlSock* piPerl, int stayopen) +{ + win32_setnetent(stayopen); +} + +void +PerlSockSetprotoent(struct IPerlSock* piPerl, int stayopen) +{ + win32_setprotoent(stayopen); +} + +void +PerlSockSetservent(struct IPerlSock* piPerl, int stayopen) +{ + win32_setservent(stayopen); +} + +int +PerlSockSetsockopt(struct IPerlSock* piPerl, SOCKET s, int level, int optname, const char* optval, int optlen) +{ + return win32_setsockopt(s, level, optname, optval, optlen); +} + +int +PerlSockShutdown(struct IPerlSock* piPerl, SOCKET s, int how) +{ + return win32_shutdown(s, how); +} + +SOCKET +PerlSockSocket(struct IPerlSock* piPerl, int af, int type, int protocol) +{ + return win32_socket(af, type, protocol); +} + +int +PerlSockSocketpair(struct IPerlSock* piPerl, int domain, int type, int protocol, int* fds) +{ + dTHXo; + Perl_croak(aTHX_ "socketpair not implemented!\n"); + return 0; +} + +int +PerlSockClosesocket(struct IPerlSock* piPerl, SOCKET s) +{ + return win32_closesocket(s); +} + +int +PerlSockIoctlsocket(struct IPerlSock* piPerl, SOCKET s, long cmd, u_long *argp) +{ + return win32_ioctlsocket(s, cmd, argp); +} + +struct IPerlSock perlSock = +{ + PerlSockHtonl, + PerlSockHtons, + PerlSockNtohl, + PerlSockNtohs, + PerlSockAccept, + PerlSockBind, + PerlSockConnect, + PerlSockEndhostent, + PerlSockEndnetent, + PerlSockEndprotoent, + PerlSockEndservent, + PerlSockGethostname, + PerlSockGetpeername, + PerlSockGethostbyaddr, + PerlSockGethostbyname, + PerlSockGethostent, + PerlSockGetnetbyaddr, + PerlSockGetnetbyname, + PerlSockGetnetent, + PerlSockGetprotobyname, + PerlSockGetprotobynumber, + PerlSockGetprotoent, + PerlSockGetservbyname, + PerlSockGetservbyport, + PerlSockGetservent, + PerlSockGetsockname, + PerlSockGetsockopt, + PerlSockInetAddr, + PerlSockInetNtoa, + PerlSockListen, + PerlSockRecv, + PerlSockRecvfrom, + PerlSockSelect, + PerlSockSend, + PerlSockSendto, + PerlSockSethostent, + PerlSockSetnetent, + PerlSockSetprotoent, + PerlSockSetservent, + PerlSockSetsockopt, + PerlSockShutdown, + PerlSockSocket, + PerlSockSocketpair, + PerlSockClosesocket, +}; + + +/* IPerlProc */ + +#define EXECF_EXEC 1 +#define EXECF_SPAWN 2 + +void +PerlProcAbort(struct IPerlProc* piPerl) +{ + win32_abort(); +} + +char * +PerlProcCrypt(struct IPerlProc* piPerl, const char* clear, const char* salt) +{ + return win32_crypt(clear, salt); +} + +void +PerlProcExit(struct IPerlProc* piPerl, int status) +{ + exit(status); +} + +void +PerlProc_Exit(struct IPerlProc* piPerl, int status) +{ + _exit(status); +} + +int +PerlProcExecl(struct IPerlProc* piPerl, const char *cmdname, const char *arg0, const char *arg1, const char *arg2, const char *arg3) +{ + return execl(cmdname, arg0, arg1, arg2, arg3); +} + +int +PerlProcExecv(struct IPerlProc* piPerl, const char *cmdname, const char *const *argv) +{ + return win32_execvp(cmdname, argv); +} + +int +PerlProcExecvp(struct IPerlProc* piPerl, const char *cmdname, const char *const *argv) +{ + return win32_execvp(cmdname, argv); +} + +uid_t +PerlProcGetuid(struct IPerlProc* piPerl) +{ + return getuid(); +} + +uid_t +PerlProcGeteuid(struct IPerlProc* piPerl) +{ + return geteuid(); +} + +gid_t +PerlProcGetgid(struct IPerlProc* piPerl) +{ + return getgid(); +} + +gid_t +PerlProcGetegid(struct IPerlProc* piPerl) +{ + return getegid(); +} + +char * +PerlProcGetlogin(struct IPerlProc* piPerl) +{ + return g_getlogin(); +} + +int +PerlProcKill(struct IPerlProc* piPerl, int pid, int sig) +{ + return win32_kill(pid, sig); +} + +int +PerlProcKillpg(struct IPerlProc* piPerl, int pid, int sig) +{ + dTHXo; + Perl_croak(aTHX_ "killpg not implemented!\n"); + return 0; +} + +int +PerlProcPauseProc(struct IPerlProc* piPerl) +{ + return win32_sleep((32767L << 16) + 32767); +} + +PerlIO* +PerlProcPopen(struct IPerlProc* piPerl, const char *command, const char *mode) +{ + dTHXo; + PERL_FLUSHALL_FOR_CHILD; + return (PerlIO*)win32_popen(command, mode); +} + +int +PerlProcPclose(struct IPerlProc* piPerl, PerlIO *stream) +{ + return win32_pclose((FILE*)stream); +} + +int +PerlProcPipe(struct IPerlProc* piPerl, int *phandles) +{ + return win32_pipe(phandles, 512, O_BINARY); +} + +int +PerlProcSetuid(struct IPerlProc* piPerl, uid_t u) +{ + return setuid(u); +} + +int +PerlProcSetgid(struct IPerlProc* piPerl, gid_t g) +{ + return setgid(g); +} + +int +PerlProcSleep(struct IPerlProc* piPerl, unsigned int s) +{ + return win32_sleep(s); +} + +int +PerlProcTimes(struct IPerlProc* piPerl, struct tms *timebuf) +{ + return win32_times(timebuf); +} + +int +PerlProcWait(struct IPerlProc* piPerl, int *status) +{ + return win32_wait(status); +} + +int +PerlProcWaitpid(struct IPerlProc* piPerl, int pid, int *status, int flags) +{ + return win32_waitpid(pid, status, flags); +} + +Sighandler_t +PerlProcSignal(struct IPerlProc* piPerl, int sig, Sighandler_t subcode) +{ + return 0; +} + +static DWORD WINAPI +win32_start_child(LPVOID arg) +{ + PerlInterpreter *my_perl = (PerlInterpreter*)arg; + GV *tmpgv; + int status; +#ifdef PERL_OBJECT + CPerlObj *pPerl = (CPerlObj*)my_perl; +#endif +#ifdef PERL_SYNC_FORK + static long sync_fork_id = 0; + long id = ++sync_fork_id; +#endif + + + PERL_SET_INTERP(my_perl); + + /* set $$ to pseudo id */ +#ifdef PERL_SYNC_FORK + w32_pseudo_id = id; +#else + w32_pseudo_id = GetCurrentThreadId(); +#endif + if (tmpgv = gv_fetchpv("$", TRUE, SVt_PV)) + sv_setiv(GvSV(tmpgv), -(IV)w32_pseudo_id); + hv_clear(PL_pidstatus); + + /* push a zero on the stack (we are the child) */ + { + djSP; + dTARGET; + PUSHi(0); + PUTBACK; + } + + /* continue from next op */ + PL_op = PL_op->op_next; + + { + dJMPENV; + volatile oldscope = PL_scopestack_ix; + +restart: + JMPENV_PUSH(status); + switch (status) { + case 0: + CALLRUNOPS(aTHX); + status = 0; + break; + case 2: + while (PL_scopestack_ix > oldscope) + LEAVE; + FREETMPS; + PL_curstash = PL_defstash; + if (PL_endav && !PL_minus_c) + call_list(oldscope, PL_endav); + status = STATUS_NATIVE_EXPORT; + break; + case 3: + if (PL_restartop) { + POPSTACK_TO(PL_mainstack); + PL_op = PL_restartop; + PL_restartop = Nullop; + goto restart; + } + PerlIO_printf(Perl_error_log, "panic: restartop\n"); + FREETMPS; + status = 1; + break; + } + JMPENV_POP; + + /* XXX hack to avoid perl_destruct() freeing optree */ + PL_main_root = Nullop; + } + + /* destroy everything (waits for any pseudo-forked children) */ + perl_destruct(my_perl); + perl_free(my_perl); + +#ifdef PERL_SYNC_FORK + return id; +#else + return (DWORD)status; +#endif +} + +int +PerlProcFork(struct IPerlProc* piPerl) +{ + dTHXo; + DWORD id; + HANDLE handle; + CPerlHost *h = new CPerlHost(); + PerlInterpreter *new_perl = perl_clone_using((PerlInterpreter*)aTHXo, 1, + h->m_pHostperlMem, + h->m_pHostperlMemShared, + h->m_pHostperlMemParse, + h->m_pHostperlEnv, + h->m_pHostperlStdIO, + h->m_pHostperlLIO, + h->m_pHostperlDir, + h->m_pHostperlSock, + h->m_pHostperlProc + ); +#ifdef PERL_SYNC_FORK + id = win32_start_child((LPVOID)new_perl); + PERL_SET_INTERP(aTHXo); +#else + handle = CreateThread(NULL, 0, win32_start_child, + (LPVOID)new_perl, 0, &id); + PERL_SET_INTERP(aTHXo); + if (!handle) + Perl_croak(aTHX_ "panic: pseudo fork() failed"); + w32_pseudo_child_handles[w32_num_pseudo_children] = handle; + w32_pseudo_child_pids[w32_num_pseudo_children] = id; + ++w32_num_pseudo_children; +#endif + return -(int)id; +} + +int +PerlProcGetpid(struct IPerlProc* piPerl) +{ + return win32_getpid(); +} + +void* +PerlProcDynaLoader(struct IPerlProc* piPerl, const char* filename) +{ + return win32_dynaload(filename); +} + +void +PerlProcGetOSError(struct IPerlProc* piPerl, SV* sv, DWORD dwErr) +{ + win32_str_os_error(sv, dwErr); +} + +BOOL +PerlProcDoCmd(struct IPerlProc* piPerl, char *cmd) +{ + do_spawn2(cmd, EXECF_EXEC); + return FALSE; +} + +int +PerlProcSpawn(struct IPerlProc* piPerl, char* cmds) +{ + return do_spawn2(cmds, EXECF_SPAWN); +} + +int +PerlProcSpawnvp(struct IPerlProc* piPerl, int mode, const char *cmdname, const char *const *argv) +{ + return win32_spawnvp(mode, cmdname, argv); +} + +int +PerlProcASpawn(struct IPerlProc* piPerl, void *vreally, void **vmark, void **vsp) +{ + return do_aspawn(vreally, vmark, vsp); +} + +struct IPerlProc perlProc = +{ + PerlProcAbort, + PerlProcCrypt, + PerlProcExit, + PerlProc_Exit, + PerlProcExecl, + PerlProcExecv, + PerlProcExecvp, + PerlProcGetuid, + PerlProcGeteuid, + PerlProcGetgid, + PerlProcGetegid, + PerlProcGetlogin, + PerlProcKill, + PerlProcKillpg, + PerlProcPauseProc, + PerlProcPopen, + PerlProcPclose, + PerlProcPipe, + PerlProcSetuid, + PerlProcSetgid, + PerlProcSleep, + PerlProcTimes, + PerlProcWait, + PerlProcWaitpid, + PerlProcSignal, + PerlProcFork, + PerlProcGetpid, + PerlProcDynaLoader, + PerlProcGetOSError, + PerlProcDoCmd, + PerlProcSpawn, + PerlProcSpawnvp, + PerlProcASpawn, +}; + + +/* + * CPerlHost + */ + +CPerlHost::CPerlHost(void) +{ + m_pvDir = new VDir(); + m_pVMem = new VMem(); + m_pVMemShared = new VMem(); + m_pVMemParse = new VMem(); + + m_pvDir->Init(NULL, m_pVMem); + + m_dwEnvCount = 0; + m_lppEnvList = NULL; + + CopyMemory(&m_hostperlMem, &perlMem, sizeof(perlMem)); + CopyMemory(&m_hostperlMemShared, &perlMemShared, sizeof(perlMemShared)); + CopyMemory(&m_hostperlMemParse, &perlMemParse, sizeof(perlMemParse)); + CopyMemory(&m_hostperlEnv, &perlEnv, sizeof(perlEnv)); + CopyMemory(&m_hostperlStdIO, &perlStdIO, sizeof(perlStdIO)); + CopyMemory(&m_hostperlLIO, &perlLIO, sizeof(perlLIO)); + CopyMemory(&m_hostperlDir, &perlDir, sizeof(perlDir)); + CopyMemory(&m_hostperlSock, &perlSock, sizeof(perlSock)); + CopyMemory(&m_hostperlProc, &perlProc, sizeof(perlProc)); + + m_pHostperlMem = &m_hostperlMem; + m_pHostperlMemShared = &m_hostperlMemShared; + m_pHostperlMemParse = &m_hostperlMemParse; + m_pHostperlEnv = &m_hostperlEnv; + m_pHostperlStdIO = &m_hostperlStdIO; + m_pHostperlLIO = &m_hostperlLIO; + m_pHostperlDir = &m_hostperlDir; + m_pHostperlSock = &m_hostperlSock; + m_pHostperlProc = &m_hostperlProc; +} + +#define SETUPEXCHANGE(xptr, iptr, table) \ + STMT_START { \ + if (xptr) { \ + iptr = *xptr; \ + *xptr = &table; \ + } \ + else { \ + iptr = &table; \ + } \ + } STMT_END + +CPerlHost::CPerlHost(struct IPerlMem** ppMem, struct IPerlMem** ppMemShared, + struct IPerlMem** ppMemParse, struct IPerlEnv** ppEnv, + struct IPerlStdIO** ppStdIO, struct IPerlLIO** ppLIO, + struct IPerlDir** ppDir, struct IPerlSock** ppSock, + struct IPerlProc** ppProc) +{ + m_pvDir = new VDir(); + m_pVMem = new VMem(); + m_pVMemShared = new VMem(); + m_pVMemParse = new VMem(); + + m_pvDir->Init(NULL, m_pVMem); + + m_dwEnvCount = 0; + m_lppEnvList = NULL; + + CopyMemory(&m_hostperlMem, &perlMem, sizeof(perlMem)); + CopyMemory(&m_hostperlMemShared, &perlMemShared, sizeof(perlMemShared)); + CopyMemory(&m_hostperlMemParse, &perlMemParse, sizeof(perlMemParse)); + CopyMemory(&m_hostperlEnv, &perlEnv, sizeof(perlEnv)); + CopyMemory(&m_hostperlStdIO, &perlStdIO, sizeof(perlStdIO)); + CopyMemory(&m_hostperlLIO, &perlLIO, sizeof(perlLIO)); + CopyMemory(&m_hostperlDir, &perlDir, sizeof(perlDir)); + CopyMemory(&m_hostperlSock, &perlSock, sizeof(perlSock)); + CopyMemory(&m_hostperlProc, &perlProc, sizeof(perlProc)); + + SETUPEXCHANGE(ppMem, m_pHostperlMem, m_hostperlMem); + SETUPEXCHANGE(ppMemShared, m_pHostperlMemShared, m_hostperlMemShared); + SETUPEXCHANGE(ppMemParse, m_pHostperlMemParse, m_hostperlMemParse); + SETUPEXCHANGE(ppEnv, m_pHostperlEnv, m_hostperlEnv); + SETUPEXCHANGE(ppStdIO, m_pHostperlStdIO, m_hostperlStdIO); + SETUPEXCHANGE(ppLIO, m_pHostperlLIO, m_hostperlLIO); + SETUPEXCHANGE(ppDir, m_pHostperlDir, m_hostperlDir); + SETUPEXCHANGE(ppSock, m_pHostperlSock, m_hostperlSock); + SETUPEXCHANGE(ppProc, m_pHostperlProc, m_hostperlProc); +} +#undef SETUPEXCHANGE + +CPerlHost::CPerlHost(CPerlHost& host) +{ + m_pVMem = new VMem(); + m_pVMemShared = host.GetMemShared(); + m_pVMemParse = host.GetMemParse(); + + /* duplicate directory info */ + m_pvDir = new VDir(); + m_pvDir->Init(host.GetDir(), m_pVMem); + + CopyMemory(&m_hostperlMem, &perlMem, sizeof(perlMem)); + CopyMemory(&m_hostperlMemShared, &perlMemShared, sizeof(perlMemShared)); + CopyMemory(&m_hostperlMemParse, &perlMemParse, sizeof(perlMemParse)); + CopyMemory(&m_hostperlEnv, &perlEnv, sizeof(perlEnv)); + CopyMemory(&m_hostperlStdIO, &perlStdIO, sizeof(perlStdIO)); + CopyMemory(&m_hostperlLIO, &perlLIO, sizeof(perlLIO)); + CopyMemory(&m_hostperlDir, &perlDir, sizeof(perlDir)); + CopyMemory(&m_hostperlSock, &perlSock, sizeof(perlSock)); + CopyMemory(&m_hostperlProc, &perlProc, sizeof(perlProc)); + m_pHostperlMem = &host.m_hostperlMem; + m_pHostperlMemShared = &host.m_hostperlMemShared; + m_pHostperlMemParse = &host.m_hostperlMemParse; + m_pHostperlEnv = &host.m_hostperlEnv; + m_pHostperlStdIO = &host.m_hostperlStdIO; + m_pHostperlLIO = &host.m_hostperlLIO; + m_pHostperlDir = &host.m_hostperlDir; + m_pHostperlSock = &host.m_hostperlSock; + m_pHostperlProc = &host.m_hostperlProc; + + m_dwEnvCount = 0; + m_lppEnvList = NULL; + + /* duplicate environment info */ + LPSTR lpPtr; + DWORD dwIndex = 0; + while(lpPtr = host.GetIndex(dwIndex)) + Add(lpPtr); +} + +CPerlHost::~CPerlHost(void) +{ +// Reset(); + delete m_pvDir; + m_pVMemParse->Release(); + m_pVMemShared->Release(); + m_pVMem->Release(); +} + +LPSTR +CPerlHost::Find(LPCSTR lpStr) +{ + LPSTR lpPtr; + LPSTR* lppPtr = Lookup(lpStr); + if(lppPtr != NULL) { + for(lpPtr = *lppPtr; *lpPtr != '\0' && *lpPtr != '='; ++lpPtr) + ; + + if(*lpPtr == '=') + ++lpPtr; + + return lpPtr; + } + return NULL; +} + +int +lookup(const void *arg1, const void *arg2) +{ // Compare strings + char*ptr1, *ptr2; + char c1,c2; + + ptr1 = *(char**)arg1; + ptr2 = *(char**)arg2; + for(;;) { + c1 = *ptr1++; + c2 = *ptr2++; + if(c1 == '\0' || c1 == '=') { + if(c2 == '\0' || c2 == '=') + break; + + return -1; // string 1 < string 2 + } + else if(c2 == '\0' || c2 == '=') + return 1; // string 1 > string 2 + else if(c1 != c2) { + c1 = toupper(c1); + c2 = toupper(c2); + if(c1 != c2) { + if(c1 < c2) + return -1; // string 1 < string 2 + + return 1; // string 1 > string 2 + } + } + } + return 0; +} + +LPSTR* +CPerlHost::Lookup(LPCSTR lpStr) +{ + return (LPSTR*)bsearch(&lpStr, m_lppEnvList, m_dwEnvCount, sizeof(LPSTR), lookup); +} + +int +compare(const void *arg1, const void *arg2) +{ // Compare strings + char*ptr1, *ptr2; + char c1,c2; + + ptr1 = *(char**)arg1; + ptr2 = *(char**)arg2; + for(;;) { + c1 = *ptr1++; + c2 = *ptr2++; + if(c1 == '\0' || c1 == '=') { + if(c1 == c2) + break; + + return -1; // string 1 < string 2 + } + else if(c2 == '\0' || c2 == '=') + return 1; // string 1 > string 2 + else if(c1 != c2) { + c1 = toupper(c1); + c2 = toupper(c2); + if(c1 != c2) { + if(c1 < c2) + return -1; // string 1 < string 2 + + return 1; // string 1 > string 2 + } + } + } + return 0; +} + +void +CPerlHost::Add(LPCSTR lpStr) +{ + dTHXo; + char szBuffer[1024]; + LPSTR *lpPtr; + int index, length = strlen(lpStr)+1; + + for(index = 0; lpStr[index] != '\0' && lpStr[index] != '='; ++index) + szBuffer[index] = lpStr[index]; + + szBuffer[index] = '\0'; + + // replacing ? + lpPtr = Lookup(szBuffer); + if(lpPtr != NULL) { + Renew(*lpPtr, length, char); + strcpy(*lpPtr, lpStr); + } + else { + ++m_dwEnvCount; + Renew(m_lppEnvList, m_dwEnvCount, LPSTR); + New(1, m_lppEnvList[m_dwEnvCount-1], length, char); + if(m_lppEnvList[m_dwEnvCount-1] != NULL) { + strcpy(m_lppEnvList[m_dwEnvCount-1], lpStr); + qsort(m_lppEnvList, m_dwEnvCount, sizeof(LPSTR), compare); + } + else + --m_dwEnvCount; + } +} + +DWORD +CPerlHost::CalculateEnvironmentSpace(void) +{ + DWORD index; + DWORD dwSize = 0; + for(index = 0; index < m_dwEnvCount; ++index) + dwSize += strlen(m_lppEnvList[index]) + 1; + + return dwSize; +} + +void +CPerlHost::FreeLocalEnvironmentStrings(LPSTR lpStr) +{ + dTHXo; + Safefree(lpStr); +} + +char* +CPerlHost::GetChildDir(void) +{ + dTHXo; + int length; + char* ptr; + New(0, ptr, MAX_PATH+1, char); + if(ptr) { + m_pvDir->GetCurrentDirectoryA(MAX_PATH+1, ptr); + length = strlen(ptr)-1; + if(length > 0) { + if((ptr[length] == '\\') || (ptr[length] == '/')) + ptr[length] = 0; + } + } + return ptr; +} + +void +CPerlHost::FreeChildDir(char* pStr) +{ + dTHXo; + Safefree(pStr); +} + +LPSTR +CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir) +{ + dTHXo; + LPSTR lpStr, lpPtr, lpEnvPtr, lpTmp, lpLocalEnv, lpAllocPtr; + DWORD dwSize, dwEnvIndex; + int nLength, compVal; + + // get the process environment strings + lpAllocPtr = lpTmp = (LPSTR)GetEnvironmentStrings(); + + // step over current directory stuff + while(*lpTmp == '=') + lpTmp += strlen(lpTmp) + 1; + + // save the start of the environment strings + lpEnvPtr = lpTmp; + for(dwSize = 1; *lpTmp != '\0'; lpTmp += strlen(lpTmp) + 1) { + // calculate the size of the environment strings + dwSize += strlen(lpTmp) + 1; + } + + // add the size of current directories + dwSize += vDir.CalculateEnvironmentSpace(); + + // add the additional space used by changes made to the environment + dwSize += CalculateEnvironmentSpace(); + + New(1, lpStr, dwSize, char); + lpPtr = lpStr; + if(lpStr != NULL) { + // build the local environment + lpStr = vDir.BuildEnvironmentSpace(lpStr); + + dwEnvIndex = 0; + lpLocalEnv = GetIndex(dwEnvIndex); + while(*lpEnvPtr != '\0') { + if(lpLocalEnv == NULL) { + // all environment overrides have been added + // so copy string into place + strcpy(lpStr, lpEnvPtr); + nLength = strlen(lpEnvPtr) + 1; + lpStr += nLength; + lpEnvPtr += nLength; + } + else { + // determine which string to copy next + compVal = compare(&lpEnvPtr, &lpLocalEnv); + if(compVal < 0) { + strcpy(lpStr, lpEnvPtr); + nLength = strlen(lpEnvPtr) + 1; + lpStr += nLength; + lpEnvPtr += nLength; + } + else { + char *ptr = strchr(lpLocalEnv, '='); + if(ptr && ptr[1]) { + strcpy(lpStr, lpLocalEnv); + lpStr += strlen(lpLocalEnv) + 1; + } + lpLocalEnv = GetIndex(dwEnvIndex); + if(compVal == 0) { + // this string was replaced + lpEnvPtr += strlen(lpEnvPtr) + 1; + } + } + } + } + + // add final NULL + *lpStr = '\0'; + } + + // release the process environment strings + FreeEnvironmentStrings(lpAllocPtr); + + return lpPtr; +} + +void +CPerlHost::Reset(void) +{ + dTHXo; + if(m_lppEnvList != NULL) { + for(DWORD index = 0; index < m_dwEnvCount; ++index) { + Safefree(m_lppEnvList[index]); + m_lppEnvList[index] = NULL; + } + } + m_dwEnvCount = 0; +} + +void +CPerlHost::Clearenv(void) +{ + char ch; + LPSTR lpPtr, lpStr, lpEnvPtr; + if(m_lppEnvList != NULL) { + /* set every entry to an empty string */ + for(DWORD index = 0; index < m_dwEnvCount; ++index) { + char* ptr = strchr(m_lppEnvList[index], '='); + if(ptr) { + *++ptr = 0; + } + } + } + + /* get the process environment strings */ + lpStr = lpEnvPtr = (LPSTR)GetEnvironmentStrings(); + + /* step over current directory stuff */ + while(*lpStr == '=') + lpStr += strlen(lpStr) + 1; + + while(*lpStr) { + lpPtr = strchr(lpStr, '='); + if(lpPtr) { + ch = *++lpPtr; + *lpPtr = 0; + Add(lpStr); + *lpPtr = ch; + } + lpStr += strlen(lpStr) + 1; + } + + FreeEnvironmentStrings(lpEnvPtr); +} + + +char* +CPerlHost::Getenv(const char *varname) +{ + char* pEnv = Find(varname); + if(pEnv == NULL) { + pEnv = win32_getenv(varname); + } + else { + if(!*pEnv) + pEnv = 0; + } + + return pEnv; +} + +int +CPerlHost::Putenv(const char *envstring) +{ + Add(envstring); + return 0; +} + +int +CPerlHost::Chdir(const char *dirname) +{ + dTHXo; + int ret; + if (USING_WIDE()) { + WCHAR wBuffer[MAX_PATH]; + A2WHELPER(dirname, wBuffer, sizeof(wBuffer)); + ret = m_pvDir->SetCurrentDirectoryW(wBuffer); + } + else + ret = m_pvDir->SetCurrentDirectoryA((char*)dirname); + if(ret < 0) { + errno = ENOENT; + } + return ret; +} + +#endif /* ___PerlHost_H___ */ diff --git a/win32/perllib.c b/win32/perllib.c index 9cd542b..717b902 100644 --- a/win32/perllib.c +++ b/win32/perllib.c @@ -15,1304 +15,33 @@ #ifdef PERL_IMPLICIT_SYS #include "win32iop.h" #include -#endif - - -/* Register any extra external extensions */ -char *staticlinkmodules[] = { - "DynaLoader", - NULL, -}; - -EXTERN_C void boot_DynaLoader (pTHXo_ CV* cv); - -static void -xs_init(pTHXo) -{ - char *file = __FILE__; - dXSUB_SYS; - newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); -} - -#ifdef PERL_IMPLICIT_SYS -/* IPerlMem */ -void* -PerlMemMalloc(struct IPerlMem *I, size_t size) -{ - return win32_malloc(size); -} -void* -PerlMemRealloc(struct IPerlMem *I, void* ptr, size_t size) -{ - return win32_realloc(ptr, size); -} -void -PerlMemFree(struct IPerlMem *I, void* ptr) -{ - win32_free(ptr); -} - -struct IPerlMem perlMem = -{ - PerlMemMalloc, - PerlMemRealloc, - PerlMemFree, -}; - - -/* IPerlEnv */ -extern char * g_win32_get_privlib(char *pl); -extern char * g_win32_get_sitelib(char *pl); - - -char* -PerlEnvGetenv(struct IPerlEnv *I, const char *varname) -{ - return win32_getenv(varname); -}; -int -PerlEnvPutenv(struct IPerlEnv *I, const char *envstring) -{ - return win32_putenv(envstring); -}; - -char* -PerlEnvGetenv_len(struct IPerlEnv *I, const char* varname, unsigned long* len) -{ - char *e = win32_getenv(varname); - if (e) - *len = strlen(e); - return e; -} - -int -PerlEnvUname(struct IPerlEnv *I, struct utsname *name) -{ - return win32_uname(name); -} - -void -PerlEnvClearenv(struct IPerlEnv *I) -{ - dTHXo; - char *envv = GetEnvironmentStrings(); - char *cur = envv; - STRLEN len; - while (*cur) { - char *end = strchr(cur,'='); - if (end && end != cur) { - *end = '\0'; - my_setenv(cur,Nullch); - *end = '='; - cur = end + strlen(end+1)+2; - } - else if ((len = strlen(cur))) - cur += len+1; - } - FreeEnvironmentStrings(envv); -} - -void* -PerlEnvGetChildEnv(struct IPerlEnv *I) -{ - return NULL; -} - -void -PerlEnvFreeChildEnv(struct IPerlEnv *I, void* env) -{ -} - -char* -PerlEnvGetChildDir(struct IPerlEnv *I) -{ - return NULL; -} - -void -PerlEnvFreeChildDir(struct IPerlEnv *I, char* dir) -{ -} - -unsigned long -PerlEnvOsId(struct IPerlEnv *I) -{ - return win32_os_id(); -} - -char* -PerlEnvLibPath(struct IPerlEnv *I, char *pl) -{ - return g_win32_get_privlib(pl); -} - -char* -PerlEnvSiteLibPath(struct IPerlEnv *I, char *pl) -{ - return g_win32_get_sitelib(pl); -} - -struct IPerlEnv perlEnv = -{ - PerlEnvGetenv, - PerlEnvPutenv, - PerlEnvGetenv_len, - PerlEnvUname, - PerlEnvClearenv, - PerlEnvGetChildEnv, - PerlEnvFreeChildEnv, - PerlEnvGetChildDir, - PerlEnvFreeChildDir, - PerlEnvOsId, - PerlEnvLibPath, - PerlEnvSiteLibPath, -}; - - -/* PerlStdIO */ -PerlIO* -PerlStdIOStdin(struct IPerlStdIO *I) -{ - return (PerlIO*)win32_stdin(); -} - -PerlIO* -PerlStdIOStdout(struct IPerlStdIO *I) -{ - return (PerlIO*)win32_stdout(); -} - -PerlIO* -PerlStdIOStderr(struct IPerlStdIO *I) -{ - return (PerlIO*)win32_stderr(); -} - -PerlIO* -PerlStdIOOpen(struct IPerlStdIO *I, const char *path, const char *mode) -{ - return (PerlIO*)win32_fopen(path, mode); -} - -int -PerlStdIOClose(struct IPerlStdIO *I, PerlIO* pf) -{ - return win32_fclose(((FILE*)pf)); -} - -int -PerlStdIOEof(struct IPerlStdIO *I, PerlIO* pf) -{ - return win32_feof((FILE*)pf); -} - -int -PerlStdIOError(struct IPerlStdIO *I, PerlIO* pf) -{ - return win32_ferror((FILE*)pf); -} - -void -PerlStdIOClearerr(struct IPerlStdIO *I, PerlIO* pf) -{ - win32_clearerr((FILE*)pf); -} - -int -PerlStdIOGetc(struct IPerlStdIO *I, PerlIO* pf) -{ - return win32_getc((FILE*)pf); -} - -char* -PerlStdIOGetBase(struct IPerlStdIO *I, PerlIO* pf) -{ -#ifdef FILE_base - FILE *f = (FILE*)pf; - return FILE_base(f); -#else - return Nullch; -#endif -} - -int -PerlStdIOGetBufsiz(struct IPerlStdIO *I, PerlIO* pf) -{ -#ifdef FILE_bufsiz - FILE *f = (FILE*)pf; - return FILE_bufsiz(f); -#else - return (-1); -#endif -} - -int -PerlStdIOGetCnt(struct IPerlStdIO *I, PerlIO* pf) -{ -#ifdef USE_STDIO_PTR - FILE *f = (FILE*)pf; - return FILE_cnt(f); -#else - return (-1); -#endif -} - -char* -PerlStdIOGetPtr(struct IPerlStdIO *I, PerlIO* pf) -{ -#ifdef USE_STDIO_PTR - FILE *f = (FILE*)pf; - return FILE_ptr(f); -#else - return Nullch; -#endif -} - -char* -PerlStdIOGets(struct IPerlStdIO *I, PerlIO* pf, char* s, int n) -{ - return win32_fgets(s, n, (FILE*)pf); -} - -int -PerlStdIOPutc(struct IPerlStdIO *I, PerlIO* pf, int c) -{ - return win32_fputc(c, (FILE*)pf); -} - -int -PerlStdIOPuts(struct IPerlStdIO *I, PerlIO* pf, const char *s) -{ - return win32_fputs(s, (FILE*)pf); -} - -int -PerlStdIOFlush(struct IPerlStdIO *I, PerlIO* pf) -{ - return win32_fflush((FILE*)pf); -} - -int -PerlStdIOUngetc(struct IPerlStdIO *I, PerlIO* pf,int c) -{ - return win32_ungetc(c, (FILE*)pf); -} - -int -PerlStdIOFileno(struct IPerlStdIO *I, PerlIO* pf) -{ - return win32_fileno((FILE*)pf); -} - -PerlIO* -PerlStdIOFdopen(struct IPerlStdIO *I, int fd, const char *mode) -{ - return (PerlIO*)win32_fdopen(fd, mode); -} - -PerlIO* -PerlStdIOReopen(struct IPerlStdIO *I, const char*path, const char*mode, PerlIO* pf) -{ - return (PerlIO*)win32_freopen(path, mode, (FILE*)pf); -} - -SSize_t -PerlStdIORead(struct IPerlStdIO *I, PerlIO* pf, void *buffer, Size_t size) -{ - return win32_fread(buffer, 1, size, (FILE*)pf); -} - -SSize_t -PerlStdIOWrite(struct IPerlStdIO *I, PerlIO* pf, const void *buffer, Size_t size) -{ - return win32_fwrite(buffer, 1, size, (FILE*)pf); -} - -void -PerlStdIOSetBuf(struct IPerlStdIO *I, PerlIO* pf, char* buffer) -{ - win32_setbuf((FILE*)pf, buffer); -} - -int -PerlStdIOSetVBuf(struct IPerlStdIO *I, PerlIO* pf, char* buffer, int type, Size_t size) -{ - return win32_setvbuf((FILE*)pf, buffer, type, size); -} - -void -PerlStdIOSetCnt(struct IPerlStdIO *I, PerlIO* pf, int n) -{ -#ifdef STDIO_CNT_LVALUE - FILE *f = (FILE*)pf; - FILE_cnt(f) = n; -#endif -} - -void -PerlStdIOSetPtrCnt(struct IPerlStdIO *I, PerlIO* pf, char * ptr, int n) -{ -#ifdef STDIO_PTR_LVALUE - FILE *f = (FILE*)pf; - FILE_ptr(f) = ptr; - FILE_cnt(f) = n; -#endif -} - -void -PerlStdIOSetlinebuf(struct IPerlStdIO *I, PerlIO* pf) -{ - win32_setvbuf((FILE*)pf, NULL, _IOLBF, 0); -} - -int -PerlStdIOPrintf(struct IPerlStdIO *I, PerlIO* pf, const char *format,...) -{ - va_list(arglist); - va_start(arglist, format); - return win32_vfprintf((FILE*)pf, format, arglist); -} - -int -PerlStdIOVprintf(struct IPerlStdIO *I, PerlIO* pf, const char *format, va_list arglist) -{ - return win32_vfprintf((FILE*)pf, format, arglist); -} - -long -PerlStdIOTell(struct IPerlStdIO *I, PerlIO* pf) -{ - return win32_ftell((FILE*)pf); -} - -int -PerlStdIOSeek(struct IPerlStdIO *I, PerlIO* pf, off_t offset, int origin) -{ - return win32_fseek((FILE*)pf, offset, origin); -} - -void -PerlStdIORewind(struct IPerlStdIO *I, PerlIO* pf) -{ - win32_rewind((FILE*)pf); -} - -PerlIO* -PerlStdIOTmpfile(struct IPerlStdIO *I) -{ - return (PerlIO*)win32_tmpfile(); -} - -int -PerlStdIOGetpos(struct IPerlStdIO *I, PerlIO* pf, Fpos_t *p) -{ - return win32_fgetpos((FILE*)pf, p); -} - -int -PerlStdIOSetpos(struct IPerlStdIO *I, PerlIO* pf, const Fpos_t *p) -{ - return win32_fsetpos((FILE*)pf, p); -} -void -PerlStdIOInit(struct IPerlStdIO *I) -{ -} - -void -PerlStdIOInitOSExtras(struct IPerlStdIO *I) -{ - Perl_init_os_extras(); -} - -int -PerlStdIOOpenOSfhandle(struct IPerlStdIO *I, long osfhandle, int flags) -{ - return win32_open_osfhandle(osfhandle, flags); -} - -int -PerlStdIOGetOSfhandle(struct IPerlStdIO *I, int filenum) -{ - return win32_get_osfhandle(filenum); -} - - -struct IPerlStdIO perlStdIO = -{ - PerlStdIOStdin, - PerlStdIOStdout, - PerlStdIOStderr, - PerlStdIOOpen, - PerlStdIOClose, - PerlStdIOEof, - PerlStdIOError, - PerlStdIOClearerr, - PerlStdIOGetc, - PerlStdIOGetBase, - PerlStdIOGetBufsiz, - PerlStdIOGetCnt, - PerlStdIOGetPtr, - PerlStdIOGets, - PerlStdIOPutc, - PerlStdIOPuts, - PerlStdIOFlush, - PerlStdIOUngetc, - PerlStdIOFileno, - PerlStdIOFdopen, - PerlStdIOReopen, - PerlStdIORead, - PerlStdIOWrite, - PerlStdIOSetBuf, - PerlStdIOSetVBuf, - PerlStdIOSetCnt, - PerlStdIOSetPtrCnt, - PerlStdIOSetlinebuf, - PerlStdIOPrintf, - PerlStdIOVprintf, - PerlStdIOTell, - PerlStdIOSeek, - PerlStdIORewind, - PerlStdIOTmpfile, - PerlStdIOGetpos, - PerlStdIOSetpos, - PerlStdIOInit, - PerlStdIOInitOSExtras, -}; - - -/* IPerlLIO */ -int -PerlLIOAccess(struct IPerlLIO *I, const char *path, int mode) -{ - return access(path, mode); -} - -int -PerlLIOChmod(struct IPerlLIO *I, const char *filename, int pmode) -{ - return chmod(filename, pmode); -} - -int -PerlLIOChown(struct IPerlLIO *I, const char *filename, uid_t owner, gid_t group) -{ - return chown(filename, owner, group); -} - -int -PerlLIOChsize(struct IPerlLIO *I, int handle, long size) -{ - return chsize(handle, size); -} - -int -PerlLIOClose(struct IPerlLIO *I, int handle) -{ - return win32_close(handle); -} - -int -PerlLIODup(struct IPerlLIO *I, int handle) -{ - return win32_dup(handle); -} - -int -PerlLIODup2(struct IPerlLIO *I, int handle1, int handle2) -{ - return win32_dup2(handle1, handle2); -} - -int -PerlLIOFlock(struct IPerlLIO *I, int fd, int oper) -{ - return win32_flock(fd, oper); -} - -int -PerlLIOFileStat(struct IPerlLIO *I, int handle, struct stat *buffer) -{ - return fstat(handle, buffer); -} - -int -PerlLIOIOCtl(struct IPerlLIO *I, int i, unsigned int u, char *data) -{ - return win32_ioctlsocket((SOCKET)i, (long)u, (u_long*)data); -} - -int -PerlLIOIsatty(struct IPerlLIO *I, int fd) -{ - return isatty(fd); -} - -int -PerlLIOLink(struct IPerlLIO *I, const char*oldname, const char *newname) -{ - return win32_link(oldname, newname); -} - -long -PerlLIOLseek(struct IPerlLIO *I, int handle, long offset, int origin) -{ - return win32_lseek(handle, offset, origin); -} - -int -PerlLIOLstat(struct IPerlLIO* p, const char *path, struct stat *buffer) -{ - return win32_stat(path, buffer); -} - -char* -PerlLIOMktemp(struct IPerlLIO *I, char *Template) -{ - return mktemp(Template); -} - -int -PerlLIOOpen(struct IPerlLIO *I, const char *filename, int oflag) -{ - return win32_open(filename, oflag); -} - -int -PerlLIOOpen3(struct IPerlLIO *I, const char *filename, int oflag, int pmode) -{ - int ret; - if(stricmp(filename, "/dev/null") == 0) - ret = open("NUL", oflag, pmode); - else - ret = open(filename, oflag, pmode); - - return ret; -} - -int -PerlLIORead(struct IPerlLIO *I, int handle, void *buffer, unsigned int count) -{ - return win32_read(handle, buffer, count); -} - -int -PerlLIORename(struct IPerlLIO *I, const char *OldFileName, const char *newname) -{ - return win32_rename(OldFileName, newname); -} - -int -PerlLIOSetmode(struct IPerlLIO *I, int handle, int mode) -{ - return win32_setmode(handle, mode); -} - -int -PerlLIONameStat(struct IPerlLIO *I, const char *path, struct stat *buffer) -{ - return win32_stat(path, buffer); -} - -char* -PerlLIOTmpnam(struct IPerlLIO *I, char *string) -{ - return tmpnam(string); -} - -int -PerlLIOUmask(struct IPerlLIO *I, int pmode) -{ - return umask(pmode); -} - -int -PerlLIOUnlink(struct IPerlLIO *I, const char *filename) -{ - chmod(filename, S_IREAD | S_IWRITE); - return unlink(filename); -} - -int -PerlLIOUtime(struct IPerlLIO *I, char *filename, struct utimbuf *times) -{ - return win32_utime(filename, times); -} - -int -PerlLIOWrite(struct IPerlLIO *I, int handle, const void *buffer, unsigned int count) -{ - return win32_write(handle, buffer, count); -} - -struct IPerlLIO perlLIO = -{ - PerlLIOAccess, - PerlLIOChmod, - PerlLIOChown, - PerlLIOChsize, - PerlLIOClose, - PerlLIODup, - PerlLIODup2, - PerlLIOFlock, - PerlLIOFileStat, - PerlLIOIOCtl, - PerlLIOIsatty, - PerlLIOLink, - PerlLIOLseek, - PerlLIOLstat, - PerlLIOMktemp, - PerlLIOOpen, - PerlLIOOpen3, - PerlLIORead, - PerlLIORename, - PerlLIOSetmode, - PerlLIONameStat, - PerlLIOTmpnam, - PerlLIOUmask, - PerlLIOUnlink, - PerlLIOUtime, - PerlLIOWrite, -}; - -/* IPerlDIR */ -int -PerlDirMakedir(struct IPerlDir *I, const char *dirname, int mode) -{ - return win32_mkdir(dirname, mode); -} - -int -PerlDirChdir(struct IPerlDir *I, const char *dirname) -{ - return win32_chdir(dirname); -} - -int -PerlDirRmdir(struct IPerlDir *I, const char *dirname) -{ - return win32_rmdir(dirname); -} - -int -PerlDirClose(struct IPerlDir *I, DIR *dirp) -{ - return win32_closedir(dirp); -} - -DIR* -PerlDirOpen(struct IPerlDir *I, char *filename) -{ - return win32_opendir(filename); -} - -struct direct * -PerlDirRead(struct IPerlDir *I, DIR *dirp) -{ - return win32_readdir(dirp); -} - -void -PerlDirRewind(struct IPerlDir *I, DIR *dirp) -{ - win32_rewinddir(dirp); -} - -void -PerlDirSeek(struct IPerlDir *I, DIR *dirp, long loc) -{ - win32_seekdir(dirp, loc); -} - -long -PerlDirTell(struct IPerlDir *I, DIR *dirp) -{ - return win32_telldir(dirp); -} - -struct IPerlDir perlDir = -{ - PerlDirMakedir, - PerlDirChdir, - PerlDirRmdir, - PerlDirClose, - PerlDirOpen, - PerlDirRead, - PerlDirRewind, - PerlDirSeek, - PerlDirTell, -}; - - -/* IPerlSock */ -u_long -PerlSockHtonl(struct IPerlSock *I, u_long hostlong) -{ - return win32_htonl(hostlong); -} - -u_short -PerlSockHtons(struct IPerlSock *I, u_short hostshort) -{ - return win32_htons(hostshort); -} - -u_long -PerlSockNtohl(struct IPerlSock *I, u_long netlong) -{ - return win32_ntohl(netlong); -} - -u_short -PerlSockNtohs(struct IPerlSock *I, u_short netshort) -{ - return win32_ntohs(netshort); -} - -SOCKET PerlSockAccept(struct IPerlSock *I, SOCKET s, struct sockaddr* addr, int* addrlen) -{ - return win32_accept(s, addr, addrlen); -} - -int -PerlSockBind(struct IPerlSock *I, SOCKET s, const struct sockaddr* name, int namelen) -{ - return win32_bind(s, name, namelen); -} - -int -PerlSockConnect(struct IPerlSock *I, SOCKET s, const struct sockaddr* name, int namelen) -{ - return win32_connect(s, name, namelen); -} - -void -PerlSockEndhostent(struct IPerlSock *I) -{ - win32_endhostent(); -} - -void -PerlSockEndnetent(struct IPerlSock *I) -{ - win32_endnetent(); -} - -void -PerlSockEndprotoent(struct IPerlSock *I) -{ - win32_endprotoent(); -} - -void -PerlSockEndservent(struct IPerlSock *I) -{ - win32_endservent(); -} - -struct hostent* -PerlSockGethostbyaddr(struct IPerlSock *I, const char* addr, int len, int type) -{ - return win32_gethostbyaddr(addr, len, type); -} - -struct hostent* -PerlSockGethostbyname(struct IPerlSock *I, const char* name) -{ - return win32_gethostbyname(name); -} - -struct hostent* -PerlSockGethostent(struct IPerlSock *I) -{ - dTHXo; - Perl_croak(aTHX_ "gethostent not implemented!\n"); - return NULL; -} - -int -PerlSockGethostname(struct IPerlSock *I, char* name, int namelen) -{ - return win32_gethostname(name, namelen); -} - -struct netent * -PerlSockGetnetbyaddr(struct IPerlSock *I, long net, int type) -{ - return win32_getnetbyaddr(net, type); -} - -struct netent * -PerlSockGetnetbyname(struct IPerlSock *I, const char *name) -{ - return win32_getnetbyname((char*)name); -} - -struct netent * -PerlSockGetnetent(struct IPerlSock *I) -{ - return win32_getnetent(); -} - -int PerlSockGetpeername(struct IPerlSock *I, SOCKET s, struct sockaddr* name, int* namelen) -{ - return win32_getpeername(s, name, namelen); -} - -struct protoent* -PerlSockGetprotobyname(struct IPerlSock *I, const char* name) -{ - return win32_getprotobyname(name); -} - -struct protoent* -PerlSockGetprotobynumber(struct IPerlSock *I, int number) -{ - return win32_getprotobynumber(number); -} - -struct protoent* -PerlSockGetprotoent(struct IPerlSock *I) -{ - return win32_getprotoent(); -} - -struct servent* -PerlSockGetservbyname(struct IPerlSock *I, const char* name, const char* proto) -{ - return win32_getservbyname(name, proto); -} - -struct servent* -PerlSockGetservbyport(struct IPerlSock *I, int port, const char* proto) -{ - return win32_getservbyport(port, proto); -} - -struct servent* -PerlSockGetservent(struct IPerlSock *I) -{ - return win32_getservent(); -} - -int -PerlSockGetsockname(struct IPerlSock *I, SOCKET s, struct sockaddr* name, int* namelen) -{ - return win32_getsockname(s, name, namelen); -} - -int -PerlSockGetsockopt(struct IPerlSock *I, SOCKET s, int level, int optname, char* optval, int* optlen) -{ - return win32_getsockopt(s, level, optname, optval, optlen); -} - -unsigned long -PerlSockInetAddr(struct IPerlSock *I, const char* cp) -{ - return win32_inet_addr(cp); -} - -char* -PerlSockInetNtoa(struct IPerlSock *I, struct in_addr in) -{ - return win32_inet_ntoa(in); -} - -int -PerlSockListen(struct IPerlSock *I, SOCKET s, int backlog) -{ - return win32_listen(s, backlog); -} - -int -PerlSockRecv(struct IPerlSock *I, SOCKET s, char* buffer, int len, int flags) -{ - return win32_recv(s, buffer, len, flags); -} - -int -PerlSockRecvfrom(struct IPerlSock *I, SOCKET s, char* buffer, int len, int flags, struct sockaddr* from, int* fromlen) -{ - return win32_recvfrom(s, buffer, len, flags, from, fromlen); -} - -int -PerlSockSelect(struct IPerlSock *I, int nfds, char* readfds, char* writefds, char* exceptfds, const struct timeval* timeout) -{ - return win32_select(nfds, (Perl_fd_set*)readfds, (Perl_fd_set*)writefds, (Perl_fd_set*)exceptfds, timeout); -} - -int -PerlSockSend(struct IPerlSock *I, SOCKET s, const char* buffer, int len, int flags) -{ - return win32_send(s, buffer, len, flags); -} - -int -PerlSockSendto(struct IPerlSock *I, SOCKET s, const char* buffer, int len, int flags, const struct sockaddr* to, int tolen) -{ - return win32_sendto(s, buffer, len, flags, to, tolen); -} - -void -PerlSockSethostent(struct IPerlSock *I, int stayopen) -{ - win32_sethostent(stayopen); -} - -void -PerlSockSetnetent(struct IPerlSock *I, int stayopen) -{ - win32_setnetent(stayopen); -} - -void -PerlSockSetprotoent(struct IPerlSock *I, int stayopen) -{ - win32_setprotoent(stayopen); -} - -void -PerlSockSetservent(struct IPerlSock *I, int stayopen) -{ - win32_setservent(stayopen); -} - -int -PerlSockSetsockopt(struct IPerlSock *I, SOCKET s, int level, int optname, const char* optval, int optlen) -{ - return win32_setsockopt(s, level, optname, optval, optlen); -} - -int -PerlSockShutdown(struct IPerlSock *I, SOCKET s, int how) -{ - return win32_shutdown(s, how); -} - -SOCKET -PerlSockSocket(struct IPerlSock *I, int af, int type, int protocol) -{ - return win32_socket(af, type, protocol); -} - -int -PerlSockSocketpair(struct IPerlSock *I, int domain, int type, int protocol, int* fds) -{ - dTHXo; - Perl_croak(aTHX_ "socketpair not implemented!\n"); - return 0; -} - -int -PerlSockClosesocket(struct IPerlSock *I, SOCKET s) -{ - return win32_closesocket(s); -} +#endif /* PERL_IMPLICIT_SYS */ -int -PerlSockIoctlsocket(struct IPerlSock *I, SOCKET s, long cmd, u_long *argp) -{ - return win32_ioctlsocket(s, cmd, argp); -} -struct IPerlSock perlSock = -{ - PerlSockHtonl, - PerlSockHtons, - PerlSockNtohl, - PerlSockNtohs, - PerlSockAccept, - PerlSockBind, - PerlSockConnect, - PerlSockEndhostent, - PerlSockEndnetent, - PerlSockEndprotoent, - PerlSockEndservent, - PerlSockGethostname, - PerlSockGetpeername, - PerlSockGethostbyaddr, - PerlSockGethostbyname, - PerlSockGethostent, - PerlSockGetnetbyaddr, - PerlSockGetnetbyname, - PerlSockGetnetent, - PerlSockGetprotobyname, - PerlSockGetprotobynumber, - PerlSockGetprotoent, - PerlSockGetservbyname, - PerlSockGetservbyport, - PerlSockGetservent, - PerlSockGetsockname, - PerlSockGetsockopt, - PerlSockInetAddr, - PerlSockInetNtoa, - PerlSockListen, - PerlSockRecv, - PerlSockRecvfrom, - PerlSockSelect, - PerlSockSend, - PerlSockSendto, - PerlSockSethostent, - PerlSockSetnetent, - PerlSockSetprotoent, - PerlSockSetservent, - PerlSockSetsockopt, - PerlSockShutdown, - PerlSockSocket, - PerlSockSocketpair, - PerlSockClosesocket, +/* Register any extra external extensions */ +char *staticlinkmodules[] = { + "DynaLoader", + NULL, }; +EXTERN_C void boot_DynaLoader (pTHXo_ CV* cv); -/* IPerlProc */ - -#define EXECF_EXEC 1 -#define EXECF_SPAWN 2 - -extern char * g_getlogin(void); -extern int do_spawn2(char *cmd, int exectype); -#ifdef PERL_OBJECT -extern int g_do_aspawn(void *vreally, void **vmark, void **vsp); -#define do_aspawn g_do_aspawn -#endif -EXTERN_C PerlInterpreter* perl_alloc_using(struct IPerlMem* pMem, - struct IPerlEnv* pEnv, struct IPerlStdIO* pStdIO, - struct IPerlLIO* pLIO, struct IPerlDir* pDir, - struct IPerlSock* pSock, struct IPerlProc* pProc); - -void -PerlProcAbort(struct IPerlProc *I) -{ - win32_abort(); -} - -char * -PerlProcCrypt(struct IPerlProc *I, const char* clear, const char* salt) -{ - return win32_crypt(clear, salt); -} - -void -PerlProcExit(struct IPerlProc *I, int status) -{ - exit(status); -} - -void -PerlProc_Exit(struct IPerlProc *I, int status) -{ - _exit(status); -} - -int -PerlProcExecl(struct IPerlProc *I, const char *cmdname, const char *arg0, const char *arg1, const char *arg2, const char *arg3) -{ - return execl(cmdname, arg0, arg1, arg2, arg3); -} - -int -PerlProcExecv(struct IPerlProc *I, const char *cmdname, const char *const *argv) -{ - return win32_execvp(cmdname, argv); -} - -int -PerlProcExecvp(struct IPerlProc *I, const char *cmdname, const char *const *argv) -{ - return win32_execvp(cmdname, argv); -} - -uid_t -PerlProcGetuid(struct IPerlProc *I) -{ - return getuid(); -} - -uid_t -PerlProcGeteuid(struct IPerlProc *I) -{ - return geteuid(); -} - -gid_t -PerlProcGetgid(struct IPerlProc *I) -{ - return getgid(); -} - -gid_t -PerlProcGetegid(struct IPerlProc *I) -{ - return getegid(); -} - -char * -PerlProcGetlogin(struct IPerlProc *I) -{ - return g_getlogin(); -} - -int -PerlProcKill(struct IPerlProc *I, int pid, int sig) -{ - return win32_kill(pid, sig); -} - -int -PerlProcKillpg(struct IPerlProc *I, int pid, int sig) -{ - dTHXo; - Perl_croak(aTHX_ "killpg not implemented!\n"); - return 0; -} - -int -PerlProcPauseProc(struct IPerlProc *I) -{ - return win32_sleep((32767L << 16) + 32767); -} - -PerlIO* -PerlProcPopen(struct IPerlProc *I, const char *command, const char *mode) -{ - dTHXo; - PERL_FLUSHALL_FOR_CHILD; - return (PerlIO*)win32_popen(command, mode); -} - -int -PerlProcPclose(struct IPerlProc *I, PerlIO *stream) -{ - return win32_pclose((FILE*)stream); -} - -int -PerlProcPipe(struct IPerlProc *I, int *phandles) -{ - return win32_pipe(phandles, 512, O_BINARY); -} - -int -PerlProcSetuid(struct IPerlProc *I, uid_t u) -{ - return setuid(u); -} - -int -PerlProcSetgid(struct IPerlProc *I, gid_t g) -{ - return setgid(g); -} - -int -PerlProcSleep(struct IPerlProc *I, unsigned int s) -{ - return win32_sleep(s); -} - -int -PerlProcTimes(struct IPerlProc *I, struct tms *timebuf) -{ - return win32_times(timebuf); -} - -int -PerlProcWait(struct IPerlProc *I, int *status) -{ - return win32_wait(status); -} - -int -PerlProcWaitpid(struct IPerlProc *I, int pid, int *status, int flags) -{ - return win32_waitpid(pid, status, flags); -} - -Sighandler_t -PerlProcSignal(struct IPerlProc *I, int sig, Sighandler_t subcode) -{ - return 0; -} - -void* -PerlProcDynaLoader(struct IPerlProc *I, const char* filename) -{ - return win32_dynaload(filename); -} - -void -PerlProcGetOSError(struct IPerlProc *I, SV* sv, DWORD dwErr) -{ - win32_str_os_error(sv, dwErr); -} - -BOOL -PerlProcDoCmd(struct IPerlProc *I, char *cmd) -{ - do_spawn2(cmd, EXECF_EXEC); - return FALSE; -} - -int -PerlProcSpawn(struct IPerlProc *I, char* cmds) -{ - return do_spawn2(cmds, EXECF_SPAWN); -} - -int -PerlProcSpawnvp(struct IPerlProc *I, int mode, const char *cmdname, const char *const *argv) -{ - return win32_spawnvp(mode, cmdname, argv); -} - -int -PerlProcASpawn(struct IPerlProc *I, void *vreally, void **vmark, void **vsp) +static void +xs_init(pTHXo) { - return do_aspawn(vreally, vmark, vsp); + char *file = __FILE__; + dXSUB_SYS; + newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); } -struct IPerlProc perlProc = -{ - PerlProcAbort, - PerlProcCrypt, - PerlProcExit, - PerlProc_Exit, - PerlProcExecl, - PerlProcExecv, - PerlProcExecvp, - PerlProcGetuid, - PerlProcGeteuid, - PerlProcGetgid, - PerlProcGetegid, - PerlProcGetlogin, - PerlProcKill, - PerlProcKillpg, - PerlProcPauseProc, - PerlProcPopen, - PerlProcPclose, - PerlProcPipe, - PerlProcSetuid, - PerlProcSetgid, - PerlProcSleep, - PerlProcTimes, - PerlProcWait, - PerlProcWaitpid, - PerlProcSignal, - PerlProcDynaLoader, - PerlProcGetOSError, - PerlProcDoCmd, - PerlProcSpawn, - PerlProcSpawnvp, - PerlProcASpawn, -}; - -/*#include "perlhost.h" */ +#ifdef PERL_IMPLICIT_SYS +#include "perlhost.h" EXTERN_C void perl_get_host_info(struct IPerlMemInfo* perlMemInfo, + struct IPerlMemInfo* perlMemSharedInfo, + struct IPerlMemInfo* perlMemParseInfo, struct IPerlEnvInfo* perlEnvInfo, struct IPerlStdIOInfo* perlStdIOInfo, struct IPerlLIOInfo* perlLIOInfo, @@ -1320,31 +49,39 @@ perl_get_host_info(struct IPerlMemInfo* perlMemInfo, struct IPerlSockInfo* perlSockInfo, struct IPerlProcInfo* perlProcInfo) { - if(perlMemInfo) { + if (perlMemInfo) { Copy(&perlMem, &perlMemInfo->perlMemList, perlMemInfo->nCount, void*); perlMemInfo->nCount = (sizeof(struct IPerlMem)/sizeof(void*)); } - if(perlEnvInfo) { + if (perlMemSharedInfo) { + Copy(&perlMem, &perlMemSharedInfo->perlMemList, perlMemSharedInfo->nCount, void*); + perlMemSharedInfo->nCount = (sizeof(struct IPerlMem)/sizeof(void*)); + } + if (perlMemParseInfo) { + Copy(&perlMem, &perlMemParseInfo->perlMemList, perlMemParseInfo->nCount, void*); + perlMemParseInfo->nCount = (sizeof(struct IPerlMem)/sizeof(void*)); + } + if (perlEnvInfo) { Copy(&perlEnv, &perlEnvInfo->perlEnvList, perlEnvInfo->nCount, void*); perlEnvInfo->nCount = (sizeof(struct IPerlEnv)/sizeof(void*)); } - if(perlStdIOInfo) { + if (perlStdIOInfo) { Copy(&perlStdIO, &perlStdIOInfo->perlStdIOList, perlStdIOInfo->nCount, void*); perlStdIOInfo->nCount = (sizeof(struct IPerlStdIO)/sizeof(void*)); } - if(perlLIOInfo) { + if (perlLIOInfo) { Copy(&perlLIO, &perlLIOInfo->perlLIOList, perlLIOInfo->nCount, void*); perlLIOInfo->nCount = (sizeof(struct IPerlLIO)/sizeof(void*)); } - if(perlDirInfo) { + if (perlDirInfo) { Copy(&perlDir, &perlDirInfo->perlDirList, perlDirInfo->nCount, void*); perlDirInfo->nCount = (sizeof(struct IPerlDir)/sizeof(void*)); } - if(perlSockInfo) { + if (perlSockInfo) { Copy(&perlSock, &perlSockInfo->perlSockList, perlSockInfo->nCount, void*); perlSockInfo->nCount = (sizeof(struct IPerlSock)/sizeof(void*)); } - if(perlProcInfo) { + if (perlProcInfo) { Copy(&perlProc, &perlProcInfo->perlProcList, perlProcInfo->nCount, void*); perlProcInfo->nCount = (sizeof(struct IPerlProc)/sizeof(void*)); } @@ -1352,142 +89,173 @@ perl_get_host_info(struct IPerlMemInfo* perlMemInfo, #ifdef PERL_OBJECT -EXTERN_C PerlInterpreter* perl_alloc_using(struct IPerlMem* pMem, - struct IPerlEnv* pEnv, struct IPerlStdIO* pStdIO, - struct IPerlLIO* pLIO, struct IPerlDir* pDir, - struct IPerlSock* pSock, struct IPerlProc* pProc) +EXTERN_C PerlInterpreter* +perl_alloc_override(struct IPerlMem** ppMem, struct IPerlMem** ppMemShared, + struct IPerlMem** ppMemParse, struct IPerlEnv** ppEnv, + struct IPerlStdIO** ppStdIO, struct IPerlLIO** ppLIO, + struct IPerlDir** ppDir, struct IPerlSock** ppSock, + struct IPerlProc** ppProc) { - CPerlObj* pPerl = NULL; + PerlInterpreter *my_perl = NULL; try { - pPerl = Perl_alloc(pMem, pEnv, pStdIO, pLIO, pDir, pSock, pProc); + CPerlHost* pHost = new CPerlHost(ppMem, ppMemShared, ppMemParse, ppEnv, + ppStdIO, ppLIO, ppDir, ppSock, ppProc); + + if (pHost) { + my_perl = perl_alloc_using(pHost->m_pHostperlMem, + pHost->m_pHostperlMemShared, + pHost->m_pHostperlMemParse, + pHost->m_pHostperlEnv, + pHost->m_pHostperlStdIO, + pHost->m_pHostperlLIO, + pHost->m_pHostperlDir, + pHost->m_pHostperlSock, + pHost->m_pHostperlProc); + if (my_perl) { + CPerlObj* pPerl = (CPerlObj*)my_perl; + w32_internal_host = pHost; + } + } } catch(...) { win32_fprintf(stderr, "%s\n", "Error: Unable to allocate memory"); - pPerl = NULL; - } - if(pPerl) - { - SetPerlInterpreter(pPerl); - return (PerlInterpreter*)pPerl; + my_perl = NULL; } - SetPerlInterpreter(NULL); - return NULL; + + return my_perl; } -#undef perl_alloc -#undef perl_construct -#undef perl_destruct -#undef perl_free -#undef perl_run -#undef perl_parse -EXTERN_C PerlInterpreter* perl_alloc(void) +EXTERN_C PerlInterpreter* +perl_alloc(void) { - CPerlObj* pPerl = NULL; + PerlInterpreter* my_perl = NULL; try { - pPerl = Perl_alloc(&perlMem, &perlEnv, &perlStdIO, &perlLIO, - &perlDir, &perlSock, &perlProc); + CPerlHost* pHost = new CPerlHost(); + if (pHost) { + my_perl = perl_alloc_using(pHost->m_pHostperlMem, + pHost->m_pHostperlMemShared, + pHost->m_pHostperlMemParse, + pHost->m_pHostperlEnv, + pHost->m_pHostperlStdIO, + pHost->m_pHostperlLIO, + pHost->m_pHostperlDir, + pHost->m_pHostperlSock, + pHost->m_pHostperlProc); + if (my_perl) { + CPerlObj* pPerl = (CPerlObj*)my_perl; + w32_internal_host = pHost; + } + } } catch(...) { win32_fprintf(stderr, "%s\n", "Error: Unable to allocate memory"); - pPerl = NULL; - } - if(pPerl) - { - SetPerlInterpreter(pPerl); - return (PerlInterpreter*)pPerl; + my_perl = NULL; } - SetPerlInterpreter(NULL); - return NULL; + + return my_perl; } -EXTERN_C void perl_construct(PerlInterpreter* sv_interp) +EXTERN_C void +perl_construct(PerlInterpreter* my_perl) { - CPerlObj* pPerl = (CPerlObj*)sv_interp; + CPerlObj* pPerl = (CPerlObj*)my_perl; try { - pPerl->perl_construct(); + Perl_construct(); } catch(...) { win32_fprintf(stderr, "%s\n", "Error: Unable to construct data structures"); - pPerl->perl_free(); + CPerlHost* pHost = (CPerlHost*)w32_internal_host; + Perl_free(); + delete pHost; SetPerlInterpreter(NULL); } } -EXTERN_C void perl_destruct(PerlInterpreter* sv_interp) +EXTERN_C void +perl_destruct(PerlInterpreter* my_perl) { - CPerlObj* pPerl = (CPerlObj*)sv_interp; + CPerlObj* pPerl = (CPerlObj*)my_perl; +#ifdef DEBUGGING + Perl_destruct(); +#else try { - pPerl->perl_destruct(); + Perl_destruct(); } catch(...) { } +#endif } -EXTERN_C void perl_free(PerlInterpreter* sv_interp) +EXTERN_C void +perl_free(PerlInterpreter* my_perl) { - CPerlObj* pPerl = (CPerlObj*)sv_interp; + CPerlObj* pPerl = (CPerlObj*)my_perl; +#ifdef DEBUGGING + CPerlHost* pHost = (CPerlHost*)w32_internal_host; + Perl_free(); + delete pHost; +#else try { - pPerl->perl_free(); + CPerlHost* pHost = (CPerlHost*)w32_internal_host; + Perl_free(); + delete pHost; } catch(...) { } +#endif SetPerlInterpreter(NULL); } -EXTERN_C int perl_run(PerlInterpreter* sv_interp) +EXTERN_C int +perl_run(PerlInterpreter* my_perl) { - CPerlObj* pPerl = (CPerlObj*)sv_interp; + CPerlObj* pPerl = (CPerlObj*)my_perl; +#ifdef DEBUGGING + return Perl_run(); +#else int retVal; try { - retVal = pPerl->perl_run(); - } -/* - catch(int x) - { - // this is where exit() should arrive - retVal = x; + retVal = Perl_run(); } -*/ catch(...) { win32_fprintf(stderr, "Error: Runtime exception\n"); retVal = -1; } return retVal; +#endif } -EXTERN_C int perl_parse(PerlInterpreter* sv_interp, void (*xsinit)(CPerlObj*), int argc, char** argv, char** env) +EXTERN_C int +perl_parse(PerlInterpreter* my_perl, void (*xsinit)(CPerlObj*), int argc, char** argv, char** env) { int retVal; - CPerlObj* pPerl = (CPerlObj*)sv_interp; + CPerlObj* pPerl = (CPerlObj*)my_perl; +#ifdef DEBUGGING + retVal = Perl_parse(xsinit, argc, argv, env); +#else try { - retVal = pPerl->perl_parse(xsinit, argc, argv, env); - } -/* - catch(int x) - { - // this is where exit() should arrive - retVal = x; + retVal = Perl_parse(xsinit, argc, argv, env); } -*/ catch(...) { win32_fprintf(stderr, "Error: Parse exception\n"); retVal = -1; } +#endif *win32_errno() = 0; return retVal; } @@ -1500,15 +268,31 @@ EXTERN_C int perl_parse(PerlInterpreter* sv_interp, void (*xsinit)(CPerlObj*), i EXTERN_C PerlInterpreter* perl_alloc(void) { - return perl_alloc_using(&perlMem, &perlEnv, &perlStdIO, &perlLIO, - &perlDir, &perlSock, &perlProc); + PerlInterpreter *my_perl = NULL; + CPerlHost* pHost = new CPerlHost(); + if (pHost) { + my_perl = perl_alloc_using(pHost->m_pHostperlMem, + pHost->m_pHostperlMemShared, + pHost->m_pHostperlMemParse, + pHost->m_pHostperlEnv, + pHost->m_pHostperlStdIO, + pHost->m_pHostperlLIO, + pHost->m_pHostperlDir, + pHost->m_pHostperlSock, + pHost->m_pHostperlProc); + if (my_perl) { + CPerlObj* pPerl = (CPerlObj*)my_perl; + w32_internal_host = pHost; + } + } + return my_perl; } #endif /* PERL_OBJECT */ - #endif /* PERL_IMPLICIT_SYS */ -extern HANDLE w32_perldll_handle; +EXTERN_C HANDLE w32_perldll_handle; + static DWORD g_TlsAllocIndex; EXTERN_C DllExport bool @@ -1563,9 +347,24 @@ RunPerl(int argc, char **argv, char **env) exitstatus = perl_parse(my_perl, xs_init, argc, argv, env); if (!exitstatus) { -#ifdef USE_ITHREADS /* XXXXXX testing */ - new_perl = perl_clone(my_perl, 0); - Perl_push_scope(new_perl); /* ENTER; (hack in lieu of perl_destruct()) */ +#if defined(TOP_CLONE) && defined(USE_ITHREADS) /* XXXXXX testing */ +# ifdef PERL_OBJECT + CPerlHost *h = new CPerlHost(); + new_perl = perl_clone_using(my_perl, 1, + h->m_pHostperlMem, + h->m_pHostperlMemShared, + h->m_pHostperlMemParse, + h->m_pHostperlEnv, + h->m_pHostperlStdIO, + h->m_pHostperlLIO, + h->m_pHostperlDir, + h->m_pHostperlSock, + h->m_pHostperlProc + ); + CPerlObj *pPerl = (CPerlObj*)new_perl; +# else + new_perl = perl_clone(my_perl, 1); +# endif exitstatus = perl_run( new_perl ); SetPerlInterpreter(my_perl); #else @@ -1630,4 +429,3 @@ DllMain(HANDLE hModule, /* DLL module handle */ } return TRUE; } - diff --git a/win32/vdir.h b/win32/vdir.h new file mode 100644 index 0000000..0d21616 --- /dev/null +++ b/win32/vdir.h @@ -0,0 +1,467 @@ +/* vdir.h + * + * (c) 1999 Microsoft Corporation. All rights reserved. + * Portions (c) 1999 ActiveState Tool Corp, http://www.ActiveState.com/ + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the README file. + */ + +#ifndef ___VDir_H___ +#define ___VDir_H___ + +const int driveCount = 30; + +class VDir +{ +public: + VDir(); + ~VDir() {}; + + void Init(VDir* pDir, VMem *pMem); + void SetDefaultA(char const *pDefault); + void SetDefaultW(WCHAR const *pDefault); + char* MapPathA(const char *pInName); + WCHAR* MapPathW(const WCHAR *pInName); + int SetCurrentDirectoryA(char *lpBuffer); + int SetCurrentDirectoryW(WCHAR *lpBuffer); + inline const char *GetDirA(int index) + { + return dirTableA[index]; + }; + inline const WCHAR *GetDirW(int index) + { + return dirTableW[index]; + }; + inline int GetDefault(void) { return nDefault; }; + + inline char* GetCurrentDirectoryA(int dwBufSize, char *lpBuffer) + { + char* ptr = dirTableA[nDefault]; + while (dwBufSize--) + { + if ((*lpBuffer++ = *ptr++) == '\0') + break; + } + return lpBuffer; + }; + inline WCHAR* GetCurrentDirectoryW(int dwBufSize, WCHAR *lpBuffer) + { + WCHAR* ptr = dirTableW[nDefault]; + while (dwBufSize--) + { + if ((*lpBuffer++ = *ptr++) == '\0') + break; + } + return lpBuffer; + }; + + + DWORD CalculateEnvironmentSpace(void); + LPSTR BuildEnvironmentSpace(LPSTR lpStr); + +protected: + int SetDirA(char const *pPath, int index); + void FromEnvA(char *pEnv, int index); + inline const char *GetDefaultDirA(void) + { + return dirTableA[nDefault]; + }; + + inline void SetDefaultDirA(char const *pPath, int index) + { + SetDirA(pPath, index); + nDefault = index; + }; + int SetDirW(WCHAR const *pPath, int index); + inline const WCHAR *GetDefaultDirW(void) + { + return dirTableW[nDefault]; + }; + + inline void SetDefaultDirW(WCHAR const *pPath, int index) + { + SetDirW(pPath, index); + nDefault = index; + }; + + inline int DriveIndex(char chr) + { + return (chr | 0x20)-'a'; + }; + + VMem *pMem; + int nDefault; + char *dirTableA[driveCount]; + char szLocalBufferA[MAX_PATH+1]; + WCHAR *dirTableW[driveCount]; + WCHAR szLocalBufferW[MAX_PATH+1]; +}; + + +VDir::VDir() +{ + nDefault = 0; + memset(dirTableA, 0, sizeof(dirTableA)); + memset(dirTableW, 0, sizeof(dirTableW)); +} + +void VDir::Init(VDir* pDir, VMem *p) +{ + int index; + DWORD driveBits; + char szBuffer[MAX_PATH*driveCount]; + + pMem = p; + if (pDir) { + for (index = 0; index < driveCount; ++index) { + SetDirW(pDir->GetDirW(index), index); + } + nDefault = pDir->GetDefault(); + } + else { + driveBits = GetLogicalDrives(); + if (GetLogicalDriveStrings(sizeof(szBuffer), szBuffer)) { + char* pEnv = GetEnvironmentStrings(); + char* ptr = szBuffer; + for (index = 0; index < driveCount; ++index) { + if (driveBits & (1<Free(dirTableA[index]); + ptr = dirTableA[index] = (char*)pMem->Malloc(length+2); + if (ptr != NULL) { + strcpy(ptr, pPath); + ptr += length-1; + chr = *ptr++; + if (chr != '\\' && chr != '/') { + *ptr++ = '\\'; + *ptr = '\0'; + } + MultiByteToWideChar(CP_ACP, 0, dirTableA[index], -1, + wBuffer, (sizeof(wBuffer)/sizeof(WCHAR))); + length = wcslen(wBuffer); + pMem->Free(dirTableW[index]); + dirTableW[index] = (WCHAR*)pMem->Malloc((length+1)*2); + if (dirTableW[index] != NULL) { + wcscpy(dirTableW[index], wBuffer); + } + } + } + return length; +} + +void VDir::FromEnvA(char *pEnv, int index) +{ /* gets the directory for index from the environment variable. */ + while (*pEnv != '\0') { + if ((pEnv[0] == '=') && (DriveIndex(pEnv[1]) == index)) { + SetDirA(&pEnv[4], index); + break; + } + else + pEnv += strlen(pEnv)+1; + } +} + +void VDir::SetDefaultA(char const *pDefault) +{ + char szBuffer[MAX_PATH+1]; + char *pPtr; + + if (GetFullPathNameA(pDefault, sizeof(szBuffer), szBuffer, &pPtr)) { + if (*pDefault != '.' && pPtr != NULL) + *pPtr = '\0'; + + SetDefaultDirA(szBuffer, DriveIndex(szBuffer[0])); + } +} + +int VDir::SetDirW(WCHAR const *pPath, int index) +{ + WCHAR chr, *ptr; + char szBuffer[MAX_PATH+1]; + int length = 0; + if (index < driveCount && pPath != NULL) { + length = wcslen(pPath); + pMem->Free(dirTableW[index]); + ptr = dirTableW[index] = (WCHAR*)pMem->Malloc((length+2)*2); + if (ptr != NULL) { + wcscpy(ptr, pPath); + ptr += length-1; + chr = *ptr++; + if (chr != '\\' && chr != '/') { + *ptr++ = '\\'; + *ptr = '\0'; + } + WideCharToMultiByte(CP_ACP, 0, dirTableW[index], -1, szBuffer, sizeof(szBuffer), NULL, NULL); + length = strlen(szBuffer); + pMem->Free(dirTableA[index]); + dirTableA[index] = (char*)pMem->Malloc(length+1); + if (dirTableA[index] != NULL) { + strcpy(dirTableA[index], szBuffer); + } + } + } + return length; +} + +void VDir::SetDefaultW(WCHAR const *pDefault) +{ + WCHAR szBuffer[MAX_PATH+1]; + WCHAR *pPtr; + + if (GetFullPathNameW(pDefault, (sizeof(szBuffer)/sizeof(WCHAR)), szBuffer, &pPtr)) { + if (*pDefault != '.' && pPtr != NULL) + *pPtr = '\0'; + + SetDefaultDirW(szBuffer, DriveIndex((char)szBuffer[0])); + } +} + +inline BOOL IsPathSep(char ch) +{ + return (ch == '\\' || ch == '/'); +} + +inline void DoGetFullPathNameA(char* lpBuffer, DWORD dwSize, char* Dest) +{ + char *pPtr; + + /* + * On WinNT GetFullPathName does not fail, (or at least always + * succeeds when the drive is valid) WinNT does set *Dest to Nullch + * On Win98 GetFullPathName will set last error if it fails, but + * does not touch *Dest + */ + *Dest = '\0'; + GetFullPathNameA(lpBuffer, dwSize, Dest, &pPtr); +} + +char *VDir::MapPathA(const char *pInName) +{ /* + * possiblities -- relative path or absolute path with or without drive letter + * OR UNC name + */ + char szBuffer[(MAX_PATH+1)*2]; + char szlBuf[MAX_PATH+1]; + + if (strlen(pInName) > MAX_PATH) { + strncpy(szlBuf, pInName, MAX_PATH); + if (IsPathSep(pInName[0]) && !IsPathSep(pInName[1])) { + /* absolute path - reduce length by 2 for drive specifier */ + szlBuf[MAX_PATH-2] = '\0'; + } + else + szlBuf[MAX_PATH] = '\0'; + pInName = szlBuf; + } + /* strlen(pInName) is now <= MAX_PATH */ + + if (pInName[1] == ':') { + /* has drive letter */ + if (IsPathSep(pInName[2])) { + /* absolute with drive letter */ + strcpy(szLocalBufferA, pInName); + } + else { + /* relative path with drive letter */ + strcpy(szBuffer, GetDirA(DriveIndex(*pInName))); + strcat(szBuffer, &pInName[2]); + if(strlen(szBuffer) > MAX_PATH) + szBuffer[MAX_PATH] = '\0'; + + DoGetFullPathNameA(szBuffer, sizeof(szLocalBufferA), szLocalBufferA); + } + } + else { + /* no drive letter */ + if (IsPathSep(pInName[1]) && IsPathSep(pInName[0])) { + /* UNC name */ + strcpy(szLocalBufferA, pInName); + } + else { + strcpy(szBuffer, GetDefaultDirA()); + if (IsPathSep(pInName[0])) { + /* absolute path */ + szLocalBufferA[0] = szBuffer[0]; + szLocalBufferA[1] = szBuffer[1]; + strcpy(&szLocalBufferA[2], pInName); + } + else { + /* relative path */ + strcat(szBuffer, pInName); + if (strlen(szBuffer) > MAX_PATH) + szBuffer[MAX_PATH] = '\0'; + + DoGetFullPathNameA(szBuffer, sizeof(szLocalBufferA), szLocalBufferA); + } + } + } + + return szLocalBufferA; +} + +int VDir::SetCurrentDirectoryA(char *lpBuffer) +{ + HANDLE hHandle; + WIN32_FIND_DATA win32FD; + char szBuffer[MAX_PATH+1], *pPtr; + int nRet = -1; + + GetFullPathNameA(MapPathA(lpBuffer), sizeof(szBuffer), szBuffer, &pPtr); + + hHandle = FindFirstFile(szBuffer, &win32FD); + if (hHandle != INVALID_HANDLE_VALUE) { + FindClose(hHandle); + SetDefaultDirA(szBuffer, DriveIndex(szBuffer[0])); + nRet = 0; + } + return nRet; +} + +int VDir::SetCurrentDirectoryW(WCHAR *lpBuffer) +{ + HANDLE hHandle; + WIN32_FIND_DATAW win32FD; + WCHAR szBuffer[MAX_PATH+1], *pPtr; + int nRet = -1; + + GetFullPathNameW(MapPathW(lpBuffer), (sizeof(szBuffer)/sizeof(WCHAR)), szBuffer, &pPtr); + + hHandle = FindFirstFileW(szBuffer, &win32FD); + if (hHandle != INVALID_HANDLE_VALUE) { + FindClose(hHandle); + SetDefaultDirW(szBuffer, DriveIndex((char)szBuffer[0])); + nRet = 0; + } + return nRet; +} + +DWORD VDir::CalculateEnvironmentSpace(void) +{ /* the current directory environment strings are stored as '=d=d:\path' */ + int index; + DWORD dwSize = 0; + for (index = 0; index < driveCount; ++index) { + if (dirTableA[index] != NULL) { + dwSize += strlen(dirTableA[index]) + 4; /* add 1 for trailing NULL and 3 for '=d=' */ + } + } + return dwSize; +} + +LPSTR VDir::BuildEnvironmentSpace(LPSTR lpStr) +{ /* store the current directory environment strings as '=d=d:\path' */ + int index; + LPSTR lpDirStr; + for (index = 0; index < driveCount; ++index) { + lpDirStr = dirTableA[index]; + if (lpDirStr != NULL) { + lpStr[0] = '='; + lpStr[1] = lpDirStr[0]; + lpStr[2] = '='; + strcpy(&lpStr[3], lpDirStr); + lpStr += strlen(lpDirStr) + 4; /* add 1 for trailing NULL and 3 for '=d=' */ + } + } + return lpStr; +} + +inline BOOL IsPathSep(WCHAR ch) +{ + return (ch == '\\' || ch == '/'); +} + +inline void DoGetFullPathNameW(WCHAR* lpBuffer, DWORD dwSize, WCHAR* Dest) +{ + WCHAR *pPtr; + + /* + * On WinNT GetFullPathName does not fail, (or at least always + * succeeds when the drive is valid) WinNT does set *Dest to Nullch + * On Win98 GetFullPathName will set last error if it fails, but + * does not touch *Dest + */ + *Dest = '\0'; + GetFullPathNameW(lpBuffer, dwSize, Dest, &pPtr); +} + +WCHAR* VDir::MapPathW(const WCHAR *pInName) +{ /* + * possiblities -- relative path or absolute path with or without drive letter + * OR UNC name + */ + WCHAR szBuffer[(MAX_PATH+1)*2]; + WCHAR szlBuf[MAX_PATH+1]; + + if (wcslen(pInName) > MAX_PATH) { + wcsncpy(szlBuf, pInName, MAX_PATH); + if (IsPathSep(pInName[0]) && !IsPathSep(pInName[1])) { + /* absolute path - reduce length by 2 for drive specifier */ + szlBuf[MAX_PATH-2] = '\0'; + } + else + szlBuf[MAX_PATH] = '\0'; + pInName = szlBuf; + } + /* strlen(pInName) is now <= MAX_PATH */ + + if (pInName[1] == ':') { + /* has drive letter */ + if (IsPathSep(pInName[2])) { + /* absolute with drive letter */ + wcscpy(szLocalBufferW, pInName); + } + else { + /* relative path with drive letter */ + wcscpy(szBuffer, GetDirW(DriveIndex((char)*pInName))); + wcscat(szBuffer, &pInName[2]); + if(wcslen(szBuffer) > MAX_PATH) + szBuffer[MAX_PATH] = '\0'; + + DoGetFullPathNameW(szBuffer, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW); + } + } + else { + /* no drive letter */ + if (IsPathSep(pInName[1]) && IsPathSep(pInName[0])) { + /* UNC name */ + wcscpy(szLocalBufferW, pInName); + } + else { + wcscpy(szBuffer, GetDefaultDirW()); + if (IsPathSep(pInName[0])) { + /* absolute path */ + szLocalBufferW[0] = szBuffer[0]; + szLocalBufferW[1] = szBuffer[1]; + wcscpy(&szLocalBufferW[2], pInName); + } + else { + /* relative path */ + wcscat(szBuffer, pInName); + if (wcslen(szBuffer) > MAX_PATH) + szBuffer[MAX_PATH] = '\0'; + + DoGetFullPathNameW(szBuffer, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW); + } + } + } + return szLocalBufferW; +} + + +#endif /* ___VDir_H___ */ diff --git a/win32/vmem.h b/win32/vmem.h new file mode 100644 index 0000000..cf3f502 --- /dev/null +++ b/win32/vmem.h @@ -0,0 +1,703 @@ +/* vmem.h + * + * (c) 1999 Microsoft Corporation. All rights reserved. + * Portions (c) 1999 ActiveState Tool Corp, http://www.ActiveState.com/ + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the README file. + * + * + * Knuth's boundary tag algorithm Vol #1, Page 440. + * + * Each block in the heap has tag words before and after it, + * TAG + * block + * TAG + * The size is stored in these tags as a long word, and includes the 8 bytes + * of overhead that the boundary tags consume. Blocks are allocated on long + * word boundaries, so the size is always multiples of long words. When the + * block is allocated, bit 0, (the tag bit), of the size is set to 1. When + * a block is freed, it is merged with adjacent free blocks, and the tag bit + * is set to 0. + * + * A linked list is used to manage the free list. The first two long words of + * the block contain double links. These links are only valid when the block + * is freed, therefore space needs to be reserved for them. Thus, the minimum + * block size (not counting the tags) is 8 bytes. + * + * Since memory allocation may occur on a single threaded, explict locks are + * provided. + * + */ + +#ifndef ___VMEM_H_INC___ +#define ___VMEM_H_INC___ + +const long lAllocStart = 0x00010000; /* start at 64K */ +const long minBlockSize = sizeof(void*)*2; +const long sizeofTag = sizeof(long); +const long blockOverhead = sizeofTag*2; +const long minAllocSize = minBlockSize+blockOverhead; + +typedef BYTE* PBLOCK; /* pointer to a memory block */ + +/* + * Macros for accessing hidden fields in a memory block: + * + * SIZE size of this block (tag bit 0 is 1 if block is allocated) + * PSIZE size of previous physical block + */ + +#define SIZE(block) (*(ULONG*)(((PBLOCK)(block))-sizeofTag)) +#define PSIZE(block) (*(ULONG*)(((PBLOCK)(block))-(sizeofTag*2))) +inline void SetTags(PBLOCK block, long size) +{ + SIZE(block) = size; + PSIZE(block+(size&~1)) = size; +} + +/* + * Free list pointers + * PREV pointer to previous block + * NEXT pointer to next block + */ + +#define PREV(block) (*(PBLOCK*)(block)) +#define NEXT(block) (*(PBLOCK*)((block)+sizeof(PBLOCK))) +inline void SetLink(PBLOCK block, PBLOCK prev, PBLOCK next) +{ + PREV(block) = prev; + NEXT(block) = next; +} +inline void Unlink(PBLOCK p) +{ + PBLOCK next = NEXT(p); + PBLOCK prev = PREV(p); + NEXT(prev) = next; + PREV(next) = prev; +} +inline void AddToFreeList(PBLOCK block, PBLOCK pInList) +{ + PBLOCK next = NEXT(pInList); + NEXT(pInList) = block; + SetLink(block, pInList, next); + PREV(next) = block; +} + + +/* Macro for rounding up to the next sizeof(long) */ +#define ROUND_UP(n) (((ULONG)(n)+sizeof(long)-1)&~(sizeof(long)-1)) +#define ROUND_UP64K(n) (((ULONG)(n)+0x10000-1)&~(0x10000-1)) +#define ROUND_DOWN(n) ((ULONG)(n)&~(sizeof(long)-1)) + +/* + * HeapRec - a list of all non-contiguous heap areas + * + * Each record in this array contains information about a non-contiguous heap area. + */ + +const int maxHeaps = 64; +const long lAllocMax = 0x80000000; /* max size of allocation */ + +typedef struct _HeapRec +{ + PBLOCK base; /* base of heap area */ + ULONG len; /* size of heap area */ +} HeapRec; + + +class VMem +{ +public: + VMem(); + ~VMem(); + virtual void* Malloc(size_t size); + virtual void* Realloc(void* pMem, size_t size); + virtual void Free(void* pMem); + virtual void GetLock(void); + virtual void FreeLock(void); + virtual int IsLocked(void); + virtual long Release(void); + virtual long AddRef(void); + + inline BOOL CreateOk(void) + { + return m_hHeap != NULL; + }; + + void ReInit(void); + +protected: + void Init(void); + int Getmem(size_t size); + int HeapAdd(void* ptr, size_t size); + void* Expand(void* block, size_t size); + void WalkHeap(void); + + HANDLE m_hHeap; // memory heap for this script + char m_FreeDummy[minAllocSize]; // dummy free block + PBLOCK m_pFreeList; // pointer to first block on free list + PBLOCK m_pRover; // roving pointer into the free list + HeapRec m_heaps[maxHeaps]; // list of all non-contiguous heap areas + int m_nHeaps; // no. of heaps in m_heaps + long m_lAllocSize; // current alloc size + long m_lRefCount; // number of current users + CRITICAL_SECTION m_cs; // access lock +}; + +// #define _DEBUG_MEM +#ifdef _DEBUG_MEM +#define ASSERT(f) if(!(f)) DebugBreak(); + +inline void MEMODS(char *str) +{ + OutputDebugString(str); + OutputDebugString("\n"); +} + +inline void MEMODSlx(char *str, long x) +{ + char szBuffer[512]; + sprintf(szBuffer, "%s %lx\n", str, x); + OutputDebugString(szBuffer); +} + +#define WALKHEAP() WalkHeap() +#define WALKHEAPTRACE() m_pRover = NULL; WalkHeap() + +#else + +#define ASSERT(f) +#define MEMODS(x) +#define MEMODSlx(x, y) +#define WALKHEAP() +#define WALKHEAPTRACE() + +#endif + + +VMem::VMem() +{ + m_lRefCount = 1; + BOOL bRet = (NULL != (m_hHeap = HeapCreate(HEAP_NO_SERIALIZE, + lAllocStart, /* initial size of heap */ + 0))); /* no upper limit on size of heap */ + ASSERT(bRet); + + InitializeCriticalSection(&m_cs); + + Init(); +} + +VMem::~VMem(void) +{ + ASSERT(HeapValidate(m_hHeap, HEAP_NO_SERIALIZE, NULL)); + WALKHEAPTRACE(); + DeleteCriticalSection(&m_cs); + BOOL bRet = HeapDestroy(m_hHeap); + ASSERT(bRet); +} + +void VMem::ReInit(void) +{ + for(int index = 0; index < m_nHeaps; ++index) + HeapFree(m_hHeap, HEAP_NO_SERIALIZE, m_heaps[index].base); + + Init(); +} + +void VMem::Init(void) +{ /* + * Initialize the free list by placing a dummy zero-length block on it. + * Set the number of non-contiguous heaps to zero. + */ + m_pFreeList = m_pRover = (PBLOCK)(&m_FreeDummy[minBlockSize]); + PSIZE(m_pFreeList) = SIZE(m_pFreeList) = 0; + PREV(m_pFreeList) = NEXT(m_pFreeList) = m_pFreeList; + + m_nHeaps = 0; + m_lAllocSize = lAllocStart; +} + +void* VMem::Malloc(size_t size) +{ + WALKHEAP(); + + /* + * Adjust the real size of the block to be a multiple of sizeof(long), and add + * the overhead for the boundary tags. Disallow negative or zero sizes. + */ + size_t realsize = (size < blockOverhead) ? minAllocSize : (size_t)ROUND_UP(size) + minBlockSize; + if((int)realsize < minAllocSize || size == 0) + return NULL; + + /* + * Start searching the free list at the rover. If we arrive back at rover without + * finding anything, allocate some memory from the heap and try again. + */ + PBLOCK ptr = m_pRover; /* start searching at rover */ + int loops = 2; /* allow two times through the loop */ + for(;;) { + size_t lsize = SIZE(ptr); + ASSERT((lsize&1)==0); + /* is block big enough? */ + if(lsize >= realsize) { + /* if the remainder is too small, don't bother splitting the block. */ + size_t rem = lsize - realsize; + if(rem < minAllocSize) { + if(m_pRover == ptr) + m_pRover = NEXT(ptr); + + /* Unlink the block from the free list. */ + Unlink(ptr); + } + else { + /* + * split the block + * The remainder is big enough to split off into a new block. + * Use the end of the block, resize the beginning of the block + * no need to change the free list. + */ + SetTags(ptr, rem); + ptr += SIZE(ptr); + lsize = realsize; + } + /* Set the boundary tags to mark it as allocated. */ + SetTags(ptr, lsize | 1); + return ((void *)ptr); + } + + /* + * This block was unsuitable. If we've gone through this list once already without + * finding anything, allocate some new memory from the heap and try again. + */ + ptr = NEXT(ptr); + if(ptr == m_pRover) { + if(!(loops-- && Getmem(realsize))) { + return NULL; + } + ptr = m_pRover; + } + } +} + +void* VMem::Realloc(void* block, size_t size) +{ + WALKHEAP(); + + /* if size is zero, free the block. */ + if(size == 0) { + Free(block); + return (NULL); + } + + /* if block pointer is NULL, do a Malloc(). */ + if(block == NULL) + return Malloc(size); + + /* + * Grow or shrink the block in place. + * if the block grows then the next block will be used if free + */ + if(Expand(block, size) != NULL) + return block; + + /* + * adjust the real size of the block to be a multiple of sizeof(long), and add the + * overhead for the boundary tags. Disallow negative or zero sizes. + */ + size_t realsize = (size < blockOverhead) ? minAllocSize : (size_t)ROUND_UP(size) + minBlockSize; + if((int)realsize < minAllocSize) + return NULL; + + /* + * see if the previous block is free, and is it big enough to cover the new size + * if merged with the current block. + */ + PBLOCK ptr = (PBLOCK)block; + size_t cursize = SIZE(ptr) & ~1; + size_t psize = PSIZE(ptr); + if((psize&1) == 0 && (psize + cursize) >= realsize) { + PBLOCK prev = ptr - psize; + if(m_pRover == prev) + m_pRover = NEXT(prev); + + /* Unlink the next block from the free list. */ + Unlink(prev); + + /* Copy contents of old block to new location, make it the current block. */ + memmove(prev, ptr, cursize); + cursize += psize; /* combine sizes */ + ptr = prev; + + size_t rem = cursize - realsize; + if(rem >= minAllocSize) { + /* + * The remainder is big enough to be a new block. Set boundary + * tags for the resized block and the new block. + */ + prev = ptr + realsize; + /* + * add the new block to the free list. + * next block cannot be free + */ + SetTags(prev, rem); + AddToFreeList(prev, m_pFreeList); + cursize = realsize; + } + /* Set the boundary tags to mark it as allocated. */ + SetTags(ptr, cursize | 1); + return ((void *)ptr); + } + + /* Allocate a new block, copy the old to the new, and free the old. */ + if((ptr = (PBLOCK)Malloc(size)) != NULL) { + memmove(ptr, block, cursize-minBlockSize); + Free(block); + } + return ((void *)ptr); +} + +void VMem::Free(void* p) +{ + WALKHEAP(); + + /* Ignore null pointer. */ + if(p == NULL) + return; + + PBLOCK ptr = (PBLOCK)p; + + /* Check for attempt to free a block that's already free. */ + size_t size = SIZE(ptr); + if((size&1) == 0) { + MEMODSlx("Attempt to free previously freed block", (long)p); + return; + } + size &= ~1; /* remove allocated tag */ + + /* if previous block is free, add this block to it. */ + int linked = FALSE; + size_t psize = PSIZE(ptr); + if((psize&1) == 0) { + ptr -= psize; /* point to previous block */ + size += psize; /* merge the sizes of the two blocks */ + linked = TRUE; /* it's already on the free list */ + } + + /* if the next physical block is free, merge it with this block. */ + PBLOCK next = ptr + size; /* point to next physical block */ + size_t nsize = SIZE(next); + if((nsize&1) == 0) { + /* block is free move rover if needed */ + if(m_pRover == next) + m_pRover = NEXT(next); + + /* unlink the next block from the free list. */ + Unlink(next); + + /* merge the sizes of this block and the next block. */ + size += nsize; + } + + /* Set the boundary tags for the block; */ + SetTags(ptr, size); + + /* Link the block to the head of the free list. */ + if(!linked) { + AddToFreeList(ptr, m_pFreeList); + } +} + +void VMem::GetLock(void) +{ + EnterCriticalSection(&m_cs); +} + +void VMem::FreeLock(void) +{ + LeaveCriticalSection(&m_cs); +} + +int VMem::IsLocked(void) +{ + BOOL bAccessed = TryEnterCriticalSection(&m_cs); + if(bAccessed) { + LeaveCriticalSection(&m_cs); + } + return !bAccessed; +} + + +long VMem::Release(void) +{ + long lCount = InterlockedDecrement(&m_lRefCount); + if(!lCount) + delete this; + return lCount; +} + +long VMem::AddRef(void) +{ + long lCount = InterlockedIncrement(&m_lRefCount); + return lCount; +} + + +int VMem::Getmem(size_t requestSize) +{ /* returns -1 is successful 0 if not */ + void *ptr; + + /* Round up size to next multiple of 64K. */ + size_t size = (size_t)ROUND_UP64K(requestSize); + + /* + * if the size requested is smaller than our current allocation size + * adjust up + */ + if(size < (unsigned long)m_lAllocSize) + size = m_lAllocSize; + + /* Update the size to allocate on the next request */ + if(m_lAllocSize != lAllocMax) + m_lAllocSize <<= 1; + + if(m_nHeaps != 0) { + /* Expand the last allocated heap */ + ptr = HeapReAlloc(m_hHeap, HEAP_REALLOC_IN_PLACE_ONLY|HEAP_ZERO_MEMORY|HEAP_NO_SERIALIZE, + m_heaps[m_nHeaps-1].base, + m_heaps[m_nHeaps-1].len + size); + if(ptr != 0) { + HeapAdd(((char*)ptr) + m_heaps[m_nHeaps-1].len, size); + return -1; + } + } + + /* + * if we didn't expand a block to cover the requested size + * allocate a new Heap + * the size of this block must include the additional dummy tags at either end + * the above ROUND_UP64K may not have added any memory to include this. + */ + if(size == requestSize) + size = (size_t)ROUND_UP64K(requestSize+(sizeofTag*2)); + + ptr = HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY|HEAP_NO_SERIALIZE, size); + if(ptr == 0) { + MEMODSlx("HeapAlloc failed on size!!!", size); + return 0; + } + + HeapAdd(ptr, size); + return -1; +} + +int VMem::HeapAdd(void *p, size_t size) +{ /* if the block can be succesfully added to the heap, returns 0; otherwise -1. */ + int index; + + /* Check size, then round size down to next long word boundary. */ + if(size < minAllocSize) + return -1; + + size = (size_t)ROUND_DOWN(size); + PBLOCK ptr = (PBLOCK)p; + + /* + * Search for another heap area that's contiguous with the bottom of this new area. + * (It should be extremely unusual to find one that's contiguous with the top). + */ + for(index = 0; index < m_nHeaps; ++index) { + if(ptr == m_heaps[index].base + (int)m_heaps[index].len) { + /* + * The new block is contiguous with a previously allocated heap area. Add its + * length to that of the previous heap. Merge it with the the dummy end-of-heap + * area marker of the previous heap. + */ + m_heaps[index].len += size; + break; + } + } + + if(index == m_nHeaps) { + /* The new block is not contiguous. Add it to the heap list. */ + if(m_nHeaps == maxHeaps) { + return -1; /* too many non-contiguous heaps */ + } + m_heaps[m_nHeaps].base = ptr; + m_heaps[m_nHeaps].len = size; + m_nHeaps++; + + /* + * Reserve the first LONG in the block for the ending boundary tag of a dummy + * block at the start of the heap area. + */ + size -= minBlockSize; + ptr += minBlockSize; + PSIZE(ptr) = 1; /* mark the dummy previous block as allocated */ + } + + /* + * Convert the heap to one large block. Set up its boundary tags, and those of + * marker block after it. The marker block before the heap will already have + * been set up if this heap is not contiguous with the end of another heap. + */ + SetTags(ptr, size | 1); + PBLOCK next = ptr + size; /* point to dummy end block */ + SIZE(next) = 1; /* mark the dummy end block as allocated */ + + /* + * Link the block to the start of the free list by calling free(). + * This will merge the block with any adjacent free blocks. + */ + Free(ptr); + return 0; +} + + +void* VMem::Expand(void* block, size_t size) +{ + /* + * Adjust the size of the block to be a multiple of sizeof(long), and add the + * overhead for the boundary tags. Disallow negative or zero sizes. + */ + size_t realsize = (size < blockOverhead) ? minAllocSize : (size_t)ROUND_UP(size) + minBlockSize; + if((int)realsize < minAllocSize || size == 0) + return NULL; + + PBLOCK ptr = (PBLOCK)block; + + /* if the current size is the same as requested, do nothing. */ + size_t cursize = SIZE(ptr) & ~1; + if(cursize == realsize) { + return block; + } + + /* if the block is being shrunk, convert the remainder of the block into a new free block. */ + if(realsize <= cursize) { + size_t nextsize = cursize - realsize; /* size of new remainder block */ + if(nextsize >= minAllocSize) { + /* + * Split the block + * Set boundary tags for the resized block and the new block. + */ + SetTags(ptr, realsize | 1); + ptr += realsize; + + /* + * add the new block to the free list. + * call Free to merge this block with next block if free + */ + SetTags(ptr, nextsize | 1); + Free(ptr); + } + + return block; + } + + PBLOCK next = ptr + cursize; + size_t nextsize = SIZE(next); + + /* Check the next block for consistency.*/ + if((nextsize&1) == 0 && (nextsize + cursize) >= realsize) { + /* + * The next block is free and big enough. Add the part that's needed + * to our block, and split the remainder off into a new block. + */ + if(m_pRover == next) + m_pRover = NEXT(next); + + /* Unlink the next block from the free list. */ + Unlink(next); + cursize += nextsize; /* combine sizes */ + + size_t rem = cursize - realsize; /* size of remainder */ + if(rem >= minAllocSize) { + /* + * The remainder is big enough to be a new block. + * Set boundary tags for the resized block and the new block. + */ + next = ptr + realsize; + /* + * add the new block to the free list. + * next block cannot be free + */ + SetTags(next, rem); + AddToFreeList(next, m_pFreeList); + cursize = realsize; + } + /* Set the boundary tags to mark it as allocated. */ + SetTags(ptr, cursize | 1); + return ((void *)ptr); + } + return NULL; +} + +#ifdef _DEBUG_MEM +#define LOG_FILENAME "P:\\Apps\\Perl\\Result.txt" + +void MemoryUsageMessage(char *str, long x, long y, int c) +{ + static FILE* fp = NULL; + char szBuffer[512]; + if(str) { + if(!fp) + fp = fopen(LOG_FILENAME, "w"); + sprintf(szBuffer, str, x, y, c); + fputs(szBuffer, fp); + } + else { + fflush(fp); + fclose(fp); + } +} + +void VMem::WalkHeap(void) +{ + if(!m_pRover) { + MemoryUsageMessage("VMem heaps used %d\n", m_nHeaps, 0, 0); + } + + /* Walk all the heaps - verify structures */ + for(int index = 0; index < m_nHeaps; ++index) { + PBLOCK ptr = m_heaps[index].base; + size_t size = m_heaps[index].len; + ASSERT(HeapValidate(m_hHeap, HEAP_NO_SERIALIZE, p)); + + /* set over reserved header block */ + size -= minBlockSize; + ptr += minBlockSize; + PBLOCK pLast = ptr + size; + ASSERT(PSIZE(ptr) == 1); /* dummy previous block is allocated */ + ASSERT(SIZE(pLast) == 1); /* dummy next block is allocated */ + while(ptr < pLast) { + ASSERT(ptr > m_heaps[index].base); + size_t cursize = SIZE(ptr) & ~1; + ASSERT((PSIZE(ptr+cursize) & ~1) == cursize); + if(!m_pRover) { + MemoryUsageMessage("Memory Block %08x: Size %08x %c\n", (long)ptr, cursize, (SIZE(p)&1) ? 'x' : ' '); + } + if(!(SIZE(ptr)&1)) { + /* this block is on the free list */ + PBLOCK tmp = NEXT(ptr); + while(tmp != ptr) { + ASSERT((SIZE(tmp)&1)==0); + if(tmp == m_pFreeList) + break; + ASSERT(NEXT(tmp)); + tmp = NEXT(tmp); + } + if(tmp == ptr) { + MemoryUsageMessage("Memory Block %08x: Size %08x free but not in free list\n", (long)ptr, cursize, 0); + } + } + ptr += cursize; + } + } + if(!m_pRover) { + MemoryUsageMessage(NULL, 0, 0, 0); + } +} +#endif + +#endif /* ___VMEM_H_INC___ */ diff --git a/win32/win32.c b/win32/win32.c index 6566f9a..4c13d4a 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -95,11 +95,20 @@ static char * get_emd_part(SV **leading, char *trailing, ...); static void remove_dead_process(long deceased); static long find_pid(int pid); static char * qualified_path(const char *cmd); +#ifdef USE_ITHREADS +static void remove_dead_pseudo_process(long child); +static long find_pseudo_pid(int pid); +#endif +START_EXTERN_C HANDLE w32_perldll_handle = INVALID_HANDLE_VALUE; char w32_module_name[MAX_PATH+1]; +END_EXTERN_C + static DWORD w32_platform = (DWORD)-1; +#define ONE_K_BUFSIZE 1024 + int IsWin95(void) { @@ -349,17 +358,17 @@ PerlIO * Perl_my_popen(pTHX_ char *cmd, char *mode) { #ifdef FIXCMD -#define fixcmd(x) { \ - char *pspace = strchr((x),' '); \ - if (pspace) { \ - char *p = (x); \ - while (p < pspace) { \ - if (*p == '/') \ - *p = '\\'; \ - p++; \ - } \ - } \ - } +#define fixcmd(x) { \ + char *pspace = strchr((x),' '); \ + if (pspace) { \ + char *p = (x); \ + while (p < pspace) { \ + if (*p == '/') \ + *p = '\\'; \ + p++; \ + } \ + } \ + } #else #define fixcmd(x) #endif @@ -389,6 +398,17 @@ win32_os_id(void) return (unsigned long)w32_platform; } +DllExport int +win32_getpid(void) +{ +#ifdef USE_ITHREADS + dTHXo; + if (w32_pseudo_id) + return -((int)w32_pseudo_id); +#endif + return _getpid(); +} + /* Tokenize a string. Words are null-separated, and the list * ends with a doubled null. Any character (except null and * including backslash) may be escaped by preceding it with a @@ -685,10 +705,10 @@ win32_opendir(char *filename) /* do the FindFirstFile call */ if (USING_WIDE()) { A2WHELPER(scanname, wbuffer, sizeof(wbuffer)); - fh = FindFirstFileW(wbuffer, &wFindData); + fh = FindFirstFileW(PerlDir_mapW(wbuffer), &wFindData); } else { - fh = FindFirstFileA(scanname, &aFindData); + fh = FindFirstFileA(PerlDir_mapA(scanname), &aFindData); } dirp->handle = fh; if (fh == INVALID_HANDLE_VALUE) { @@ -911,8 +931,8 @@ static long find_pid(int pid) { dTHXo; - long child; - for (child = 0 ; child < w32_num_children ; ++child) { + long child = w32_num_children; + while (--child >= 0) { if (w32_child_pids[child] == pid) return child; } @@ -933,18 +953,72 @@ remove_dead_process(long child) } } +#ifdef USE_ITHREADS +static long +find_pseudo_pid(int pid) +{ + dTHXo; + long child = w32_num_pseudo_children; + while (--child >= 0) { + if (w32_pseudo_child_pids[child] == pid) + return child; + } + return -1; +} + +static void +remove_dead_pseudo_process(long child) +{ + if (child >= 0) { + dTHXo; + CloseHandle(w32_pseudo_child_handles[child]); + Copy(&w32_pseudo_child_handles[child+1], &w32_pseudo_child_handles[child], + (w32_num_pseudo_children-child-1), HANDLE); + Copy(&w32_pseudo_child_pids[child+1], &w32_pseudo_child_pids[child], + (w32_num_pseudo_children-child-1), DWORD); + w32_num_pseudo_children--; + } +} +#endif + DllExport int win32_kill(int pid, int sig) { + dTHXo; HANDLE hProcess; - hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid); - if (hProcess && TerminateProcess(hProcess, sig)) - CloseHandle(hProcess); - else { - errno = EINVAL; - return -1; +#ifdef USE_ITHREADS + if (pid < 0) { + /* it is a pseudo-forked child */ + long child = find_pseudo_pid(-pid); + if (child >= 0) { + hProcess = w32_pseudo_child_handles[child]; + if (TerminateThread(hProcess, sig)) { + remove_dead_pseudo_process(child); + return 0; + } + } } - return 0; + else +#endif + { + long child = find_pid(pid); + if (child >= 0) { + hProcess = w32_child_handles[child]; + if (TerminateProcess(hProcess, sig)) { + remove_dead_process(child); + return 0; + } + } + else { + hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid); + if (hProcess && TerminateProcess(hProcess, sig)) { + CloseHandle(hProcess); + return 0; + } + } + } + errno = EINVAL; + return -1; } /* @@ -995,9 +1069,11 @@ win32_stat(const char *path, struct stat *buffer) /* This also gives us an opportunity to determine the number of links. */ if (USING_WIDE()) { A2WHELPER(path, wbuffer, sizeof(wbuffer)); + wcscpy(wbuffer, PerlDir_mapW(wbuffer)); handle = CreateFileW(wbuffer, 0, 0, NULL, OPEN_EXISTING, 0, NULL); } else { + path = PerlDir_mapA(path); handle = CreateFileA(path, 0, 0, NULL, OPEN_EXISTING, 0, NULL); } if (handle != INVALID_HANDLE_VALUE) { @@ -1007,10 +1083,13 @@ win32_stat(const char *path, struct stat *buffer) CloseHandle(handle); } - if (USING_WIDE()) + /* wbuffer or path will be mapped correctly above */ + if (USING_WIDE()) { res = _wstat(wbuffer, (struct _stat *)buffer); - else + } + else { res = stat(path, buffer); + } buffer->st_nlink = nlink; if (res < 0) { @@ -1213,9 +1292,9 @@ win32_putenv(const char *name) New(1309,wCuritem,length,WCHAR); A2WHELPER(name, wCuritem, length*sizeof(WCHAR)); wVal = wcschr(wCuritem, '='); - if(wVal) { + if (wVal) { *wVal++ = '\0'; - if(SetEnvironmentVariableW(wCuritem, *wVal ? wVal : NULL)) + if (SetEnvironmentVariableW(wCuritem, *wVal ? wVal : NULL)) relval = 0; } Safefree(wCuritem); @@ -1224,7 +1303,7 @@ win32_putenv(const char *name) New(1309,curitem,strlen(name)+1,char); strcpy(curitem, name); val = strchr(curitem, '='); - if(val) { + if (val) { /* The sane way to deal with the environment. * Has these advantages over putenv() & co.: * * enables us to store a truly empty value in the @@ -1240,7 +1319,7 @@ win32_putenv(const char *name) * GSAR 97-06-07 */ *val++ = '\0'; - if(SetEnvironmentVariableA(curitem, *val ? val : NULL)) + if (SetEnvironmentVariableA(curitem, *val ? val : NULL)) relval = 0; } Safefree(curitem); @@ -1254,11 +1333,11 @@ win32_putenv(const char *name) static long filetime_to_clock(PFILETIME ft) { - __int64 qw = ft->dwHighDateTime; - qw <<= 32; - qw |= ft->dwLowDateTime; - qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */ - return (long) qw; + __int64 qw = ft->dwHighDateTime; + qw <<= 32; + qw |= ft->dwLowDateTime; + qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */ + return (long) qw; } DllExport int @@ -1309,6 +1388,43 @@ filetime_from_time(PFILETIME pFileTime, time_t Time) } DllExport int +win32_unlink(const char *filename) +{ + dTHXo; + int ret; + DWORD attrs; + + if (USING_WIDE()) { + WCHAR wBuffer[MAX_PATH]; + + A2WHELPER(filename, wBuffer, sizeof(wBuffer)); + wcscpy(wBuffer, PerlDir_mapW(wBuffer)); + attrs = GetFileAttributesW(wBuffer); + if (attrs & FILE_ATTRIBUTE_READONLY) { + (void)SetFileAttributesW(wBuffer, attrs & ~FILE_ATTRIBUTE_READONLY); + ret = _wunlink(wBuffer); + if (ret == -1) + (void)SetFileAttributesW(wBuffer, attrs); + } + else + ret = _wunlink(wBuffer); + } + else { + filename = PerlDir_mapA(filename); + attrs = GetFileAttributesA(filename); + if (attrs & FILE_ATTRIBUTE_READONLY) { + (void)SetFileAttributesA(filename, attrs & ~FILE_ATTRIBUTE_READONLY); + ret = unlink(filename); + if (ret == -1) + (void)SetFileAttributesA(filename, attrs); + } + else + ret = unlink(filename); + } + return ret; +} + +DllExport int win32_utime(const char *filename, struct utimbuf *times) { dTHXo; @@ -1322,9 +1438,11 @@ win32_utime(const char *filename, struct utimbuf *times) int rc; if (USING_WIDE()) { A2WHELPER(filename, wbuffer, sizeof(wbuffer)); + wcscpy(wbuffer, PerlDir_mapW(wbuffer)); rc = _wutime(wbuffer, (struct _utimbuf*)times); } else { + filename = PerlDir_mapA(filename); rc = utime(filename, times); } /* EACCES: path specifies directory or readonly file */ @@ -1458,8 +1576,27 @@ win32_waitpid(int pid, int *status, int flags) { dTHXo; int retval = -1; - if (pid == -1) + if (pid == -1) /* XXX threadid == 1 ? */ return win32_wait(status); +#ifdef USE_ITHREADS + else if (pid < 0) { + long child = find_pseudo_pid(-pid); + if (child >= 0) { + HANDLE hThread = w32_pseudo_child_handles[child]; + DWORD waitcode = WaitForSingleObject(hThread, INFINITE); + if (waitcode != WAIT_FAILED) { + if (GetExitCodeThread(hThread, &waitcode)) { + *status = (int)((waitcode & 0xff) << 8); + retval = (int)w32_pseudo_child_pids[child]; + remove_dead_pseudo_process(child); + return retval; + } + } + else + errno = ECHILD; + } + } +#endif else { long child = find_pid(pid); if (child >= 0) { @@ -1498,6 +1635,28 @@ win32_wait(int *status) int i, retval; DWORD exitcode, waitcode; +#ifdef USE_ITHREADS + if (w32_num_pseudo_children) { + waitcode = WaitForMultipleObjects(w32_num_pseudo_children, + w32_pseudo_child_handles, + FALSE, + INFINITE); + if (waitcode != WAIT_FAILED) { + if (waitcode >= WAIT_ABANDONED_0 + && waitcode < WAIT_ABANDONED_0 + w32_num_pseudo_children) + i = waitcode - WAIT_ABANDONED_0; + else + i = waitcode - WAIT_OBJECT_0; + if (GetExitCodeThread(w32_pseudo_child_handles[i], &exitcode)) { + *status = (int)((exitcode & 0xff) << 8); + retval = (int)w32_pseudo_child_pids[i]; + remove_dead_pseudo_process(i); + return retval; + } + } + } +#endif + if (!w32_num_children) { errno = ECHILD; return -1; @@ -1903,9 +2062,9 @@ win32_fopen(const char *filename, const char *mode) if (USING_WIDE()) { A2WHELPER(mode, wMode, sizeof(wMode)); A2WHELPER(filename, wBuffer, sizeof(wBuffer)); - return _wfopen(wBuffer, wMode); + return _wfopen(PerlDir_mapW(wBuffer), wMode); } - return fopen(filename, mode); + return fopen(PerlDir_mapA(filename), mode); } #ifndef USE_SOCKETS_AS_HANDLES @@ -1936,9 +2095,9 @@ win32_freopen(const char *path, const char *mode, FILE *stream) if (USING_WIDE()) { A2WHELPER(mode, wMode, sizeof(wMode)); A2WHELPER(path, wBuffer, sizeof(wBuffer)); - return _wfreopen(wBuffer, wMode, stream); + return _wfreopen(PerlDir_mapW(wBuffer), wMode, stream); } - return freopen(path, mode, stream); + return freopen(PerlDir_mapA(path), mode, stream); } DllExport int @@ -2244,7 +2403,8 @@ win32_link(const char *oldname, const char *newname) if ((A2WHELPER(oldname, wOldName, sizeof(wOldName))) && (A2WHELPER(newname, wNewName, sizeof(wNewName))) && - pfnCreateHardLinkW(wNewName, wOldName, NULL)) + (wcscpy(wOldName, PerlDir_mapW(wOldName)), + pfnCreateHardLinkW(PerlDir_mapW(wNewName), wOldName, NULL))) { return 0; } @@ -2257,6 +2417,7 @@ win32_rename(const char *oname, const char *newname) { WCHAR wOldName[MAX_PATH]; WCHAR wNewName[MAX_PATH]; + char szOldName[MAX_PATH]; BOOL bResult; /* XXX despite what the documentation says about MoveFileEx(), * it doesn't work under Windows95! @@ -2266,11 +2427,13 @@ win32_rename(const char *oname, const char *newname) if (USING_WIDE()) { A2WHELPER(oname, wOldName, sizeof(wOldName)); A2WHELPER(newname, wNewName, sizeof(wNewName)); - bResult = MoveFileExW(wOldName,wNewName, + wcscpy(wOldName, PerlDir_mapW(wOldName)); + bResult = MoveFileExW(wOldName,PerlDir_mapW(wNewName), MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING); } else { - bResult = MoveFileExA(oname,newname, + strcpy(szOldName, PerlDir_mapA(szOldName)); + bResult = MoveFileExA(szOldName,PerlDir_mapA(newname), MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING); } if (!bResult) { @@ -2401,9 +2564,9 @@ win32_open(const char *path, int flag, ...) if (USING_WIDE()) { A2WHELPER(path, wBuffer, sizeof(wBuffer)); - return _wopen(wBuffer, flag, pmode); + return _wopen(PerlDir_mapW(wBuffer), flag, pmode); } - return open(path,flag,pmode); + return open(PerlDir_mapA(path), flag, pmode); } DllExport int @@ -2445,21 +2608,64 @@ win32_write(int fd, const void *buf, unsigned int cnt) DllExport int win32_mkdir(const char *dir, int mode) { - return mkdir(dir); /* just ignore mode */ + dTHXo; + if (USING_WIDE()) { + WCHAR wBuffer[MAX_PATH]; + A2WHELPER(dir, wBuffer, sizeof(wBuffer)); + return _wmkdir(PerlDir_mapW(wBuffer)); + } + return mkdir(PerlDir_mapA(dir)); /* just ignore mode */ } DllExport int win32_rmdir(const char *dir) { - return rmdir(dir); + dTHXo; + if (USING_WIDE()) { + WCHAR wBuffer[MAX_PATH]; + A2WHELPER(dir, wBuffer, sizeof(wBuffer)); + return _wrmdir(PerlDir_mapW(wBuffer)); + } + return rmdir(PerlDir_mapA(dir)); } DllExport int win32_chdir(const char *dir) { + dTHXo; + if (USING_WIDE()) { + WCHAR wBuffer[MAX_PATH]; + A2WHELPER(dir, wBuffer, sizeof(wBuffer)); + return _wchdir(wBuffer); + } return chdir(dir); } +DllExport int +win32_access(const char *path, int mode) +{ + dTHXo; + if (USING_WIDE()) { + WCHAR wBuffer[MAX_PATH]; + A2WHELPER(path, wBuffer, sizeof(wBuffer)); + return _waccess(PerlDir_mapW(wBuffer), mode); + } + return access(PerlDir_mapA(path), mode); +} + +DllExport int +win32_chmod(const char *path, int mode) +{ + dTHXo; + if (USING_WIDE()) { + WCHAR wBuffer[MAX_PATH]; + A2WHELPER(path, wBuffer, sizeof(wBuffer)); + return _wchmod(PerlDir_mapW(wBuffer), mode); + } + return chmod(PerlDir_mapA(path), mode); +} + + static char * create_command_line(const char* command, const char * const *args) { @@ -2592,12 +2798,28 @@ free_childenv(void* d) char* get_childdir(void) { - return NULL; + dTHXo; + char* ptr; + char szfilename[(MAX_PATH+1)*2]; + if (USING_WIDE()) { + WCHAR wfilename[MAX_PATH+1]; + GetCurrentDirectoryW(MAX_PATH+1, wfilename); + W2AHELPER(wfilename, szfilename, sizeof(szfilename)); + } + else { + GetCurrentDirectoryA(MAX_PATH+1, szfilename); + } + + New(0, ptr, strlen(szfilename)+1, char); + strcpy(ptr, szfilename); + return ptr; } void free_childdir(char* d) { + dTHXo; + Safefree(d); } @@ -2722,12 +2944,26 @@ RETVAL: DllExport int win32_execv(const char *cmdname, const char *const *argv) { +#ifdef USE_ITHREADS + dTHXo; + /* if this is a pseudo-forked child, we just want to spawn + * the new program, and return */ + if (w32_pseudo_id) + return spawnv(P_WAIT, cmdname, (char *const *)argv); +#endif return execv(cmdname, (char *const *)argv); } DllExport int win32_execvp(const char *cmdname, const char *const *argv) { +#ifdef USE_ITHREADS + dTHXo; + /* if this is a pseudo-forked child, we just want to spawn + * the new program, and return */ + if (w32_pseudo_id) + return win32_spawnvp(P_WAIT, cmdname, (char *const *)argv); +#endif return execvp(cmdname, (char *const *)argv); } @@ -2927,44 +3163,14 @@ win32_dynaload(const char* filename) if (USING_WIDE()) { WCHAR wfilename[MAX_PATH]; A2WHELPER(filename, wfilename, sizeof(wfilename)); - hModule = LoadLibraryExW(wfilename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + hModule = LoadLibraryExW(PerlDir_mapW(wfilename), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); } else { - hModule = LoadLibraryExA(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + hModule = LoadLibraryExA(PerlDir_mapA(filename), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); } return hModule; } -DllExport int -win32_add_host(char *nameId, void *data) -{ - /* - * This must be called before the script is parsed, - * therefore no locking of threads is needed - */ - dTHXo; - struct host_link *link; - New(1314, link, 1, struct host_link); - link->host_data = data; - link->nameId = nameId; - link->next = w32_host_link; - w32_host_link = link; - return 1; -} - -DllExport void * -win32_get_host_data(char *nameId) -{ - dTHXo; - struct host_link *link = w32_host_link; - while(link) { - if(strEQ(link->nameId, nameId)) - return link->host_data; - link = link->next; - } - return Nullch; -} - /* * Extras. */ @@ -2973,19 +3179,19 @@ static XS(w32_GetCwd) { dXSARGS; - SV *sv = sv_newmortal(); - /* Make one call with zero size - return value is required size */ - DWORD len = GetCurrentDirectory((DWORD)0,NULL); - SvUPGRADE(sv,SVt_PV); - SvGROW(sv,len); - SvCUR(sv) = GetCurrentDirectory((DWORD) SvLEN(sv), SvPVX(sv)); + /* Make the host for current directory */ + char* ptr = PerlEnv_get_childdir(); /* - * If result != 0 + * If ptr != Nullch * then it worked, set PV valid, - * else leave it 'undef' + * else return 'undef' */ - EXTEND(SP,1); - if (SvCUR(sv)) { + if (ptr) { + SV *sv = sv_newmortal(); + sv_setpv(sv, ptr); + PerlEnv_free_childdir(ptr); + + EXTEND(SP,1); SvPOK_on(sv); ST(0) = sv; XSRETURN(1); @@ -2999,7 +3205,7 @@ XS(w32_SetCwd) dXSARGS; if (items != 1) Perl_croak(aTHX_ "usage: Win32::SetCurrentDirectory($cwd)"); - if (SetCurrentDirectory(SvPV_nolen(ST(0)))) + if (!PerlDir_chdir(SvPV_nolen(ST(0)))) XSRETURN_YES; XSRETURN_NO; @@ -3122,7 +3328,7 @@ XS(w32_DomainName) if (hNetApi32) FreeLibrary(hNetApi32); if (GetUserName(name,&size)) { - char sid[1024]; + char sid[ONE_K_BUFSIZE]; DWORD sidlen = sizeof(sid); char dname[256]; DWORD dnamelen = sizeof(dname); @@ -3161,19 +3367,34 @@ static XS(w32_GetOSVersion) { dXSARGS; - OSVERSIONINFO osver; + OSVERSIONINFOA osver; - osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (GetVersionEx(&osver)) { + if (USING_WIDE()) { + OSVERSIONINFOW osverw; + char szCSDVersion[sizeof(osverw.szCSDVersion)]; + osverw.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + if (!GetVersionExW(&osverw)) { + XSRETURN_EMPTY; + } + W2AHELPER(osverw.szCSDVersion, szCSDVersion, sizeof(szCSDVersion)); + XPUSHs(newSVpvn(szCSDVersion, strlen(szCSDVersion))); + osver.dwMajorVersion = osverw.dwMajorVersion; + osver.dwMinorVersion = osverw.dwMinorVersion; + osver.dwBuildNumber = osverw.dwBuildNumber; + osver.dwPlatformId = osverw.dwPlatformId; + } + else { + osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); + if (!GetVersionExA(&osver)) { + XSRETURN_EMPTY; + } XPUSHs(newSVpvn(osver.szCSDVersion, strlen(osver.szCSDVersion))); - XPUSHs(newSViv(osver.dwMajorVersion)); - XPUSHs(newSViv(osver.dwMinorVersion)); - XPUSHs(newSViv(osver.dwBuildNumber)); - XPUSHs(newSViv(osver.dwPlatformId)); - PUTBACK; - return; } - XSRETURN_EMPTY; + XPUSHs(newSViv(osver.dwMajorVersion)); + XPUSHs(newSViv(osver.dwMinorVersion)); + XPUSHs(newSViv(osver.dwBuildNumber)); + XPUSHs(newSViv(osver.dwPlatformId)); + PUTBACK; } static @@ -3197,15 +3418,27 @@ XS(w32_FormatMessage) { dXSARGS; DWORD source = 0; - char msgbuf[1024]; + char msgbuf[ONE_K_BUFSIZE]; if (items != 1) Perl_croak(aTHX_ "usage: Win32::FormatMessage($errno)"); - if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, - &source, SvIV(ST(0)), 0, - msgbuf, sizeof(msgbuf)-1, NULL)) - XSRETURN_PV(msgbuf); + if (USING_WIDE()) { + WCHAR wmsgbuf[ONE_K_BUFSIZE]; + if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, + &source, SvIV(ST(0)), 0, + wmsgbuf, ONE_K_BUFSIZE-1, NULL)) + { + W2AHELPER(wmsgbuf, msgbuf, sizeof(msgbuf)); + XSRETURN_PV(msgbuf); + } + } + else { + if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, + &source, SvIV(ST(0)), 0, + msgbuf, sizeof(msgbuf)-1, NULL)) + XSRETURN_PV(msgbuf); + } XSRETURN_UNDEF; } @@ -3358,9 +3591,24 @@ static XS(w32_CopyFile) { dXSARGS; + BOOL bResult; if (items != 3) Perl_croak(aTHX_ "usage: Win32::CopyFile($from, $to, $overwrite)"); - if (CopyFile(SvPV_nolen(ST(0)), SvPV_nolen(ST(1)), !SvTRUE(ST(2)))) + if (USING_WIDE()) { + WCHAR wSourceFile[MAX_PATH]; + WCHAR wDestFile[MAX_PATH]; + A2WHELPER(SvPV_nolen(ST(0)), wSourceFile, sizeof(wSourceFile)); + wcscpy(wSourceFile, PerlDir_mapW(wSourceFile)); + A2WHELPER(SvPV_nolen(ST(1)), wDestFile, sizeof(wDestFile)); + bResult = CopyFileW(wSourceFile, PerlDir_mapW(wDestFile), !SvTRUE(ST(2))); + } + else { + char szSourceFile[MAX_PATH]; + strcpy(szSourceFile, PerlDir_mapA(SvPV_nolen(ST(0)))); + bResult = CopyFileA(szSourceFile, PerlDir_mapA(SvPV_nolen(ST(1))), !SvTRUE(ST(2))); + } + + if (bResult) XSRETURN_YES; XSRETURN_NO; } @@ -3377,6 +3625,12 @@ Perl_init_os_extras(void) w32_fdpid = newAV(); /* XXX needs to be in Perl_win32_init()? */ New(1313, w32_children, 1, child_tab); w32_num_children = 0; + w32_init_socktype = 0; +#ifdef USE_ITHREADS + w32_pseudo_id = 0; + New(1313, w32_pseudo_children, 1, child_tab); + w32_num_pseudo_children = 0; +#endif /* these names are Activeware compatible */ newXS("Win32::GetCwd", w32_GetCwd, file); @@ -3427,21 +3681,6 @@ Perl_win32_init(int *argcp, char ***argvp) MALLOC_INIT; } -#ifdef USE_ITHREADS -void -Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst) -{ - dst->perlshell_tokens = Nullch; - dst->perlshell_vec = (char**)NULL; - dst->perlshell_items = 0; - dst->fdpid = newAV(); - New(1313, dst->children, 1, child_tab); - dst->children->num = 0; - dst->hostlist = src->hostlist; /* XXX */ - dst->thr_intern.Winit_socktype = src->thr_intern.Winit_socktype; -} -#endif - #ifdef USE_BINMODE_SCRIPTS void @@ -3466,3 +3705,27 @@ win32_strip_return(SV *sv) } #endif + +#ifdef USE_ITHREADS + +# ifdef PERL_OBJECT +# undef Perl_sys_intern_dup +# define Perl_sys_intern_dup CPerlObj::Perl_sys_intern_dup +# define pPerl this +# endif + +void +Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst) +{ + dst->perlshell_tokens = Nullch; + dst->perlshell_vec = (char**)NULL; + dst->perlshell_items = 0; + dst->fdpid = newAV(); + Newz(1313, dst->children, 1, child_tab); + Newz(1313, dst->pseudo_children, 1, child_tab); + dst->pseudo_id = 0; + dst->children->num = 0; + dst->thr_intern.Winit_socktype = src->thr_intern.Winit_socktype; +} +#endif + diff --git a/win32/win32.h b/win32/win32.h index 9eaf76a..856232a 100644 --- a/win32/win32.h +++ b/win32/win32.h @@ -378,22 +378,20 @@ struct thread_intern { typedef struct { long num; DWORD pids[MAXIMUM_WAIT_OBJECTS]; + HANDLE handles[MAXIMUM_WAIT_OBJECTS]; } child_tab; -struct host_link { - char * nameId; - void * host_data; - struct host_link * next; -}; - struct interp_intern { char * perlshell_tokens; char ** perlshell_vec; long perlshell_items; struct av * fdpid; child_tab * children; - HANDLE child_handles[MAXIMUM_WAIT_OBJECTS]; - struct host_link * hostlist; +#ifdef USE_ITHREADS + DWORD pseudo_id; + child_tab * pseudo_children; +#endif + void * internal_host; #ifndef USE_THREADS struct thread_intern thr_intern; #endif @@ -407,8 +405,13 @@ struct interp_intern { #define w32_children (PL_sys_intern.children) #define w32_num_children (w32_children->num) #define w32_child_pids (w32_children->pids) -#define w32_child_handles (PL_sys_intern.child_handles) -#define w32_host_link (PL_sys_intern.hostlist) +#define w32_child_handles (w32_children->handles) +#define w32_pseudo_id (PL_sys_intern.pseudo_id) +#define w32_pseudo_children (PL_sys_intern.pseudo_children) +#define w32_num_pseudo_children (w32_pseudo_children->num) +#define w32_pseudo_child_pids (w32_pseudo_children->pids) +#define w32_pseudo_child_handles (w32_pseudo_children->handles) +#define w32_internal_host (PL_sys_intern.internal_host) #ifdef USE_THREADS # define w32_strerror_buffer (thr->i.Wstrerror_buffer) # define w32_getlogin_buffer (thr->i.Wgetlogin_buffer) @@ -435,6 +438,20 @@ struct interp_intern { #define USING_WIDE() (PerlEnv_os_id() == VER_PLATFORM_WIN32_NT) +#ifdef USE_ITHREADS +# define PERL_WAIT_FOR_CHILDREN \ + STMT_START { \ + if (w32_pseudo_children && w32_num_pseudo_children) { \ + long children = w32_num_pseudo_children; \ + WaitForMultipleObjects(children, \ + w32_pseudo_child_handles, \ + TRUE, INFINITE); \ + while (children) \ + CloseHandle(w32_pseudo_child_handles[--children]); \ + } \ + } STMT_END +#endif + /* * This provides a layer of functions and macros to ensure extensions will * get to use the same RTL functions as the core. diff --git a/win32/win32iop.h b/win32/win32iop.h index 566ed57..d7c2ac4 100644 --- a/win32/win32iop.h +++ b/win32/win32iop.h @@ -132,6 +132,7 @@ DllExport int win32_stat(const char *path, struct stat *buf); DllExport char* win32_longpath(char *path); DllExport int win32_ioctl(int i, unsigned int u, char *data); DllExport int win32_link(const char *oldname, const char *newname); +DllExport int win32_unlink(const char *f); DllExport int win32_utime(const char *f, struct utimbuf *t); DllExport int win32_uname(struct utsname *n); DllExport int win32_wait(int *status); @@ -139,6 +140,9 @@ DllExport int win32_waitpid(int pid, int *status, int flags); DllExport int win32_kill(int pid, int sig); DllExport unsigned long win32_os_id(void); DllExport void* win32_dynaload(const char*filename); +DllExport int win32_access(const char *path, int mode); +DllExport int win32_chmod(const char *path, int mode); +DllExport int win32_getpid(void); DllExport char * win32_crypt(const char *txt, const char *salt); @@ -162,6 +166,7 @@ END_EXTERN_C #undef times #undef alarm #undef ioctl +#undef unlink #undef utime #undef uname #undef wait @@ -254,6 +259,9 @@ END_EXTERN_C #define getchar win32_getchar #undef putchar #define putchar win32_putchar +#define access(p,m) win32_access(p,m) +#define chmod(p,m) win32_chmod(p,m) + #if !defined(MYMALLOC) || !defined(PERL_CORE) #undef malloc @@ -273,6 +281,7 @@ END_EXTERN_C #define alarm win32_alarm #define ioctl win32_ioctl #define link win32_link +#define unlink win32_unlink #define utime win32_utime #define uname win32_uname #define wait win32_wait @@ -286,6 +295,7 @@ END_EXTERN_C #define rewinddir win32_rewinddir #define closedir win32_closedir #define os_id win32_os_id +#define getpid win32_getpid #undef crypt #define crypt(t,s) win32_crypt(t,s) diff --git a/win32/win32thread.h b/win32/win32thread.h index 4fa3e2f..d4f8ee4 100644 --- a/win32/win32thread.h +++ b/win32/win32thread.h @@ -1,8 +1,7 @@ #ifndef _WIN32THREAD_H #define _WIN32THREAD_H -#define WIN32_LEAN_AND_MEAN -#include +#include "win32.h" typedef struct win32_cond { LONG waiters; HANDLE sem; } perl_cond; typedef DWORD perl_key; @@ -193,7 +192,7 @@ END_EXTERN_C if ((WaitForSingleObject((t)->self,INFINITE) == WAIT_FAILED) \ || (GetExitCodeThread((t)->self,(LPDWORD)(avp)) == 0) \ || (CloseHandle((t)->self) == 0)) \ - Perl_croak(aTHX_ "panic: JOIN"); \ + Perl_croak(aTHX_ "panic: JOIN"); \ } STMT_END #endif /* !USE_RTL_THREAD_API || _MSC_VER */