@@ -4266,11 +4266,32 @@ S_require_file(pTHX_ SV *sv)
4266
4266
if (vms_unixname )
4267
4267
#endif
4268
4268
{
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 */
4270
4271
namesv = newSV_type (SVt_PV );
4271
4272
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
+ }
4274
4295
4275
4296
if (SvGMAGICAL (dirsv )) {
4276
4297
SvGETMAGIC (dirsv );
@@ -4289,6 +4310,7 @@ S_require_file(pTHX_ SV *sv)
4289
4310
int count ;
4290
4311
SV * * svp ;
4291
4312
SV * loader = dirsv ;
4313
+ UV diruv = PTR2UV (SvRV (dirsv ));
4292
4314
4293
4315
if (SvTYPE (SvRV (loader )) == SVt_PVAV
4294
4316
&& !SvOBJECT (SvRV (loader )))
@@ -4298,7 +4320,7 @@ S_require_file(pTHX_ SV *sv)
4298
4320
}
4299
4321
4300
4322
Perl_sv_setpvf (aTHX_ namesv , "/loader/0x%" UVxf "/%s" ,
4301
- PTR2UV ( SvRV ( dirsv )) , name );
4323
+ diruv , name );
4302
4324
tryname = SvPVX_const (namesv );
4303
4325
tryrsfp = NULL ;
4304
4326
@@ -4308,6 +4330,7 @@ S_require_file(pTHX_ SV *sv)
4308
4330
}
4309
4331
4310
4332
const char * method = NULL ;
4333
+ bool is_incdir = FALSE;
4311
4334
SV * inc_idx_sv = save_scalar (PL_incgv );
4312
4335
sv_setiv (inc_idx_sv ,inc_idx );
4313
4336
if (sv_isobject (loader )) {
@@ -4318,6 +4341,12 @@ S_require_file(pTHX_ SV *sv)
4318
4341
GV * gv = gv_fetchmethod_pvn_flags (pkg , "INC" , 3 , 0 );
4319
4342
if (gv && isGV (gv )) {
4320
4343
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
+ }
4321
4350
}
4322
4351
/* But if we have no method, check if this is a
4323
4352
* coderef, if it is then we treat it as an
@@ -4367,6 +4396,48 @@ S_require_file(pTHX_ SV *sv)
4367
4396
SV * arg ;
4368
4397
4369
4398
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
+
4370
4441
arg = SP [i ++ ];
4371
4442
4372
4443
if (SvROK (arg ) && (SvTYPE (SvRV (arg )) <= SVt_PVLV )
@@ -4415,6 +4486,7 @@ S_require_file(pTHX_ SV *sv)
4415
4486
tryrsfp = PerlIO_open (BIT_BUCKET ,
4416
4487
PERL_SCRIPT_MODE );
4417
4488
}
4489
+ done_hook :
4418
4490
SP -- ;
4419
4491
} else {
4420
4492
SV * errsv = ERRSV ;
0 commit comments