This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 5.0 alpha 3
[perl5.git] / hv.c
CommitLineData
79072805
LW
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
30static void hsplit();
31
32static void hfreeentries();
33
34SV**
35hv_fetch(hv,key,klen,lval)
36HV *hv;
37char *key;
38U32 klen;
39I32 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
116SV**
117hv_store(hv,key,klen,val,hash)
118HV *hv;
119char *key;
120U32 klen;
121SV *val;
93a17b20 122register U32 hash;
79072805
LW
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
212SV *
213hv_delete(hv,key,klen)
214HV *hv;
215char *key;
216U32 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
286static void
287hsplit(hv)
288HV *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
333HV *
334newHV(lookat)
335U32 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
364void
365he_free(hent)
366register HE *hent;
367{
368 if (!hent)
369 return;
370 sv_free(hent->hent_val);
371 Safefree(hent->hent_key);
372 Safefree(hent);
373}
374
375void
376he_delayfree(hent)
377register 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
386void
387hv_clear(hv,dodbm)
388HV *hv;
389I32 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
403static void
404hfreeentries(hv,dodbm)
405HV *hv;
406I32 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
476void
477hv_undef(hv,dodbm)
478HV *hv;
479I32 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
503void
504hv_free(hv,dodbm)
505register HV *hv;
506I32 dodbm;
507{
508 if (!hv)
509 return;
510 hfreeentries(hv,dodbm);
511 Safefree(HvARRAY(hv));
512 Safefree(hv);
513}
514
515I32
516hv_iterinit(hv)
517HV *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
525HE *
526hv_iternext(hv)
527HV *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
602char *
603hv_iterkey(entry,retlen)
604register HE *entry;
605I32 *retlen;
606{
607 *retlen = entry->hent_klen;
608 return entry->hent_key;
609}
610
611SV *
612hv_iterval(hv,entry)
613HV *hv;
614register 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
660bool
661hv_dbmopen(hv,fname,mode)
662HV *hv;
663char *fname;
664I32 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
714void
715hv_dbmclose(hv)
716HV *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
739bool
740hv_dbmstore(hv,key,klen,sv)
741HV *hv;
742char *key;
743U32 klen;
744register 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
800void
801hv_magic(hv, gv, how)
802HV* hv;
803GV* gv;
804I32 how;
805{
806 sv_magic(hv, gv, how, 0, 0);
807}