This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
5.003_11 on UnixWare 2.1.1 - Only one small UnixWare buglet
[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 #ifndef STRANGE_MALLOC
68                 U32 bytes;
69 #endif
70
71                 newmax = key + AvMAX(av) / 5;
72               resize:
73 #ifdef STRANGE_MALLOC
74                 Renew(AvALLOC(av),newmax+1, SV*);
75 #else
76                 bytes = (newmax + 1) * sizeof(SV*);
77 #define MALLOC_OVERHEAD 16
78                 tmp = MALLOC_OVERHEAD;
79                 while (tmp - MALLOC_OVERHEAD < bytes)
80                     tmp += tmp;
81                 tmp -= MALLOC_OVERHEAD;
82                 tmp /= sizeof(SV*);
83                 assert(tmp > newmax);
84                 newmax = tmp - 1;
85                 New(2,ary, newmax+1, SV*);
86                 Copy(AvALLOC(av), ary, AvMAX(av)+1, SV*);
87                 if (AvMAX(av) > 64 && !nice_chunk) {
88                     nice_chunk = (char*)AvALLOC(av);
89                     nice_chunk_size = (AvMAX(av) + 1) * sizeof(SV*);
90                 }
91                 else
92                     Safefree(AvALLOC(av));
93                 AvALLOC(av) = ary;
94 #endif
95                 ary = AvALLOC(av) + AvMAX(av) + 1;
96                 tmp = newmax - AvMAX(av);
97                 if (av == curstack) {   /* Oops, grew stack (via av_store()?) */
98                     stack_sp = AvALLOC(av) + (stack_sp - stack_base);
99                     stack_base = AvALLOC(av);
100                     stack_max = stack_base + newmax;
101                 }
102             }
103             else {
104                 newmax = key < 4 ? 4 : key;
105                 New(2,AvALLOC(av), newmax+1, SV*);
106                 ary = AvALLOC(av) + 1;
107                 tmp = newmax;
108                 AvALLOC(av)[0] = &sv_undef;     /* For the stacks */
109             }
110             if (AvREAL(av)) {
111                 while (tmp)
112                     ary[--tmp] = &sv_undef;
113             }
114             
115             SvPVX(av) = (char*)AvALLOC(av);
116             AvMAX(av) = newmax;
117         }
118     }
119 }
120
121 SV**
122 av_fetch(av,key,lval)
123 register AV *av;
124 I32 key;
125 I32 lval;
126 {
127     SV *sv;
128
129     if (!av)
130         return 0;
131
132     if (SvRMAGICAL(av)) {
133         if (mg_find((SV*)av,'P')) {
134             sv = sv_newmortal();
135             mg_copy((SV*)av, sv, 0, key);
136             Sv = sv;
137             return &Sv;
138         }
139     }
140
141     if (key < 0) {
142         key += AvFILL(av) + 1;
143         if (key < 0)
144             return 0;
145     }
146     else if (key > AvFILL(av)) {
147         if (!lval)
148             return 0;
149         if (AvREALISH(av))
150             sv = NEWSV(5,0);
151         else
152             sv = sv_newmortal();
153         return av_store(av,key,sv);
154     }
155     if (AvARRAY(av)[key] == &sv_undef) {
156     emptyness:
157         if (lval) {
158             sv = NEWSV(6,0);
159             return av_store(av,key,sv);
160         }
161         return 0;
162     }
163     else if (AvREIFY(av)
164              && (!AvARRAY(av)[key]      /* eg. @_ could have freed elts */
165                  || SvTYPE(AvARRAY(av)[key]) == SVTYPEMASK)) {
166         AvARRAY(av)[key] = &sv_undef;   /* 1/2 reify */
167         goto emptyness;
168     }
169     return &AvARRAY(av)[key];
170 }
171
172 SV**
173 av_store(av,key,val)
174 register AV *av;
175 I32 key;
176 SV *val;
177 {
178     SV** ary;
179
180     if (!av)
181         return 0;
182     if (!val)
183         val = &sv_undef;
184
185     if (SvRMAGICAL(av)) {
186         if (mg_find((SV*)av,'P')) {
187             if (val != &sv_undef)
188                 mg_copy((SV*)av, val, 0, key);
189             return 0;
190         }
191     }
192
193     if (key < 0) {
194         key += AvFILL(av) + 1;
195         if (key < 0)
196             return 0;
197     }
198     if (SvREADONLY(av) && key >= AvFILL(av))
199         croak(no_modify);
200     if (key > AvMAX(av))
201         av_extend(av,key);
202     if (AvREIFY(av))
203         av_reify(av);
204
205     ary = AvARRAY(av);
206     if (AvFILL(av) < key) {
207         if (!AvREAL(av)) {
208             if (av == curstack && key > stack_sp - stack_base)
209                 stack_sp = stack_base + key;    /* XPUSH in disguise */
210             do
211                 ary[++AvFILL(av)] = &sv_undef;
212             while (AvFILL(av) < key);
213         }
214         AvFILL(av) = key;
215     }
216     else if (AvREAL(av))
217         SvREFCNT_dec(ary[key]);
218     ary[key] = val;
219     if (SvSMAGICAL(av)) {
220         if (val != &sv_undef) {
221             MAGIC* mg = SvMAGIC(av);
222             sv_magic(val, (SV*)av, toLOWER(mg->mg_type), 0, key);
223         }
224         mg_set((SV*)av);
225     }
226     return &ary[key];
227 }
228
229 AV *
230 newAV()
231 {
232     register AV *av;
233
234     av = (AV*)NEWSV(3,0);
235     sv_upgrade((SV *)av, SVt_PVAV);
236     AvREAL_on(av);
237     AvALLOC(av) = 0;
238     SvPVX(av) = 0;
239     AvMAX(av) = AvFILL(av) = -1;
240     return av;
241 }
242
243 AV *
244 av_make(size,strp)
245 register I32 size;
246 register SV **strp;
247 {
248     register AV *av;
249     register I32 i;
250     register SV** ary;
251
252     av = (AV*)NEWSV(8,0);
253     sv_upgrade((SV *) av,SVt_PVAV);
254     New(4,ary,size+1,SV*);
255     AvALLOC(av) = ary;
256     AvFLAGS(av) = AVf_REAL;
257     SvPVX(av) = (char*)ary;
258     AvFILL(av) = size - 1;
259     AvMAX(av) = size - 1;
260     for (i = 0; i < size; i++) {
261         assert (*strp);
262         ary[i] = NEWSV(7,0);
263         sv_setsv(ary[i], *strp);
264         strp++;
265     }
266     return av;
267 }
268
269 AV *
270 av_fake(size,strp)
271 register I32 size;
272 register SV **strp;
273 {
274     register AV *av;
275     register SV** ary;
276
277     av = (AV*)NEWSV(9,0);
278     sv_upgrade((SV *)av, SVt_PVAV);
279     New(4,ary,size+1,SV*);
280     AvALLOC(av) = ary;
281     Copy(strp,ary,size,SV*);
282     AvFLAGS(av) = AVf_REIFY;
283     SvPVX(av) = (char*)ary;
284     AvFILL(av) = size - 1;
285     AvMAX(av) = size - 1;
286     while (size--) {
287         assert (*strp);
288         SvTEMP_off(*strp);
289         strp++;
290     }
291     return av;
292 }
293
294 void
295 av_clear(av)
296 register AV *av;
297 {
298     register I32 key;
299     SV** ary;
300
301 #ifdef DEBUGGING
302     if (SvREFCNT(av) <= 0) {
303         warn("Attempt to clear deleted array");
304     }
305 #endif
306     if (!av || AvMAX(av) < 0)
307         return;
308     /*SUPPRESS 560*/
309
310     if (AvREAL(av)) {
311         ary = AvARRAY(av);
312         key = AvFILL(av) + 1;
313         while (key) {
314             SvREFCNT_dec(ary[--key]);
315             ary[key] = &sv_undef;
316         }
317     }
318     if (key = AvARRAY(av) - AvALLOC(av)) {
319         AvMAX(av) += key;
320         SvPVX(av) = (char*)AvALLOC(av);
321     }
322     AvFILL(av) = -1;
323 }
324
325 void
326 av_undef(av)
327 register AV *av;
328 {
329     register I32 key;
330
331     if (!av)
332         return;
333     /*SUPPRESS 560*/
334     if (AvREAL(av)) {
335         key = AvFILL(av) + 1;
336         while (key)
337             SvREFCNT_dec(AvARRAY(av)[--key]);
338     }
339     Safefree(AvALLOC(av));
340     AvALLOC(av) = 0;
341     SvPVX(av) = 0;
342     AvMAX(av) = AvFILL(av) = -1;
343     if (AvARYLEN(av)) {
344         SvREFCNT_dec(AvARYLEN(av));
345         AvARYLEN(av) = 0;
346     }
347 }
348
349 void
350 av_push(av,val)
351 register AV *av;
352 SV *val;
353 {
354     if (!av)
355         return;
356     av_store(av,AvFILL(av)+1,val);
357 }
358
359 SV *
360 av_pop(av)
361 register AV *av;
362 {
363     SV *retval;
364
365     if (!av || AvFILL(av) < 0)
366         return &sv_undef;
367     if (SvREADONLY(av))
368         croak(no_modify);
369     retval = AvARRAY(av)[AvFILL(av)];
370     AvARRAY(av)[AvFILL(av)--] = &sv_undef;
371     if (SvSMAGICAL(av))
372         mg_set((SV*)av);
373     return retval;
374 }
375
376 void
377 av_unshift(av,num)
378 register AV *av;
379 register I32 num;
380 {
381     register I32 i;
382     register SV **sstr,**dstr;
383
384     if (!av || num <= 0)
385         return;
386     if (SvREADONLY(av))
387         croak(no_modify);
388     if (!AvREAL(av)) {
389         if (AvREIFY(av))
390             av_reify(av);
391         else
392             croak("Can't unshift");
393     }
394     i = AvARRAY(av) - AvALLOC(av);
395     if (i) {
396         if (i > num)
397             i = num;
398         num -= i;
399     
400         AvMAX(av) += i;
401         AvFILL(av) += i;
402         SvPVX(av) = (char*)(AvARRAY(av) - i);
403     }
404     if (num) {
405         av_extend(av,AvFILL(av)+num);
406         AvFILL(av) += num;
407         dstr = AvARRAY(av) + AvFILL(av);
408         sstr = dstr - num;
409 #ifdef BUGGY_MSC5
410  # pragma loop_opt(off) /* don't loop-optimize the following code */
411 #endif /* BUGGY_MSC5 */
412         for (i = AvFILL(av) - num; i >= 0; --i) {
413             *dstr-- = *sstr--;
414 #ifdef BUGGY_MSC5
415  # pragma loop_opt()    /* loop-optimization back to command-line setting */
416 #endif /* BUGGY_MSC5 */
417         }
418         while (num)
419             AvARRAY(av)[--num] = &sv_undef;
420     }
421 }
422
423 SV *
424 av_shift(av)
425 register AV *av;
426 {
427     SV *retval;
428
429     if (!av || AvFILL(av) < 0)
430         return &sv_undef;
431     if (SvREADONLY(av))
432         croak(no_modify);
433     retval = *AvARRAY(av);
434     if (AvREAL(av))
435         *AvARRAY(av) = &sv_undef;
436     SvPVX(av) = (char*)(AvARRAY(av) + 1);
437     AvMAX(av)--;
438     AvFILL(av)--;
439     if (SvSMAGICAL(av))
440         mg_set((SV*)av);
441     return retval;
442 }
443
444 I32
445 av_len(av)
446 register AV *av;
447 {
448     return AvFILL(av);
449 }
450
451 void
452 av_fill(av, fill)
453 register AV *av;
454 I32 fill;
455 {
456     if (!av)
457         croak("panic: null array");
458     if (fill < 0)
459         fill = -1;
460     if (fill <= AvMAX(av)) {
461         I32 key = AvFILL(av);
462         SV** ary = AvARRAY(av);
463
464         if (AvREAL(av)) {
465             while (key > fill) {
466                 SvREFCNT_dec(ary[key]);
467                 ary[key--] = &sv_undef;
468             }
469         }
470         else {
471             while (key < fill)
472                 ary[++key] = &sv_undef;
473         }
474             
475         AvFILL(av) = fill;
476         if (SvSMAGICAL(av))
477             mg_set((SV*)av);
478     }
479     else
480         (void)av_store(av,fill,&sv_undef);
481 }