e62432d63ef7ad05916c925dc41965f900c5a869
[p5sagit/p5-mst-13.2.git] / hv.c
1 /* $RCSfile: hash.c,v $$Revision: 4.1 $$Date: 92/08/07 18:21:48 $
2  *
3  *    Copyright (c) 1991, Larry Wall
4  *
5  *    You may distribute under the terms of either the GNU General Public
6  *    License or the Artistic License, as specified in the README file.
7  *
8  * $Log:        hash.c,v $
9  * Revision 4.1  92/08/07  18:21:48  lwall
10  * 
11  * Revision 4.0.1.3  92/06/08  13:26:29  lwall
12  * patch20: removed implicit int declarations on functions
13  * patch20: delete could cause %array to give too low a count of buckets filled
14  * patch20: hash tables now split only if the memory is available to do so
15  * 
16  * Revision 4.0.1.2  91/11/05  17:24:13  lwall
17  * patch11: saberized perl
18  * 
19  * Revision 4.0.1.1  91/06/07  11:10:11  lwall
20  * patch4: new copyright notice
21  * 
22  * Revision 4.0  91/03/20  01:22:26  lwall
23  * 4.0 baseline.
24  * 
25  */
26
27 #include "EXTERN.h"
28 #include "perl.h"
29
30 static void hsplit();
31
32 static void hfreeentries();
33
34 SV**
35 hv_fetch(hv,key,klen,lval)
36 HV *hv;
37 char *key;
38 U32 klen;
39 I32 lval;
40 {
41     register XPVHV* xhv;
42     register char *s;
43     register I32 i;
44     register I32 hash;
45     register HE *entry;
46     register I32 maxi;
47     SV *sv;
48 #ifdef SOME_DBM
49     datum dkey,dcontent;
50 #endif
51
52     if (!hv)
53         return 0;
54     xhv = (XPVHV*)SvANY(hv);
55     if (!xhv->xhv_array) {
56         if (lval)
57             Newz(503,xhv->xhv_array, xhv->xhv_max + 1, HE*);
58         else
59             return 0;
60     }
61
62     /* The hash function we use on symbols has to be equal to the first
63      * character when taken modulo 128, so that sv_reset() can be implemented
64      * efficiently.  We throw in the second character and the last character
65      * (times 128) so that long chains of identifiers starting with the
66      * same letter don't have to be strEQ'ed within hv_fetch(), since it
67      * compares hash values before trying strEQ().
68      */
69     if (!xhv->xhv_coeffsize && klen)
70         hash = klen ? *key + 128 * key[1] + 128 * key[klen-1] : 0;
71     else {      /* use normal coefficients */
72         if (klen < xhv->xhv_coeffsize)
73             maxi = klen;
74         else
75             maxi = xhv->xhv_coeffsize;
76         for (s=key,             i=0,    hash = 0;
77                             i < maxi;                   /*SUPPRESS 8*/
78              s++,               i++,    hash *= 5) {
79             hash += *s * coeff[i];
80         }
81     }
82
83     entry = xhv->xhv_array[hash & xhv->xhv_max];
84     for (; entry; entry = entry->hent_next) {
85         if (entry->hent_hash != hash)           /* strings can't be equal */
86             continue;
87         if (entry->hent_klen != klen)
88             continue;
89         if (bcmp(entry->hent_key,key,klen))     /* is this it? */
90             continue;
91         return &entry->hent_val;
92     }
93 #ifdef SOME_DBM
94     if (xhv->xhv_dbm) {
95         dkey.dptr = key;
96         dkey.dsize = klen;
97 #ifdef HAS_GDBM
98         dcontent = gdbm_fetch(xhv->xhv_dbm,dkey);
99 #else
100         dcontent = dbm_fetch(xhv->xhv_dbm,dkey);
101 #endif
102         if (dcontent.dptr) {                    /* found one */
103             sv = NEWSV(60,dcontent.dsize);
104             sv_setpvn(sv,dcontent.dptr,dcontent.dsize);
105             return hv_store(hv,key,klen,sv,hash);               /* cache it */
106         }
107     }
108 #endif
109     if (lval) {         /* gonna assign to this, so it better be there */
110         sv = NEWSV(61,0);
111         return hv_store(hv,key,klen,sv,hash);
112     }
113     return 0;
114 }
115
116 SV**
117 hv_store(hv,key,klen,val,hash)
118 HV *hv;
119 char *key;
120 U32 klen;
121 SV *val;
122 register I32 hash;
123 {
124     register XPVHV* xhv;
125     register char *s;
126     register I32 i;
127     register HE *entry;
128     register HE **oentry;
129     register I32 maxi;
130
131     if (!hv)
132         return 0;
133
134     xhv = (XPVHV*)SvANY(hv);
135     if (hash)
136         /*SUPPRESS 530*/
137         ;
138     else if (!xhv->xhv_coeffsize && klen)
139         hash = klen ? *key + 128 * key[1] + 128 * key[klen-1] : 0;
140     else {      /* use normal coefficients */
141         if (klen < xhv->xhv_coeffsize)
142             maxi = klen;
143         else
144             maxi = xhv->xhv_coeffsize;
145         for (s=key,             i=0,    hash = 0;
146                             i < maxi;                   /*SUPPRESS 8*/
147              s++,               i++,    hash *= 5) {
148             hash += *s * coeff[i];
149         }
150     }
151
152     if (!xhv->xhv_array)
153         Newz(505,xhv->xhv_array, xhv->xhv_max + 1, HE*);
154
155     oentry = &(xhv->xhv_array[hash & xhv->xhv_max]);
156     i = 1;
157
158     if (SvMAGICAL(hv)) {
159         MAGIC* mg = SvMAGIC(hv);
160         sv_magic(val, (SV*)hv, tolower(mg->mg_type), key, klen);
161     }
162     for (entry = *oentry; entry; i=0, entry = entry->hent_next) {
163         if (entry->hent_hash != hash)           /* strings can't be equal */
164             continue;
165         if (entry->hent_klen != klen)
166             continue;
167         if (bcmp(entry->hent_key,key,klen))     /* is this it? */
168             continue;
169         sv_free(entry->hent_val);
170         entry->hent_val = val;
171         return &entry->hent_val;
172     }
173     New(501,entry, 1, HE);
174
175     entry->hent_klen = klen;
176     entry->hent_key = nsavestr(key,klen);
177     entry->hent_val = val;
178     entry->hent_hash = hash;
179     entry->hent_next = *oentry;
180     *oentry = entry;
181
182     /* hv_dbmstore not necessary here because it's called from sv_setmagic() */
183
184     if (i) {                            /* initial entry? */
185         xhv->xhv_fill++;
186 #ifdef SOME_DBM
187         if (xhv->xhv_dbm && xhv->xhv_max >= DBM_CACHE_MAX)
188             return &entry->hent_val;
189 #endif
190         if (xhv->xhv_fill > xhv->xhv_dosplit)
191             hsplit(hv);
192     }
193 #ifdef SOME_DBM
194     else if (xhv->xhv_dbm) {            /* is this just a cache for dbm file? */
195         void he_delayfree();
196         HE* ent;
197
198         ent = xhv->xhv_array[hash & xhv->xhv_max];
199         oentry = &ent->hent_next;
200         ent = *oentry;
201         while (ent) {   /* trim chain down to 1 entry */
202             *oentry = ent->hent_next;
203             he_delayfree(ent);  /* no doubt they'll want this next, sigh... */
204             ent = *oentry;
205         }
206     }
207 #endif
208
209     return &entry->hent_val;
210 }
211
212 SV *
213 hv_delete(hv,key,klen)
214 HV *hv;
215 char *key;
216 U32 klen;
217 {
218     register XPVHV* xhv;
219     register char *s;
220     register I32 i;
221     register I32 hash;
222     register HE *entry;
223     register HE **oentry;
224     SV *sv;
225     I32 maxi;
226 #ifdef SOME_DBM
227     datum dkey;
228 #endif
229
230     if (!hv)
231         return Nullsv;
232     xhv = (XPVHV*)SvANY(hv);
233     if (!xhv->xhv_array)
234         return Nullsv;
235     if (!xhv->xhv_coeffsize && klen)
236         hash = klen ? *key + 128 * key[1] + 128 * key[klen-1] : 0;
237     else {      /* use normal coefficients */
238         if (klen < xhv->xhv_coeffsize)
239             maxi = klen;
240         else
241             maxi = xhv->xhv_coeffsize;
242         for (s=key,             i=0,    hash = 0;
243                             i < maxi;                   /*SUPPRESS 8*/
244              s++,               i++,    hash *= 5) {
245             hash += *s * coeff[i];
246         }
247     }
248
249     oentry = &(xhv->xhv_array[hash & xhv->xhv_max]);
250     entry = *oentry;
251     i = 1;
252     for (; entry; i=0, oentry = &entry->hent_next, entry = *oentry) {
253         if (entry->hent_hash != hash)           /* strings can't be equal */
254             continue;
255         if (entry->hent_klen != klen)
256             continue;
257         if (bcmp(entry->hent_key,key,klen))     /* is this it? */
258             continue;
259         *oentry = entry->hent_next;
260         if (i && !*oentry)
261             xhv->xhv_fill--;
262         sv = sv_mortalcopy(entry->hent_val);
263         he_free(entry);
264 #ifdef SOME_DBM
265       do_dbm_delete:
266         if (xhv->xhv_dbm) {
267             dkey.dptr = key;
268             dkey.dsize = klen;
269 #ifdef HAS_GDBM
270             gdbm_delete(xhv->xhv_dbm,dkey);
271 #else
272             dbm_delete(xhv->xhv_dbm,dkey);
273 #endif
274         }
275 #endif
276         return sv;
277     }
278 #ifdef SOME_DBM
279     sv = Nullsv;
280     goto do_dbm_delete;
281 #else
282     return Nullsv;
283 #endif
284 }
285
286 static void
287 hsplit(hv)
288 HV *hv;
289 {
290     register XPVHV* xhv = (XPVHV*)SvANY(hv);
291     I32 oldsize = xhv->xhv_max + 1;
292     register I32 newsize = oldsize * 2;
293     register I32 i;
294     register HE **a;
295     register HE **b;
296     register HE *entry;
297     register HE **oentry;
298
299     a = xhv->xhv_array;
300     nomemok = TRUE;
301     Renew(a, newsize, HE*);
302     nomemok = FALSE;
303     if (!a) {
304         xhv->xhv_dosplit = xhv->xhv_max + 1;    /* never split again */
305         return;
306     }
307     Zero(&a[oldsize], oldsize, HE*);            /* zero 2nd half*/
308     xhv->xhv_max = --newsize;
309     xhv->xhv_dosplit = xhv->xhv_max * FILLPCT / 100;
310     xhv->xhv_array = a;
311
312     for (i=0; i<oldsize; i++,a++) {
313         if (!*a)                                /* non-existent */
314             continue;
315         b = a+oldsize;
316         for (oentry = a, entry = *a; entry; entry = *oentry) {
317             if ((entry->hent_hash & newsize) != i) {
318                 *oentry = entry->hent_next;
319                 entry->hent_next = *b;
320                 if (!*b)
321                     xhv->xhv_fill++;
322                 *b = entry;
323                 continue;
324             }
325             else
326                 oentry = &entry->hent_next;
327         }
328         if (!*a)                                /* everything moved */
329             xhv->xhv_fill--;
330     }
331 }
332
333 HV *
334 newHV(lookat)
335 U32 lookat;
336 {
337     register HV *hv;
338     register XPVHV* xhv;
339
340     Newz(502,hv, 1, HV);
341     SvREFCNT(hv) = 1;
342     sv_upgrade(hv, SVt_PVHV);
343     xhv = (XPVHV*)SvANY(hv);
344     SvPOK_off(hv);
345     SvNOK_off(hv);
346     if (lookat) {
347         xhv->xhv_coeffsize = lookat;
348         xhv->xhv_max = 7;               /* it's a normal associative array */
349         xhv->xhv_dosplit = xhv->xhv_max * FILLPCT / 100;
350     }
351     else {
352         xhv->xhv_max = 127;             /* it's a symbol table */
353         xhv->xhv_dosplit = 128;         /* so never split */
354     }
355     xhv->xhv_fill = 0;
356     xhv->xhv_pmroot = 0;
357 #ifdef SOME_DBM
358     xhv->xhv_dbm = 0;
359 #endif
360     (void)hv_iterinit(hv);      /* so each() will start off right */
361     return hv;
362 }
363
364 void
365 he_free(hent)
366 register HE *hent;
367 {
368     if (!hent)
369         return;
370     sv_free(hent->hent_val);
371     Safefree(hent->hent_key);
372     Safefree(hent);
373 }
374
375 void
376 he_delayfree(hent)
377 register HE *hent;
378 {
379     if (!hent)
380         return;
381     sv_2mortal(hent->hent_val); /* free between statements */
382     Safefree(hent->hent_key);
383     Safefree(hent);
384 }
385
386 void
387 hv_clear(hv,dodbm)
388 HV *hv;
389 I32 dodbm;
390 {
391     register XPVHV* xhv;
392     if (!hv)
393         return;
394     xhv = (XPVHV*)SvANY(hv);
395     hfreeentries(hv,dodbm);
396     xhv->xhv_fill = 0;
397 #ifndef lint
398     if (xhv->xhv_array)
399         (void)memzero((char*)xhv->xhv_array, (xhv->xhv_max + 1) * sizeof(HE*));
400 #endif
401 }
402
403 static void
404 hfreeentries(hv,dodbm)
405 HV *hv;
406 I32 dodbm;
407 {
408     register XPVHV* xhv;
409     register HE *hent;
410     register HE *ohent = Null(HE*);
411 #ifdef SOME_DBM
412     datum dkey;
413     datum nextdkey;
414 #ifdef HAS_GDBM
415     GDBM_FILE old_dbm;
416 #else
417 #ifdef HAS_NDBM
418     DBM *old_dbm;
419 #else
420     I32 old_dbm;
421 #endif
422 #endif
423 #endif
424
425     if (!hv)
426         return;
427     xhv = (XPVHV*)SvANY(hv);
428     if (!xhv->xhv_array)
429         return;
430 #ifdef SOME_DBM
431     if ((old_dbm = xhv->xhv_dbm) && dodbm) {
432 #ifdef HAS_GDBM
433         while (dkey = gdbm_firstkey(xhv->xhv_dbm), dkey.dptr) {
434 #else
435         while (dkey = dbm_firstkey(xhv->xhv_dbm), dkey.dptr) {
436 #endif
437             do {
438 #ifdef HAS_GDBM
439                 nextdkey = gdbm_nextkey(xhv->xhv_dbm, dkey);
440 #else
441 #ifdef HAS_NDBM
442 #ifdef _CX_UX
443                 nextdkey = dbm_nextkey(xhv->xhv_dbm, dkey);
444 #else
445                 nextdkey = dbm_nextkey(xhv->xhv_dbm);
446 #endif
447 #else
448                 nextdkey = nextkey(dkey);
449 #endif
450 #endif
451 #ifdef HAS_GDBM
452                 gdbm_delete(xhv->xhv_dbm,dkey);
453 #else
454                 dbm_delete(xhv->xhv_dbm,dkey);
455 #endif
456                 dkey = nextdkey;
457             } while (dkey.dptr);        /* one way or another, this works */
458         }
459     }
460     xhv->xhv_dbm = 0;                   /* now clear just cache */
461 #endif
462     (void)hv_iterinit(hv);
463     /*SUPPRESS 560*/
464     while (hent = hv_iternext(hv)) {    /* concise but not very efficient */
465         he_free(ohent);
466         ohent = hent;
467     }
468     he_free(ohent);
469 #ifdef SOME_DBM
470     xhv->xhv_dbm = old_dbm;
471 #endif
472     if (SvMAGIC(hv))
473         mg_clear(hv);
474 }
475
476 void
477 hv_undef(hv,dodbm)
478 HV *hv;
479 I32 dodbm;
480 {
481     register XPVHV* xhv;
482     if (!hv)
483         return;
484     xhv = (XPVHV*)SvANY(hv);
485     hfreeentries(hv,dodbm);
486     Safefree(xhv->xhv_array);
487     xhv->xhv_array = 0;
488     if (xhv->xhv_coeffsize) {
489         xhv->xhv_max = 7;               /* it's a normal associative array */
490         xhv->xhv_dosplit = xhv->xhv_max * FILLPCT / 100;
491     }
492     else {
493         xhv->xhv_max = 127;             /* it's a symbol table */
494         xhv->xhv_dosplit = 128;         /* so never split */
495     }
496     xhv->xhv_fill = 0;
497 #ifdef SOME_DBM
498     xhv->xhv_dbm = 0;
499 #endif
500     (void)hv_iterinit(hv);      /* so each() will start off right */
501 }
502
503 void
504 hv_free(hv,dodbm)
505 register HV *hv;
506 I32 dodbm;
507 {
508     if (!hv)
509         return;
510     hfreeentries(hv,dodbm);
511     Safefree(HvARRAY(hv));
512     Safefree(hv);
513 }
514
515 I32
516 hv_iterinit(hv)
517 HV *hv;
518 {
519     register XPVHV* xhv = (XPVHV*)SvANY(hv);
520     xhv->xhv_riter = -1;
521     xhv->xhv_eiter = Null(HE*);
522     return xhv->xhv_fill;
523 }
524
525 HE *
526 hv_iternext(hv)
527 HV *hv;
528 {
529     register XPVHV* xhv;
530     register HE *entry;
531 #ifdef SOME_DBM
532     datum key;
533 #endif
534
535     if (!hv)
536         fatal("Bad associative array");
537     xhv = (XPVHV*)SvANY(hv);
538     entry = xhv->xhv_eiter;
539 #ifdef SOME_DBM
540     if (xhv->xhv_dbm) {
541         if (entry) {
542 #ifdef HAS_GDBM
543             key.dptr = entry->hent_key;
544             key.dsize = entry->hent_klen;
545             key = gdbm_nextkey(xhv->xhv_dbm, key);
546 #else
547 #ifdef HAS_NDBM
548 #ifdef _CX_UX
549             key.dptr = entry->hent_key;
550             key.dsize = entry->hent_klen;
551             key = dbm_nextkey(xhv->xhv_dbm, key);
552 #else
553             key = dbm_nextkey(xhv->xhv_dbm);
554 #endif /* _CX_UX */
555 #else
556             key.dptr = entry->hent_key;
557             key.dsize = entry->hent_klen;
558             key = nextkey(key);
559 #endif
560 #endif
561         }
562         else {
563             Newz(504,entry, 1, HE);
564             xhv->xhv_eiter = entry;
565 #ifdef HAS_GDBM
566             key = gdbm_firstkey(xhv->xhv_dbm);
567 #else
568             key = dbm_firstkey(xhv->xhv_dbm);
569 #endif
570         }
571         entry->hent_key = key.dptr;
572         entry->hent_klen = key.dsize;
573         if (!key.dptr) {
574             if (entry->hent_val)
575                 sv_free(entry->hent_val);
576             Safefree(entry);
577             xhv->xhv_eiter = Null(HE*);
578             return Null(HE*);
579         }
580         return entry;
581     }
582 #endif
583     if (!xhv->xhv_array)
584         Newz(506,xhv->xhv_array, xhv->xhv_max + 1, HE*);
585     do {
586         if (entry)
587             entry = entry->hent_next;
588         if (!entry) {
589             xhv->xhv_riter++;
590             if (xhv->xhv_riter > xhv->xhv_max) {
591                 xhv->xhv_riter = -1;
592                 break;
593             }
594             entry = xhv->xhv_array[xhv->xhv_riter];
595         }
596     } while (!entry);
597
598     xhv->xhv_eiter = entry;
599     return entry;
600 }
601
602 char *
603 hv_iterkey(entry,retlen)
604 register HE *entry;
605 I32 *retlen;
606 {
607     *retlen = entry->hent_klen;
608     return entry->hent_key;
609 }
610
611 SV *
612 hv_iterval(hv,entry)
613 HV *hv;
614 register HE *entry;
615 {
616 #ifdef SOME_DBM
617     register XPVHV* xhv;
618     datum key, content;
619
620     if (!hv)
621         fatal("Bad associative array");
622     xhv = (XPVHV*)SvANY(hv);
623     if (xhv->xhv_dbm) {
624         key.dptr = entry->hent_key;
625         key.dsize = entry->hent_klen;
626 #ifdef HAS_GDBM
627         content = gdbm_fetch(xhv->xhv_dbm,key);
628 #else
629         content = dbm_fetch(xhv->xhv_dbm,key);
630 #endif
631         if (!entry->hent_val)
632             entry->hent_val = NEWSV(62,0);
633         sv_setpvn(entry->hent_val,content.dptr,content.dsize);
634     }
635 #endif
636     return entry->hent_val;
637 }
638
639 #ifdef SOME_DBM
640
641 #ifndef OP_CREAT
642 #  ifdef I_FCNTL
643 #    include <fcntl.h>
644 #  endif
645 #  ifdef I_SYS_FILE
646 #    include <sys/file.h>
647 #  endif
648 #endif
649
650 #ifndef OP_RDONLY
651 #define OP_RDONLY 0
652 #endif
653 #ifndef OP_RDWR
654 #define OP_RDWR 2
655 #endif
656 #ifndef OP_CREAT
657 #define OP_CREAT 01000
658 #endif
659
660 bool
661 hv_dbmopen(hv,fname,mode)
662 HV *hv;
663 char *fname;
664 I32 mode;
665 {
666     register XPVHV* xhv;
667     if (!hv)
668         return FALSE;
669     xhv = (XPVHV*)SvANY(hv);
670 #ifdef HAS_ODBM
671     if (xhv->xhv_dbm)   /* never really closed it */
672         return TRUE;
673 #endif
674     if (xhv->xhv_dbm) {
675         hv_dbmclose(hv);
676         xhv->xhv_dbm = 0;
677     }
678     hv_clear(hv, FALSE);        /* clear cache */
679 #ifdef HAS_GDBM
680     if (mode >= 0)
681         xhv->xhv_dbm = gdbm_open(fname, 0, GDBM_WRCREAT,mode, (void *) NULL);
682     if (!xhv->xhv_dbm)
683         xhv->xhv_dbm = gdbm_open(fname, 0, GDBM_WRITER, mode, (void *) NULL);
684     if (!xhv->xhv_dbm)
685         xhv->xhv_dbm = gdbm_open(fname, 0, GDBM_READER, mode, (void *) NULL);
686 #else
687 #ifdef HAS_NDBM
688     if (mode >= 0)
689         xhv->xhv_dbm = dbm_open(fname, OP_RDWR|OP_CREAT, mode);
690     if (!xhv->xhv_dbm)
691         xhv->xhv_dbm = dbm_open(fname, OP_RDWR, mode);
692     if (!xhv->xhv_dbm)
693         xhv->xhv_dbm = dbm_open(fname, OP_RDONLY, mode);
694 #else
695     if (dbmrefcnt++)
696         fatal("Old dbm can only open one database");
697     sprintf(buf,"%s.dir",fname);
698     if (stat(buf, &statbuf) < 0) {
699         if (mode < 0 || close(creat(buf,mode)) < 0)
700             return FALSE;
701         sprintf(buf,"%s.pag",fname);
702         if (close(creat(buf,mode)) < 0)
703             return FALSE;
704     }
705     xhv->xhv_dbm = dbminit(fname) >= 0;
706 #endif
707 #endif
708     if (!xhv->xhv_array && xhv->xhv_dbm != 0)
709         Newz(507,xhv->xhv_array, xhv->xhv_max + 1, HE*);
710     hv_magic(hv, 0, 'D');
711     return xhv->xhv_dbm != 0;
712 }
713
714 void
715 hv_dbmclose(hv)
716 HV *hv;
717 {
718     register XPVHV* xhv;
719     if (!hv)
720         fatal("Bad associative array");
721     xhv = (XPVHV*)SvANY(hv);
722     if (xhv->xhv_dbm) {
723 #ifdef HAS_GDBM
724         gdbm_close(xhv->xhv_dbm);
725         xhv->xhv_dbm = 0;
726 #else
727 #ifdef HAS_NDBM
728         dbm_close(xhv->xhv_dbm);
729         xhv->xhv_dbm = 0;
730 #else
731         /* dbmrefcnt--;  */     /* doesn't work, rats */
732 #endif
733 #endif
734     }
735     else if (dowarn)
736         warn("Close on unopened dbm file");
737 }
738
739 bool
740 hv_dbmstore(hv,key,klen,sv)
741 HV *hv;
742 char *key;
743 U32 klen;
744 register SV *sv;
745 {
746     register XPVHV* xhv;
747     datum dkey, dcontent;
748     I32 error;
749
750     if (!hv)
751         return FALSE;
752     xhv = (XPVHV*)SvANY(hv);
753     if (!xhv->xhv_dbm)
754         return FALSE;
755     dkey.dptr = key;
756     dkey.dsize = klen;
757     dcontent.dptr = SvPVn(sv);
758     dcontent.dsize = SvCUR(sv);
759 #ifdef HAS_GDBM
760     error = gdbm_store(xhv->xhv_dbm, dkey, dcontent, GDBM_REPLACE);
761 #else
762     error = dbm_store(xhv->xhv_dbm, dkey, dcontent, DBM_REPLACE);
763 #endif
764     if (error) {
765         if (errno == EPERM)
766             fatal("No write permission to dbm file");
767         fatal("dbm store returned %d, errno %d, key \"%s\"",error,errno,key);
768 #ifdef HAS_NDBM
769         dbm_clearerr(xhv->xhv_dbm);
770 #endif
771     }
772     return !error;
773 }
774 #endif /* SOME_DBM */
775
776 #ifdef XXX
777                 magictype = MgTYPE(magic);
778                 switch (magictype) {
779                 case 'E':
780                     environ[0] = Nullch;
781                     break;
782                 case 'S':
783 #ifndef NSIG
784 #define NSIG 32
785 #endif
786                     for (i = 1; i < NSIG; i++)
787                         signal(i, SIG_DFL);     /* crunch, crunch, crunch */
788                     break;
789                 }
790
791                     if (magic) {
792                         sv_magic(tmpstr, (SV*)tmpgv, magic, tmps, SvCUR(sv));
793                         sv_magicset(tmpstr, magic);
794                     }
795
796         if (hv->hv_sv.sv_rare && !sv->sv_magic)
797             sv_magic(sv, (GV*)hv, hv->hv_sv.sv_rare, key, keylen);
798 #endif
799
800 void
801 hv_magic(hv, gv, how)
802 HV* hv;
803 GV* gv;
804 I32 how;
805 {
806     sv_magic(hv, gv, how, 0, 0);
807 }