-HV*
-Perl_avhv_keys(pTHX_ AV *av)
-{
- SV **keysp = av_fetch(av, 0, FALSE);
- if (keysp) {
- SV *sv = *keysp;
- if (SvGMAGICAL(sv))
- mg_get(sv);
- if (SvROK(sv)) {
- sv = SvRV(sv);
- if (SvTYPE(sv) == SVt_PVHV)
- return (HV*)sv;
+ assert(av);
+
+ if (SvREADONLY(av))
+ Perl_croak(aTHX_ PL_no_modify);
+
+ if (SvRMAGICAL(av)) {
+ const MAGIC * const tied_magic = mg_find((SV*)av, PERL_MAGIC_tied);
+ if ((tied_magic || mg_find((SV*)av, PERL_MAGIC_regdata))) {
+ /* Handle negative array indices 20020222 MJD */
+ SV **svp;
+ if (key < 0) {
+ unsigned adjust_index = 1;
+ if (tied_magic) {
+ SV * const * const negative_indices_glob =
+ hv_fetch(SvSTASH(SvRV(SvTIED_obj((SV *)av,
+ tied_magic))),
+ NEGATIVE_INDICES_VAR, 16, 0);
+ if (negative_indices_glob
+ && SvTRUE(GvSV(*negative_indices_glob)))
+ adjust_index = 0;
+ }
+ if (adjust_index) {
+ key += AvFILL(av) + 1;
+ if (key < 0)
+ return NULL;
+ }
+ }
+ svp = av_fetch(av, key, TRUE);
+ if (svp) {
+ sv = *svp;
+ mg_clear(sv);
+ if (mg_find(sv, PERL_MAGIC_tiedelem)) {
+ sv_unmagic(sv, PERL_MAGIC_tiedelem); /* No longer an element */
+ return sv;
+ }
+ return NULL;
+ }
+ }
+ }
+
+ if (key < 0) {
+ key += AvFILL(av) + 1;
+ if (key < 0)
+ return NULL;
+ }
+
+ if (key > AvFILLp(av))
+ return NULL;
+ else {
+ if (!AvREAL(av) && AvREIFY(av))
+ av_reify(av);
+ sv = AvARRAY(av)[key];
+ if (key == AvFILLp(av)) {
+ AvARRAY(av)[key] = &PL_sv_undef;
+ do {
+ AvFILLp(av)--;
+ } while (--key >= 0 && AvARRAY(av)[key] == &PL_sv_undef);