This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Okay, here's your official unofficial closure leak patch
[perl5.git] / av.c
1 /*    av.c
2  *
3  *    Copyright (c) 1991-1994, 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  */
9
10 /*
11  * "...for the Entwives desired order, and plenty, and peace (by which they
12  * meant that things should remain where they had set them)." --Treebeard
13  */
14
15 #include "EXTERN.h"
16 #include "perl.h"
17
18 static void     av_reify _((AV* av));
19
20 static void
21 av_reify(av)
22 AV* av;
23 {
24     I32 key;
25     SV* sv;
26     
27     key = AvMAX(av) + 1;
28     while (key > AvFILL(av) + 1)
29         AvARRAY(av)[--key] = &sv_undef;
30     while (key) {
31         sv = AvARRAY(av)[--key];
32         assert(sv);
33         if (sv != &sv_undef)
34             (void)SvREFCNT_inc(sv);
35     }
36     AvREAL_on(av);
37 }
38
39 void
40 av_extend(av,key)
41 AV *av;
42 I32 key;
43 {
44     if (key > AvMAX(av)) {
45         SV** ary;
46         I32 tmp;
47         I32 newmax;
48
49         if (AvALLOC(av) != AvARRAY(av)) {
50             ary = AvALLOC(av) + AvFILL(av) + 1;
51             tmp = AvARRAY(av) - AvALLOC(av);
52             Move(AvARRAY(av), AvALLOC(av), AvFILL(av)+1, SV*);
53             AvMAX(av) += tmp;
54             SvPVX(av) = (char*)AvALLOC(av);
55             if (AvREAL(av)) {
56                 while (tmp)
57                     ary[--tmp] = &sv_undef;
58             }
59             
60             if (key > AvMAX(av) - 10) {
61                 newmax = key + AvMAX(av);
62                 goto resize;
63             }
64         }
65         else {
66             if (AvALLOC(av)) {
67                 newmax = key + AvMAX(av) / 5;
68               resize:
69                 Renew(AvALLOC(av),newmax+1, SV*);
70                 ary = AvALLOC(av) + AvMAX(av) + 1;
71                 tmp = newmax - AvMAX(av);
72                 if (av == stack) {      /* Oops, grew stack (via av_store()?) */
73                     stack_sp = AvALLOC(av) + (stack_sp - stack_base);
74                     stack_base = AvALLOC(av);
75                     stack_max = stack_base + newmax;
76                 }
77             }
78             else {
79                 newmax = key < 4 ? 4 : key;
80                 New(2,AvALLOC(av), newmax+1, SV*);
81                 ary = AvALLOC(av) + 1;
82                 tmp = newmax;
83                 AvALLOC(av)[0] = &sv_undef;     /* For the stacks */
84             }
85             if (AvREAL(av)) {
86                 while (tmp)
87                     ary[--tmp] = &sv_undef;
88             }
89             
90             SvPVX(av) = (char*)AvALLOC(av);
91             AvMAX(av) = newmax;
92         }
93     }
94 }
95
96 SV**
97 av_fetch(av,key,lval)
98 register AV *av;
99 I32 key;
100 I32 lval;
101 {
102     SV *sv;
103
104     if (!av)
105         return 0;
106
107     if (SvRMAGICAL(av)) {
108         if (mg_find((SV*)av,'P')) {
109             sv = sv_newmortal();
110             mg_copy((SV*)av, sv, 0, key);
111             Sv = sv;
112             return &Sv;
113         }
114     }
115
116     if (key < 0) {
117         key += AvFILL(av) + 1;
118         if (key < 0)
119             return 0;
120     }
121     else if (key > AvFILL(av)) {
122         if (!lval)
123             return 0;
124         if (AvREALISH(av))
125             sv = NEWSV(5,0);
126         else
127             sv = sv_newmortal();
128         return av_store(av,key,sv);
129     }
130     if (AvARRAY(av)[key] == &sv_undef) {
131         if (lval) {
132             sv = NEWSV(6,0);
133             return av_store(av,key,sv);
134         }
135         return 0;
136     }
137     return &AvARRAY(av)[key];
138 }
139
140 SV**
141 av_store(av,key,val)
142 register AV *av;
143 I32 key;
144 SV *val;
145 {
146     SV** ary;
147
148     if (!av)
149         return 0;
150
151     if (SvRMAGICAL(av)) {
152         if (mg_find((SV*)av,'P')) {
153             mg_copy((SV*)av, val, 0, key);
154             return 0;
155         }
156     }
157
158     if (key < 0) {
159         key += AvFILL(av) + 1;
160         if (key < 0)
161             return 0;
162     }
163     if (!val)
164         val = &sv_undef;
165
166     if (key > AvMAX(av))
167         av_extend(av,key);
168     if (AvREIFY(av))
169         av_reify(av);
170
171     ary = AvARRAY(av);
172     if (AvFILL(av) < key) {
173         if (!AvREAL(av)) {
174             if (av == stack && key > stack_sp - stack_base)
175                 stack_sp = stack_base + key;    /* XPUSH in disguise */
176             do
177                 ary[++AvFILL(av)] = &sv_undef;
178             while (AvFILL(av) < key);
179         }
180         AvFILL(av) = key;
181     }
182     else if (AvREAL(av))
183         SvREFCNT_dec(ary[key]);
184     ary[key] = val;
185     if (SvSMAGICAL(av)) {
186         if (val != &sv_undef) {
187             MAGIC* mg = SvMAGIC(av);
188             sv_magic(val, (SV*)av, toLOWER(mg->mg_type), 0, key);
189         }
190         mg_set((SV*)av);
191     }
192     return &ary[key];
193 }
194
195 AV *
196 newAV()
197 {
198     register AV *av;
199
200     av = (AV*)NEWSV(3,0);
201     sv_upgrade((SV *)av, SVt_PVAV);
202     AvREAL_on(av);
203     AvALLOC(av) = 0;
204     SvPVX(av) = 0;
205     AvMAX(av) = AvFILL(av) = -1;
206     return av;
207 }
208
209 AV *
210 av_make(size,strp)
211 register I32 size;
212 register SV **strp;
213 {
214     register AV *av;
215     register I32 i;
216     register SV** ary;
217
218     av = (AV*)NEWSV(8,0);
219     sv_upgrade((SV *) av,SVt_PVAV);
220     New(4,ary,size+1,SV*);
221     AvALLOC(av) = ary;
222     AvFLAGS(av) = AVf_REAL;
223     SvPVX(av) = (char*)ary;
224     AvFILL(av) = size - 1;
225     AvMAX(av) = size - 1;
226     for (i = 0; i < size; i++) {
227         assert (*strp);
228         ary[i] = NEWSV(7,0);
229         sv_setsv(ary[i], *strp);
230         strp++;
231     }
232     return av;
233 }
234
235 AV *
236 av_fake(size,strp)
237 register I32 size;
238 register SV **strp;
239 {
240     register AV *av;
241     register SV** ary;
242
243     av = (AV*)NEWSV(9,0);
244     sv_upgrade((SV *)av, SVt_PVAV);
245     New(4,ary,size+1,SV*);
246     AvALLOC(av) = ary;
247     Copy(strp,ary,size,SV*);
248     AvFLAGS(av) = AVf_REIFY;
249     SvPVX(av) = (char*)ary;
250     AvFILL(av) = size - 1;
251     AvMAX(av) = size - 1;
252     while (size--) {
253         assert (*strp);
254         SvTEMP_off(*strp);
255         strp++;
256     }
257     return av;
258 }
259
260 void
261 av_clear(av)
262 register AV *av;
263 {
264     register I32 key;
265     SV** ary;
266
267     if (!av || AvMAX(av) < 0)
268         return;
269     /*SUPPRESS 560*/
270
271     if (AvREAL(av)) {
272         ary = AvARRAY(av);
273         key = AvFILL(av) + 1;
274         while (key) {
275             SvREFCNT_dec(ary[--key]);
276             ary[key] = &sv_undef;
277         }
278     }
279     if (key = AvARRAY(av) - AvALLOC(av)) {
280         AvMAX(av) += key;
281         SvPVX(av) = (char*)AvALLOC(av);
282     }
283     AvFILL(av) = -1;
284 }
285
286 void
287 av_undef(av)
288 register AV *av;
289 {
290     register I32 key;
291
292     if (!av)
293         return;
294     /*SUPPRESS 560*/
295     if (AvREAL(av)) {
296         key = AvFILL(av) + 1;
297         while (key)
298             SvREFCNT_dec(AvARRAY(av)[--key]);
299     }
300     if (key = AvARRAY(av) - AvALLOC(av)) {
301         AvMAX(av) += key;
302         SvPVX(av) = (char*)AvALLOC(av);
303     }
304     Safefree(AvALLOC(av));
305     AvALLOC(av) = 0;
306     SvPVX(av) = 0;
307     AvMAX(av) = AvFILL(av) = -1;
308     if (AvARYLEN(av)) {
309         SvREFCNT_dec(AvARYLEN(av));
310         AvARYLEN(av) = 0;
311     }
312 }
313
314 void
315 av_push(av,val)
316 register AV *av;
317 SV *val;
318 {
319     if (!av)
320         return;
321     av_store(av,AvFILL(av)+1,val);
322 }
323
324 SV *
325 av_pop(av)
326 register AV *av;
327 {
328     SV *retval;
329
330     if (!av || AvFILL(av) < 0)
331         return &sv_undef;
332     retval = AvARRAY(av)[AvFILL(av)];
333     AvARRAY(av)[AvFILL(av)--] = &sv_undef;
334     if (SvSMAGICAL(av))
335         mg_set((SV*)av);
336     return retval;
337 }
338
339 void
340 av_unshift(av,num)
341 register AV *av;
342 register I32 num;
343 {
344     register I32 i;
345     register SV **sstr,**dstr;
346
347     if (!av || num <= 0)
348         return;
349     if (!AvREAL(av)) {
350         if (AvREIFY(av))
351             av_reify(av);
352         else
353             croak("Can't unshift");
354     }
355     i = AvARRAY(av) - AvALLOC(av);
356     if (i) {
357         if (i > num)
358             i = num;
359         num -= i;
360     
361         AvMAX(av) += i;
362         AvFILL(av) += i;
363         SvPVX(av) = (char*)(AvARRAY(av) - i);
364     }
365     if (num) {
366         av_extend(av,AvFILL(av)+num);
367         AvFILL(av) += num;
368         dstr = AvARRAY(av) + AvFILL(av);
369         sstr = dstr - num;
370 #ifdef BUGGY_MSC5
371  # pragma loop_opt(off) /* don't loop-optimize the following code */
372 #endif /* BUGGY_MSC5 */
373         for (i = AvFILL(av) - num; i >= 0; --i) {
374             *dstr-- = *sstr--;
375 #ifdef BUGGY_MSC5
376  # pragma loop_opt()    /* loop-optimization back to command-line setting */
377 #endif /* BUGGY_MSC5 */
378         }
379         while (num)
380             AvARRAY(av)[--num] = &sv_undef;
381     }
382 }
383
384 SV *
385 av_shift(av)
386 register AV *av;
387 {
388     SV *retval;
389
390     if (!av || AvFILL(av) < 0)
391         return &sv_undef;
392     retval = *AvARRAY(av);
393     if (AvREAL(av))
394         *AvARRAY(av) = &sv_undef;
395     SvPVX(av) = (char*)(AvARRAY(av) + 1);
396     AvMAX(av)--;
397     AvFILL(av)--;
398     if (SvSMAGICAL(av))
399         mg_set((SV*)av);
400     return retval;
401 }
402
403 I32
404 av_len(av)
405 register AV *av;
406 {
407     return AvFILL(av);
408 }
409
410 void
411 av_fill(av, fill)
412 register AV *av;
413 I32 fill;
414 {
415     if (!av)
416         croak("panic: null array");
417     if (fill < 0)
418         fill = -1;
419     if (fill <= AvMAX(av)) {
420         I32 key = AvFILL(av);
421         SV** ary = AvARRAY(av);
422
423         if (AvREAL(av)) {
424             while (key > fill) {
425                 SvREFCNT_dec(ary[key]);
426                 ary[key--] = &sv_undef;
427             }
428         }
429         else {
430             while (key < fill)
431                 ary[++key] = &sv_undef;
432         }
433             
434         AvFILL(av) = fill;
435         if (SvSMAGICAL(av))
436             mg_set((SV*)av);
437     }
438     else
439         (void)av_store(av,fill,&sv_undef);
440 }