summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorLarry Wall <larry@netlabs.com>1993-11-10 00:00:00 +0000
committerLarry Wall <larry@netlabs.com>1993-11-10 00:00:00 +0000
commit463ee0b2acbd047c27e8b5393cdd8398881824c5 (patch)
treeae17d9179fc861ae5fc5a86da9139631530cb6fe /hv.c
parent93a17b20b6d176db3f04f51a63b0a781e5ffd11c (diff)
downloadperl-463ee0b2acbd047c27e8b5393cdd8398881824c5.tar.gz
perl 5.0 alpha 4
[editor's note: the sparc executables have not been included, and emacs backup files have been removed. This was reconstructed from a tarball found on the September 1994 InfoMagic CD; the date of this is approximate]
Diffstat (limited to 'hv.c')
-rw-r--r--hv.c546
1 files changed, 99 insertions, 447 deletions
diff --git a/hv.c b/hv.c
index 669d154ca5..b0958e290a 100644
--- a/hv.c
+++ b/hv.c
@@ -43,44 +43,39 @@ I32 lval;
register I32 i;
register I32 hash;
register HE *entry;
- register I32 maxi;
SV *sv;
-#ifdef SOME_DBM
- datum dkey,dcontent;
-#endif
if (!hv)
return 0;
+
+ if (SvMAGICAL(hv)) {
+ if (mg_find((SV*)hv,'P')) {
+ sv = sv_2mortal(NEWSV(61,0));
+ mg_copy((SV*)hv, sv, key, klen);
+ if (!lval) {
+ mg_get(sv);
+ sv_unmagic(sv,'p');
+ }
+ Sv = sv;
+ return &Sv;
+ }
+ }
+
xhv = (XPVHV*)SvANY(hv);
if (!xhv->xhv_array) {
if (lval)
- Newz(503,xhv->xhv_array, xhv->xhv_max + 1, HE*);
+ Newz(503,xhv->xhv_array, sizeof(HE*) * (xhv->xhv_max + 1), char);
else
return 0;
}
- /* The hash function we use on symbols has to be equal to the first
- * character when taken modulo 128, so that sv_reset() can be implemented
- * efficiently. We throw in the second character and the last character
- * (times 128) so that long chains of identifiers starting with the
- * same letter don't have to be strEQ'ed within hv_fetch(), since it
- * compares hash values before trying strEQ().
- */
- if (!xhv->xhv_coeffsize && klen)
- hash = klen ? *key + 128 * key[1] + 128 * key[klen-1] : 0;
- else { /* use normal coefficients */
- if (klen < xhv->xhv_coeffsize)
- maxi = klen;
- else
- maxi = xhv->xhv_coeffsize;
- for (s=key, i=0, hash = 0;
- i < maxi; /*SUPPRESS 8*/
- s++, i++, hash *= 5) {
- hash += *s * coeff[i];
- }
- }
+ i = klen;
+ hash = 0;
+ s = key;
+ while (i--)
+ hash = hash * 33 + *s++;
- entry = xhv->xhv_array[hash & xhv->xhv_max];
+ entry = ((HE**)xhv->xhv_array)[hash & xhv->xhv_max];
for (; entry; entry = entry->hent_next) {
if (entry->hent_hash != hash) /* strings can't be equal */
continue;
@@ -90,22 +85,6 @@ I32 lval;
continue;
return &entry->hent_val;
}
-#ifdef SOME_DBM
- if (xhv->xhv_dbm) {
- dkey.dptr = key;
- dkey.dsize = klen;
-#ifdef HAS_GDBM
- dcontent = gdbm_fetch(xhv->xhv_dbm,dkey);
-#else
- dcontent = dbm_fetch(xhv->xhv_dbm,dkey);
-#endif
- if (dcontent.dptr) { /* found one */
- sv = NEWSV(60,dcontent.dsize);
- sv_setpvn(sv,dcontent.dptr,dcontent.dsize);
- return hv_store(hv,key,klen,sv,hash); /* cache it */
- }
- }
-#endif
if (lval) { /* gonna assign to this, so it better be there */
sv = NEWSV(61,0);
return hv_store(hv,key,klen,sv,hash);
@@ -126,39 +105,30 @@ register U32 hash;
register I32 i;
register HE *entry;
register HE **oentry;
- register I32 maxi;
if (!hv)
return 0;
xhv = (XPVHV*)SvANY(hv);
- if (hash)
- /*SUPPRESS 530*/
- ;
- else if (!xhv->xhv_coeffsize && klen)
- hash = klen ? *key + 128 * key[1] + 128 * key[klen-1] : 0;
- else { /* use normal coefficients */
- if (klen < xhv->xhv_coeffsize)
- maxi = klen;
- else
- maxi = xhv->xhv_coeffsize;
- for (s=key, i=0, hash = 0;
- i < maxi; /*SUPPRESS 8*/
- s++, i++, hash *= 5) {
- hash += *s * coeff[i];
- }
+ if (SvMAGICAL(hv)) {
+ MAGIC* mg = SvMAGIC(hv);
+ mg_copy((SV*)hv, val, key, klen);
+ if (!xhv->xhv_array)
+ return 0;
+ }
+ if (!hash) {
+ i = klen;
+ s = key;
+ while (i--)
+ hash = hash * 33 + *s++;
}
if (!xhv->xhv_array)
- Newz(505,xhv->xhv_array, xhv->xhv_max + 1, HE*);
+ Newz(505, xhv->xhv_array, sizeof(HE**) * (xhv->xhv_max + 1), char);
- oentry = &(xhv->xhv_array[hash & xhv->xhv_max]);
+ oentry = &((HE**)xhv->xhv_array)[hash & xhv->xhv_max];
i = 1;
- if (SvMAGICAL(hv)) {
- MAGIC* mg = SvMAGIC(hv);
- sv_magic(val, (SV*)hv, tolower(mg->mg_type), key, klen);
- }
for (entry = *oentry; entry; i=0, entry = entry->hent_next) {
if (entry->hent_hash != hash) /* strings can't be equal */
continue;
@@ -179,32 +149,12 @@ register U32 hash;
entry->hent_next = *oentry;
*oentry = entry;
- /* hv_dbmstore not necessary here because it's called from sv_setmagic() */
-
+ xhv->xhv_keys++;
if (i) { /* initial entry? */
- xhv->xhv_fill++;
-#ifdef SOME_DBM
- if (xhv->xhv_dbm && xhv->xhv_max >= DBM_CACHE_MAX)
- return &entry->hent_val;
-#endif
- if (xhv->xhv_fill > xhv->xhv_dosplit)
+ ++xhv->xhv_fill;
+ if (xhv->xhv_keys > xhv->xhv_max)
hsplit(hv);
}
-#ifdef SOME_DBM
- else if (xhv->xhv_dbm) { /* is this just a cache for dbm file? */
- void he_delayfree();
- HE* ent;
-
- ent = xhv->xhv_array[hash & xhv->xhv_max];
- oentry = &ent->hent_next;
- ent = *oentry;
- while (ent) { /* trim chain down to 1 entry */
- *oentry = ent->hent_next;
- he_delayfree(ent); /* no doubt they'll want this next, sigh... */
- ent = *oentry;
- }
- }
-#endif
return &entry->hent_val;
}
@@ -222,31 +172,23 @@ U32 klen;
register HE *entry;
register HE **oentry;
SV *sv;
- I32 maxi;
-#ifdef SOME_DBM
- datum dkey;
-#endif
if (!hv)
return Nullsv;
+ if (SvMAGICAL(hv)) {
+ sv = *hv_fetch(hv, key, klen, TRUE);
+ mg_clear(sv);
+ }
xhv = (XPVHV*)SvANY(hv);
if (!xhv->xhv_array)
return Nullsv;
- if (!xhv->xhv_coeffsize && klen)
- hash = klen ? *key + 128 * key[1] + 128 * key[klen-1] : 0;
- else { /* use normal coefficients */
- if (klen < xhv->xhv_coeffsize)
- maxi = klen;
- else
- maxi = xhv->xhv_coeffsize;
- for (s=key, i=0, hash = 0;
- i < maxi; /*SUPPRESS 8*/
- s++, i++, hash *= 5) {
- hash += *s * coeff[i];
- }
- }
+ i = klen;
+ hash = 0;
+ s = key;
+ while (i--)
+ hash = hash * 33 + *s++;
- oentry = &(xhv->xhv_array[hash & xhv->xhv_max]);
+ oentry = &((HE**)xhv->xhv_array)[hash & xhv->xhv_max];
entry = *oentry;
i = 1;
for (; entry; i=0, oentry = &entry->hent_next, entry = *oentry) {
@@ -261,26 +203,10 @@ U32 klen;
xhv->xhv_fill--;
sv = sv_mortalcopy(entry->hent_val);
he_free(entry);
-#ifdef SOME_DBM
- do_dbm_delete:
- if (xhv->xhv_dbm) {
- dkey.dptr = key;
- dkey.dsize = klen;
-#ifdef HAS_GDBM
- gdbm_delete(xhv->xhv_dbm,dkey);
-#else
- dbm_delete(xhv->xhv_dbm,dkey);
-#endif
- }
-#endif
+ --xhv->xhv_keys;
return sv;
}
-#ifdef SOME_DBM
- sv = Nullsv;
- goto do_dbm_delete;
-#else
return Nullsv;
-#endif
}
static void
@@ -296,18 +222,13 @@ HV *hv;
register HE *entry;
register HE **oentry;
- a = xhv->xhv_array;
+ a = (HE**)xhv->xhv_array;
nomemok = TRUE;
Renew(a, newsize, HE*);
nomemok = FALSE;
- if (!a) {
- xhv->xhv_dosplit = xhv->xhv_max + 1; /* never split again */
- return;
- }
Zero(&a[oldsize], oldsize, HE*); /* zero 2nd half*/
xhv->xhv_max = --newsize;
- xhv->xhv_dosplit = xhv->xhv_max * FILLPCT / 100;
- xhv->xhv_array = a;
+ xhv->xhv_array = (char*)a;
for (i=0; i<oldsize; i++,a++) {
if (!*a) /* non-existent */
@@ -331,8 +252,7 @@ HV *hv;
}
HV *
-newHV(lookat)
-U32 lookat;
+newHV()
{
register HV *hv;
register XPVHV* xhv;
@@ -343,20 +263,9 @@ U32 lookat;
xhv = (XPVHV*)SvANY(hv);
SvPOK_off(hv);
SvNOK_off(hv);
- if (lookat) {
- xhv->xhv_coeffsize = lookat;
- xhv->xhv_max = 7; /* it's a normal associative array */
- xhv->xhv_dosplit = xhv->xhv_max * FILLPCT / 100;
- }
- else {
- xhv->xhv_max = 127; /* it's a symbol table */
- xhv->xhv_dosplit = 128; /* so never split */
- }
+ xhv->xhv_max = 7; /* start with 8 buckets */
xhv->xhv_fill = 0;
xhv->xhv_pmroot = 0;
-#ifdef SOME_DBM
- xhv->xhv_dbm = 0;
-#endif
(void)hv_iterinit(hv); /* so each() will start off right */
return hv;
}
@@ -384,81 +293,32 @@ register HE *hent;
}
void
-hv_clear(hv,dodbm)
+hv_clear(hv)
HV *hv;
-I32 dodbm;
{
register XPVHV* xhv;
if (!hv)
return;
xhv = (XPVHV*)SvANY(hv);
- hfreeentries(hv,dodbm);
+ hfreeentries(hv);
xhv->xhv_fill = 0;
-#ifndef lint
if (xhv->xhv_array)
- (void)memzero((char*)xhv->xhv_array, (xhv->xhv_max + 1) * sizeof(HE*));
-#endif
+ (void)memzero(xhv->xhv_array, (xhv->xhv_max + 1) * sizeof(HE*));
}
static void
-hfreeentries(hv,dodbm)
+hfreeentries(hv)
HV *hv;
-I32 dodbm;
{
register XPVHV* xhv;
register HE *hent;
register HE *ohent = Null(HE*);
-#ifdef SOME_DBM
- datum dkey;
- datum nextdkey;
-#ifdef HAS_GDBM
- GDBM_FILE old_dbm;
-#else
-#ifdef HAS_NDBM
- DBM *old_dbm;
-#else
- I32 old_dbm;
-#endif
-#endif
-#endif
if (!hv)
return;
xhv = (XPVHV*)SvANY(hv);
if (!xhv->xhv_array)
return;
-#ifdef SOME_DBM
- if ((old_dbm = xhv->xhv_dbm) && dodbm) {
-#ifdef HAS_GDBM
- while (dkey = gdbm_firstkey(xhv->xhv_dbm), dkey.dptr) {
-#else
- while (dkey = dbm_firstkey(xhv->xhv_dbm), dkey.dptr) {
-#endif
- do {
-#ifdef HAS_GDBM
- nextdkey = gdbm_nextkey(xhv->xhv_dbm, dkey);
-#else
-#ifdef HAS_NDBM
-#ifdef _CX_UX
- nextdkey = dbm_nextkey(xhv->xhv_dbm, dkey);
-#else
- nextdkey = dbm_nextkey(xhv->xhv_dbm);
-#endif
-#else
- nextdkey = nextkey(dkey);
-#endif
-#endif
-#ifdef HAS_GDBM
- gdbm_delete(xhv->xhv_dbm,dkey);
-#else
- dbm_delete(xhv->xhv_dbm,dkey);
-#endif
- dkey = nextdkey;
- } while (dkey.dptr); /* one way or another, this works */
- }
- }
- xhv->xhv_dbm = 0; /* now clear just cache */
-#endif
(void)hv_iterinit(hv);
/*SUPPRESS 560*/
while (hent = hv_iternext(hv)) { /* concise but not very efficient */
@@ -466,48 +326,33 @@ I32 dodbm;
ohent = hent;
}
he_free(ohent);
-#ifdef SOME_DBM
- xhv->xhv_dbm = old_dbm;
-#endif
if (SvMAGIC(hv))
- mg_clear(hv);
+ mg_clear((SV*)hv);
}
void
-hv_undef(hv,dodbm)
+hv_undef(hv)
HV *hv;
-I32 dodbm;
{
register XPVHV* xhv;
if (!hv)
return;
xhv = (XPVHV*)SvANY(hv);
- hfreeentries(hv,dodbm);
+ hfreeentries(hv);
Safefree(xhv->xhv_array);
xhv->xhv_array = 0;
- if (xhv->xhv_coeffsize) {
- xhv->xhv_max = 7; /* it's a normal associative array */
- xhv->xhv_dosplit = xhv->xhv_max * FILLPCT / 100;
- }
- else {
- xhv->xhv_max = 127; /* it's a symbol table */
- xhv->xhv_dosplit = 128; /* so never split */
- }
+ xhv->xhv_max = 7; /* it's a normal associative array */
xhv->xhv_fill = 0;
-#ifdef SOME_DBM
- xhv->xhv_dbm = 0;
-#endif
(void)hv_iterinit(hv); /* so each() will start off right */
}
void
-hv_free(hv,dodbm)
+hv_free(hv)
register HV *hv;
-I32 dodbm;
{
if (!hv)
return;
- hfreeentries(hv,dodbm);
+ hfreeentries(hv);
Safefree(HvARRAY(hv));
Safefree(hv);
}
@@ -528,60 +373,39 @@ HV *hv;
{
register XPVHV* xhv;
register HE *entry;
-#ifdef SOME_DBM
- datum key;
-#endif
+ MAGIC* mg;
if (!hv)
- fatal("Bad associative array");
+ croak("Bad associative array");
xhv = (XPVHV*)SvANY(hv);
entry = xhv->xhv_eiter;
-#ifdef SOME_DBM
- if (xhv->xhv_dbm) {
- if (entry) {
-#ifdef HAS_GDBM
- key.dptr = entry->hent_key;
- key.dsize = entry->hent_klen;
- key = gdbm_nextkey(xhv->xhv_dbm, key);
-#else
-#ifdef HAS_NDBM
-#ifdef _CX_UX
- key.dptr = entry->hent_key;
- key.dsize = entry->hent_klen;
- key = dbm_nextkey(xhv->xhv_dbm, key);
-#else
- key = dbm_nextkey(xhv->xhv_dbm);
-#endif /* _CX_UX */
-#else
- key.dptr = entry->hent_key;
- key.dsize = entry->hent_klen;
- key = nextkey(key);
-#endif
-#endif
- }
- else {
- Newz(504,entry, 1, HE);
- xhv->xhv_eiter = entry;
-#ifdef HAS_GDBM
- key = gdbm_firstkey(xhv->xhv_dbm);
-#else
- key = dbm_firstkey(xhv->xhv_dbm);
-#endif
- }
- entry->hent_key = key.dptr;
- entry->hent_klen = key.dsize;
- if (!key.dptr) {
- if (entry->hent_val)
- sv_free(entry->hent_val);
- Safefree(entry);
- xhv->xhv_eiter = Null(HE*);
- return Null(HE*);
- }
- return entry;
+
+ if (SvMAGICAL(hv) && (mg = mg_find((SV*)hv,'P'))) {
+ SV *key = sv_2mortal(NEWSV(0,0));
+ if (entry)
+ sv_setpvn(key, entry->hent_key, entry->hent_klen);
+ else {
+ Newz(504,entry, 1, HE);
+ xhv->xhv_eiter = entry;
+ }
+ magic_nextpack(hv,mg,key);
+ if (SvOK(key)) {
+ STRLEN len;
+ entry->hent_key = SvPV(key, len);
+ entry->hent_klen = len;
+ SvPOK_off(key);
+ SvPVX(key) = 0;
+ return entry;
+ }
+ if (entry->hent_val)
+ sv_free(entry->hent_val);
+ Safefree(entry);
+ xhv->xhv_eiter = Null(HE*);
+ return Null(HE*);
}
-#endif
+
if (!xhv->xhv_array)
- Newz(506,xhv->xhv_array, xhv->xhv_max + 1, HE*);
+ Newz(506,xhv->xhv_array, sizeof(HE*) * (xhv->xhv_max + 1), char);
do {
if (entry)
entry = entry->hent_next;
@@ -591,7 +415,7 @@ HV *hv;
xhv->xhv_riter = -1;
break;
}
- entry = xhv->xhv_array[xhv->xhv_riter];
+ entry = ((HE**)xhv->xhv_array)[xhv->xhv_riter];
}
} while (!entry);
@@ -613,195 +437,23 @@ hv_iterval(hv,entry)
HV *hv;
register HE *entry;
{
-#ifdef SOME_DBM
- register XPVHV* xhv;
- datum key, content;
-
- if (!hv)
- fatal("Bad associative array");
- xhv = (XPVHV*)SvANY(hv);
- if (xhv->xhv_dbm) {
- key.dptr = entry->hent_key;
- key.dsize = entry->hent_klen;
-#ifdef HAS_GDBM
- content = gdbm_fetch(xhv->xhv_dbm,key);
-#else
- content = dbm_fetch(xhv->xhv_dbm,key);
-#endif
- if (!entry->hent_val)
- entry->hent_val = NEWSV(62,0);
- sv_setpvn(entry->hent_val,content.dptr,content.dsize);
+ if (SvMAGICAL(hv)) {
+ if (mg_find((SV*)hv,'P')) {
+ SV* sv = sv_2mortal(NEWSV(61,0));
+ mg_copy((SV*)hv, sv, entry->hent_key, entry->hent_klen);
+ mg_get(sv);
+ sv_unmagic(sv,'p');
+ return sv;
+ }
}
-#endif
return entry->hent_val;
}
-#ifdef SOME_DBM
-
-#ifndef OP_CREAT
-# ifdef I_FCNTL
-# include <fcntl.h>
-# endif
-# ifdef I_SYS_FILE
-# include <sys/file.h>
-# endif
-#endif
-
-#ifndef OP_RDONLY
-#define OP_RDONLY 0
-#endif
-#ifndef OP_RDWR
-#define OP_RDWR 2
-#endif
-#ifndef OP_CREAT
-#define OP_CREAT 01000
-#endif
-
-bool
-hv_dbmopen(hv,fname,mode)
-HV *hv;
-char *fname;
-I32 mode;
-{
- register XPVHV* xhv;
- if (!hv)
- return FALSE;
- xhv = (XPVHV*)SvANY(hv);
-#ifdef HAS_ODBM
- if (xhv->xhv_dbm) /* never really closed it */
- return TRUE;
-#endif
- if (xhv->xhv_dbm) {
- hv_dbmclose(hv);
- xhv->xhv_dbm = 0;
- }
- hv_clear(hv, FALSE); /* clear cache */
-#ifdef HAS_GDBM
- if (mode >= 0)
- xhv->xhv_dbm = gdbm_open(fname, 0, GDBM_WRCREAT,mode, (void *) NULL);
- if (!xhv->xhv_dbm)
- xhv->xhv_dbm = gdbm_open(fname, 0, GDBM_WRITER, mode, (void *) NULL);
- if (!xhv->xhv_dbm)
- xhv->xhv_dbm = gdbm_open(fname, 0, GDBM_READER, mode, (void *) NULL);
-#else
-#ifdef HAS_NDBM
- if (mode >= 0)
- xhv->xhv_dbm = dbm_open(fname, OP_RDWR|OP_CREAT, mode);
- if (!xhv->xhv_dbm)
- xhv->xhv_dbm = dbm_open(fname, OP_RDWR, mode);
- if (!xhv->xhv_dbm)
- xhv->xhv_dbm = dbm_open(fname, OP_RDONLY, mode);
-#else
- if (dbmrefcnt++)
- fatal("Old dbm can only open one database");
- sprintf(buf,"%s.dir",fname);
- if (stat(buf, &statbuf) < 0) {
- if (mode < 0 || close(creat(buf,mode)) < 0)
- return FALSE;
- sprintf(buf,"%s.pag",fname);
- if (close(creat(buf,mode)) < 0)
- return FALSE;
- }
- xhv->xhv_dbm = dbminit(fname) >= 0;
-#endif
-#endif
- if (!xhv->xhv_array && xhv->xhv_dbm != 0)
- Newz(507,xhv->xhv_array, xhv->xhv_max + 1, HE*);
- hv_magic(hv, 0, 'D');
- return xhv->xhv_dbm != 0;
-}
-
-void
-hv_dbmclose(hv)
-HV *hv;
-{
- register XPVHV* xhv;
- if (!hv)
- fatal("Bad associative array");
- xhv = (XPVHV*)SvANY(hv);
- if (xhv->xhv_dbm) {
-#ifdef HAS_GDBM
- gdbm_close(xhv->xhv_dbm);
- xhv->xhv_dbm = 0;
-#else
-#ifdef HAS_NDBM
- dbm_close(xhv->xhv_dbm);
- xhv->xhv_dbm = 0;
-#else
- /* dbmrefcnt--; */ /* doesn't work, rats */
-#endif
-#endif
- }
- else if (dowarn)
- warn("Close on unopened dbm file");
-}
-
-bool
-hv_dbmstore(hv,key,klen,sv)
-HV *hv;
-char *key;
-U32 klen;
-register SV *sv;
-{
- register XPVHV* xhv;
- datum dkey, dcontent;
- I32 error;
-
- if (!hv)
- return FALSE;
- xhv = (XPVHV*)SvANY(hv);
- if (!xhv->xhv_dbm)
- return FALSE;
- dkey.dptr = key;
- dkey.dsize = klen;
- dcontent.dptr = SvPVn(sv);
- dcontent.dsize = SvCUR(sv);
-#ifdef HAS_GDBM
- error = gdbm_store(xhv->xhv_dbm, dkey, dcontent, GDBM_REPLACE);
-#else
- error = dbm_store(xhv->xhv_dbm, dkey, dcontent, DBM_REPLACE);
-#endif
- if (error) {
- if (errno == EPERM)
- fatal("No write permission to dbm file");
- fatal("dbm store returned %d, errno %d, key \"%s\"",error,errno,key);
-#ifdef HAS_NDBM
- dbm_clearerr(xhv->xhv_dbm);
-#endif
- }
- return !error;
-}
-#endif /* SOME_DBM */
-
-#ifdef XXX
- magictype = MgTYPE(magic);
- switch (magictype) {
- case 'E':
- environ[0] = Nullch;
- break;
- case 'S':
-#ifndef NSIG
-#define NSIG 32
-#endif
- for (i = 1; i < NSIG; i++)
- signal(i, SIG_DFL); /* crunch, crunch, crunch */
- break;
- }
-
- if (magic) {
- sv_magic(tmpstr, (SV*)tmpgv, magic, tmps, SvCUR(sv));
- sv_magicset(tmpstr, magic);
- }
-
- if (hv->hv_sv.sv_rare && !sv->sv_magic)
- sv_magic(sv, (GV*)hv, hv->hv_sv.sv_rare, key, keylen);
-#endif
-
void
hv_magic(hv, gv, how)
HV* hv;
GV* gv;
I32 how;
{
- sv_magic(hv, gv, how, 0, 0);
+ sv_magic((SV*)hv, (SV*)gv, how, 0, 0);
}