This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
This is my patch patch.1k for perl5.001.
[perl5.git] / av.c
CommitLineData
a0d0e21e 1/* av.c
79072805 2 *
a0d0e21e 3 * Copyright (c) 1991-1994, Larry Wall
79072805
LW
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 *
a0d0e21e
LW
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
79072805
LW
13 */
14
15#include "EXTERN.h"
16#include "perl.h"
17
a0d0e21e
LW
18static void av_reify _((AV* av));
19
20static void
21av_reify(av)
22AV* 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
39void
40av_extend(av,key)
41AV *av;
42I32 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
79072805 96SV**
463ee0b2
LW
97av_fetch(av,key,lval)
98register AV *av;
79072805
LW
99I32 key;
100I32 lval;
101{
102 SV *sv;
103
a0d0e21e
LW
104 if (!av)
105 return 0;
106
8990e307 107 if (SvRMAGICAL(av)) {
463ee0b2 108 if (mg_find((SV*)av,'P')) {
8990e307 109 sv = sv_newmortal();
463ee0b2 110 mg_copy((SV*)av, sv, 0, key);
463ee0b2
LW
111 Sv = sv;
112 return &Sv;
113 }
114 }
115
a0d0e21e
LW
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);
79072805 129 }
a0d0e21e 130 if (AvARRAY(av)[key] == &sv_undef) {
79072805
LW
131 if (lval) {
132 sv = NEWSV(6,0);
463ee0b2 133 return av_store(av,key,sv);
79072805
LW
134 }
135 return 0;
136 }
463ee0b2 137 return &AvARRAY(av)[key];
79072805
LW
138}
139
140SV**
463ee0b2
LW
141av_store(av,key,val)
142register AV *av;
79072805
LW
143I32 key;
144SV *val;
145{
79072805
LW
146 SV** ary;
147
a0d0e21e
LW
148 if (!av)
149 return 0;
463ee0b2 150
8990e307 151 if (SvRMAGICAL(av)) {
463ee0b2
LW
152 if (mg_find((SV*)av,'P')) {
153 mg_copy((SV*)av, val, 0, key);
154 return 0;
155 }
156 }
157
a0d0e21e
LW
158 if (key < 0) {
159 key += AvFILL(av) + 1;
160 if (key < 0)
161 return 0;
79072805 162 }
a0d0e21e
LW
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
463ee0b2 171 ary = AvARRAY(av);
a0d0e21e
LW
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);
79072805 179 }
a0d0e21e 180 AvFILL(av) = key;
79072805 181 }
a0d0e21e
LW
182 else if (AvREAL(av))
183 SvREFCNT_dec(ary[key]);
79072805 184 ary[key] = val;
8990e307 185 if (SvSMAGICAL(av)) {
a0d0e21e
LW
186 if (val != &sv_undef) {
187 MAGIC* mg = SvMAGIC(av);
188 sv_magic(val, (SV*)av, toLOWER(mg->mg_type), 0, key);
189 }
463ee0b2
LW
190 mg_set((SV*)av);
191 }
79072805
LW
192 return &ary[key];
193}
194
195AV *
196newAV()
197{
463ee0b2 198 register AV *av;
79072805 199
a0d0e21e
LW
200 av = (AV*)NEWSV(3,0);
201 sv_upgrade((SV *)av, SVt_PVAV);
463ee0b2
LW
202 AvREAL_on(av);
203 AvALLOC(av) = 0;
204 SvPVX(av) = 0;
205 AvMAX(av) = AvFILL(av) = -1;
206 return av;
79072805
LW
207}
208
209AV *
210av_make(size,strp)
211register I32 size;
212register SV **strp;
213{
463ee0b2 214 register AV *av;
79072805
LW
215 register I32 i;
216 register SV** ary;
217
a0d0e21e
LW
218 av = (AV*)NEWSV(8,0);
219 sv_upgrade((SV *) av,SVt_PVAV);
79072805 220 New(4,ary,size+1,SV*);
463ee0b2 221 AvALLOC(av) = ary;
a0d0e21e 222 AvFLAGS(av) = AVf_REAL;
463ee0b2
LW
223 SvPVX(av) = (char*)ary;
224 AvFILL(av) = size - 1;
225 AvMAX(av) = size - 1;
79072805 226 for (i = 0; i < size; i++) {
a0d0e21e
LW
227 assert (*strp);
228 ary[i] = NEWSV(7,0);
229 sv_setsv(ary[i], *strp);
79072805
LW
230 strp++;
231 }
463ee0b2 232 return av;
79072805
LW
233}
234
235AV *
236av_fake(size,strp)
237register I32 size;
238register SV **strp;
239{
463ee0b2 240 register AV *av;
79072805
LW
241 register SV** ary;
242
a0d0e21e
LW
243 av = (AV*)NEWSV(9,0);
244 sv_upgrade((SV *)av, SVt_PVAV);
79072805 245 New(4,ary,size+1,SV*);
463ee0b2 246 AvALLOC(av) = ary;
79072805 247 Copy(strp,ary,size,SV*);
a0d0e21e 248 AvFLAGS(av) = AVf_REIFY;
463ee0b2
LW
249 SvPVX(av) = (char*)ary;
250 AvFILL(av) = size - 1;
251 AvMAX(av) = size - 1;
79072805 252 while (size--) {
a0d0e21e
LW
253 assert (*strp);
254 SvTEMP_off(*strp);
79072805
LW
255 strp++;
256 }
463ee0b2 257 return av;
79072805
LW
258}
259
260void
463ee0b2
LW
261av_clear(av)
262register AV *av;
79072805
LW
263{
264 register I32 key;
a0d0e21e 265 SV** ary;
79072805 266
a0d0e21e 267 if (!av || AvMAX(av) < 0)
79072805
LW
268 return;
269 /*SUPPRESS 560*/
a0d0e21e
LW
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 }
463ee0b2
LW
279 if (key = AvARRAY(av) - AvALLOC(av)) {
280 AvMAX(av) += key;
a0d0e21e 281 SvPVX(av) = (char*)AvALLOC(av);
79072805 282 }
463ee0b2 283 AvFILL(av) = -1;
79072805
LW
284}
285
286void
463ee0b2
LW
287av_undef(av)
288register AV *av;
79072805
LW
289{
290 register I32 key;
291
463ee0b2 292 if (!av)
79072805
LW
293 return;
294 /*SUPPRESS 560*/
a0d0e21e
LW
295 if (AvREAL(av)) {
296 key = AvFILL(av) + 1;
297 while (key)
298 SvREFCNT_dec(AvARRAY(av)[--key]);
299 }
463ee0b2
LW
300 if (key = AvARRAY(av) - AvALLOC(av)) {
301 AvMAX(av) += key;
a0d0e21e 302 SvPVX(av) = (char*)AvALLOC(av);
79072805 303 }
463ee0b2
LW
304 Safefree(AvALLOC(av));
305 AvALLOC(av) = 0;
306 SvPVX(av) = 0;
307 AvMAX(av) = AvFILL(av) = -1;
748a9306
LW
308 if (AvARYLEN(av)) {
309 SvREFCNT_dec(AvARYLEN(av));
310 AvARYLEN(av) = 0;
311 }
79072805
LW
312}
313
a0d0e21e 314void
463ee0b2
LW
315av_push(av,val)
316register AV *av;
79072805
LW
317SV *val;
318{
a0d0e21e
LW
319 if (!av)
320 return;
321 av_store(av,AvFILL(av)+1,val);
79072805
LW
322}
323
324SV *
463ee0b2
LW
325av_pop(av)
326register AV *av;
79072805
LW
327{
328 SV *retval;
329
a0d0e21e
LW
330 if (!av || AvFILL(av) < 0)
331 return &sv_undef;
463ee0b2 332 retval = AvARRAY(av)[AvFILL(av)];
a0d0e21e 333 AvARRAY(av)[AvFILL(av)--] = &sv_undef;
8990e307 334 if (SvSMAGICAL(av))
463ee0b2 335 mg_set((SV*)av);
79072805
LW
336 return retval;
337}
338
339void
463ee0b2
LW
340av_unshift(av,num)
341register AV *av;
79072805
LW
342register I32 num;
343{
344 register I32 i;
345 register SV **sstr,**dstr;
346
a0d0e21e 347 if (!av || num <= 0)
79072805 348 return;
a0d0e21e
LW
349 if (!AvREAL(av)) {
350 if (AvREIFY(av))
351 av_reify(av);
352 else
353 croak("Can't unshift");
79072805 354 }
a0d0e21e
LW
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;
463ee0b2 368 dstr = AvARRAY(av) + AvFILL(av);
79072805
LW
369 sstr = dstr - num;
370#ifdef BUGGY_MSC5
371 # pragma loop_opt(off) /* don't loop-optimize the following code */
372#endif /* BUGGY_MSC5 */
a0d0e21e 373 for (i = AvFILL(av) - num; i >= 0; --i) {
79072805
LW
374 *dstr-- = *sstr--;
375#ifdef BUGGY_MSC5
376 # pragma loop_opt() /* loop-optimization back to command-line setting */
377#endif /* BUGGY_MSC5 */
378 }
a0d0e21e
LW
379 while (num)
380 AvARRAY(av)[--num] = &sv_undef;
79072805
LW
381 }
382}
383
384SV *
463ee0b2
LW
385av_shift(av)
386register AV *av;
79072805
LW
387{
388 SV *retval;
389
a0d0e21e
LW
390 if (!av || AvFILL(av) < 0)
391 return &sv_undef;
463ee0b2 392 retval = *AvARRAY(av);
a0d0e21e
LW
393 if (AvREAL(av))
394 *AvARRAY(av) = &sv_undef;
463ee0b2
LW
395 SvPVX(av) = (char*)(AvARRAY(av) + 1);
396 AvMAX(av)--;
397 AvFILL(av)--;
8990e307 398 if (SvSMAGICAL(av))
463ee0b2 399 mg_set((SV*)av);
79072805
LW
400 return retval;
401}
402
403I32
463ee0b2
LW
404av_len(av)
405register AV *av;
79072805 406{
463ee0b2 407 return AvFILL(av);
79072805
LW
408}
409
410void
463ee0b2
LW
411av_fill(av, fill)
412register AV *av;
79072805
LW
413I32 fill;
414{
a0d0e21e
LW
415 if (!av)
416 croak("panic: null array");
79072805
LW
417 if (fill < 0)
418 fill = -1;
463ee0b2 419 if (fill <= AvMAX(av)) {
a0d0e21e
LW
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
463ee0b2 434 AvFILL(av) = fill;
8990e307 435 if (SvSMAGICAL(av))
463ee0b2
LW
436 mg_set((SV*)av);
437 }
a0d0e21e
LW
438 else
439 (void)av_store(av,fill,&sv_undef);
79072805 440}