@@ -4266,11 +4266,32 @@ S_require_file(pTHX_ SV *sv)
42664266 if (vms_unixname )
42674267#endif
42684268 {
4269- SV * nsv = sv ;
4269+ AV * incdir_av = (AV * )sv_2mortal ((SV * )newAV ());
4270+ SV * nsv = sv ; /* non const copy we can change if necessary */
42704271 namesv = newSV_type (SVt_PV );
42714272 AV * inc_ar = GvAVn (PL_incgv );
4272- for (inc_idx = 0 ; inc_idx <= AvFILL (inc_ar ); inc_idx ++ ) {
4273- SV * dirsv = * av_fetch (inc_ar , inc_idx , TRUE);
4273+ SSize_t incdir_continue_inc_idx = -1 ;
4274+
4275+ for (
4276+ inc_idx = 0 ;
4277+ (AvFILL (incdir_av )>=0 /* we have INCDIR items pending */
4278+ || inc_idx <= AvFILL (inc_ar )); /* @INC entries remain */
4279+ inc_idx ++
4280+ ) {
4281+ SV * dirsv ;
4282+
4283+ /* do we have any pending INCDIR items? */
4284+ if (AvFILL (incdir_av )>=0 ) {
4285+ /* yep, shift it out */
4286+ dirsv = av_shift (incdir_av );
4287+ if (AvFILL (incdir_av )< 0 ) {
4288+ /* incdir is now empty, continue from where
4289+ * we left off after we process this entry */
4290+ inc_idx = incdir_continue_inc_idx ;
4291+ }
4292+ } else {
4293+ dirsv = * av_fetch (inc_ar , inc_idx , TRUE);
4294+ }
42744295
42754296 if (SvGMAGICAL (dirsv )) {
42764297 SvGETMAGIC (dirsv );
@@ -4289,6 +4310,7 @@ S_require_file(pTHX_ SV *sv)
42894310 int count ;
42904311 SV * * svp ;
42914312 SV * loader = dirsv ;
4313+ UV diruv = PTR2UV (SvRV (dirsv ));
42924314
42934315 if (SvTYPE (SvRV (loader )) == SVt_PVAV
42944316 && !SvOBJECT (SvRV (loader )))
@@ -4298,7 +4320,7 @@ S_require_file(pTHX_ SV *sv)
42984320 }
42994321
43004322 Perl_sv_setpvf (aTHX_ namesv , "/loader/0x%" UVxf "/%s" ,
4301- PTR2UV ( SvRV ( dirsv )) , name );
4323+ diruv , name );
43024324 tryname = SvPVX_const (namesv );
43034325 tryrsfp = NULL ;
43044326
@@ -4308,6 +4330,7 @@ S_require_file(pTHX_ SV *sv)
43084330 }
43094331
43104332 const char * method = NULL ;
4333+ bool is_incdir = FALSE;
43114334 SV * inc_idx_sv = save_scalar (PL_incgv );
43124335 sv_setiv (inc_idx_sv ,inc_idx );
43134336 if (sv_isobject (loader )) {
@@ -4318,6 +4341,12 @@ S_require_file(pTHX_ SV *sv)
43184341 GV * gv = gv_fetchmethod_pvn_flags (pkg , "INC" , 3 , 0 );
43194342 if (gv && isGV (gv )) {
43204343 method = "INC" ;
4344+ } else {
4345+ gv = gv_fetchmethod_pvn_flags (pkg , "INCDIR" , 6 , 0 );
4346+ if (gv && isGV (gv )) {
4347+ method = "INCDIR" ;
4348+ is_incdir = TRUE;
4349+ }
43214350 }
43224351 /* But if we have no method, check if this is a
43234352 * coderef, if it is then we treat it as an
@@ -4367,6 +4396,48 @@ S_require_file(pTHX_ SV *sv)
43674396 SV * arg ;
43684397
43694398 SP -= count - 1 ;
4399+
4400+ if (is_incdir ) {
4401+ /* push the stringified returned items into the
4402+ * incdir_av array for processing immediately
4403+ * afterwards. we deliberately stringify or copy
4404+ * "special" arguments, so that overload logic for
4405+ * instance applies, but so that the end result is
4406+ * stable. We speficially do *not* support returning
4407+ * coderefs from an INCDIR call. */
4408+ while (count -- > 0 ) {
4409+ arg = SP [i ++ ];
4410+ SvGETMAGIC (arg );
4411+ if (!SvOK (arg ))
4412+ continue ;
4413+ if (SvROK (arg )) {
4414+ STRLEN l ;
4415+ char * pv = SvPV (arg ,l );
4416+ arg = newSVpvn (pv ,l );
4417+ }
4418+ else if (SvGMAGICAL (arg )) {
4419+ arg = newSVsv_nomg (arg );
4420+ }
4421+ else {
4422+ SvREFCNT_inc (arg );
4423+ }
4424+ av_push (incdir_av , arg );
4425+ }
4426+ /* We copy $INC into incdir_continue_inc_idx
4427+ * so that when we finish processing the items
4428+ * we just inserted into incdir_av we can continue
4429+ * as though we had just finished executing the INCDIR
4430+ * hook. We honour $INC here just like we would for
4431+ * an INC hook, the hook might have rewritten @INC
4432+ * at the same time as returning something to us.
4433+ */
4434+ inc_idx_sv = GvSVn (PL_incgv );
4435+ incdir_continue_inc_idx = SvOK (inc_idx_sv )
4436+ ? SvIV (inc_idx_sv ) : -1 ;
4437+
4438+ goto done_hook ;
4439+ }
4440+
43704441 arg = SP [i ++ ];
43714442
43724443 if (SvROK (arg ) && (SvTYPE (SvRV (arg )) <= SVt_PVLV )
@@ -4415,6 +4486,7 @@ S_require_file(pTHX_ SV *sv)
44154486 tryrsfp = PerlIO_open (BIT_BUCKET ,
44164487 PERL_SCRIPT_MODE );
44174488 }
4489+ done_hook :
44184490 SP -- ;
44194491 } else {
44204492 SV * errsv = ERRSV ;
0 commit comments