[fix crash in regexec.c]
[p5sagit/p5-mst-13.2.git] / av.c
CommitLineData
a0d0e21e 1/* av.c
79072805 2 *
a0d0e21e 3 * Copyright (c) 1991-1994, Larry Wall
79072805 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 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 13 */
14
15#include "EXTERN.h"
16#include "perl.h"
17
a0d0e21e 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 97av_fetch(av,key,lval)
98register AV *av;
79072805 99I32 key;
100I32 lval;
101{
102 SV *sv;
103
a0d0e21e 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 111 Sv = sv;
112 return &Sv;
113 }
114 }
115
a0d0e21e 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 131 if (lval) {
132 sv = NEWSV(6,0);
463ee0b2 133 return av_store(av,key,sv);
79072805 134 }
135 return 0;
136 }
463ee0b2 137 return &AvARRAY(av)[key];
79072805 138}
139
140SV**
463ee0b2 141av_store(av,key,val)
142register AV *av;
79072805 143I32 key;
144SV *val;
145{
79072805 146 SV** ary;
147
a0d0e21e 148 if (!av)
149 return 0;
463ee0b2 150
8990e307 151 if (SvRMAGICAL(av)) {
463ee0b2 152 if (mg_find((SV*)av,'P')) {
153 mg_copy((SV*)av, val, 0, key);
154 return 0;
155 }
156 }
157
a0d0e21e 158 if (key < 0) {
159 key += AvFILL(av) + 1;
160 if (key < 0)
161 return 0;
79072805 162 }
a0d0e21e 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 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 182 else if (AvREAL(av))
183 SvREFCNT_dec(ary[key]);
79072805 184 ary[key] = val;
8990e307 185 if (SvSMAGICAL(av)) {
a0d0e21e 186 if (val != &sv_undef) {
187 MAGIC* mg = SvMAGIC(av);
188 sv_magic(val, (SV*)av, toLOWER(mg->mg_type), 0, key);
189 }
463ee0b2 190 mg_set((SV*)av);
191 }
79072805 192 return &ary[key];
193}
194
195AV *
196newAV()
197{
463ee0b2 198 register AV *av;
79072805 199
a0d0e21e 200 av = (AV*)NEWSV(3,0);
201 sv_upgrade((SV *)av, SVt_PVAV);
463ee0b2 202 AvREAL_on(av);
203 AvALLOC(av) = 0;
204 SvPVX(av) = 0;
205 AvMAX(av) = AvFILL(av) = -1;
206 return av;
79072805 207}
208
209AV *
210av_make(size,strp)
211register I32 size;
212register SV **strp;
213{
463ee0b2 214 register AV *av;
79072805 215 register I32 i;
216 register SV** ary;
217
a0d0e21e 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 223 SvPVX(av) = (char*)ary;
224 AvFILL(av) = size - 1;
225 AvMAX(av) = size - 1;
79072805 226 for (i = 0; i < size; i++) {
a0d0e21e 227 assert (*strp);
228 ary[i] = NEWSV(7,0);
229 sv_setsv(ary[i], *strp);
79072805 230 strp++;
231 }
463ee0b2 232 return av;
79072805 233}
234
235AV *
236av_fake(size,strp)
237register I32 size;
238register SV **strp;
239{
463ee0b2 240 register AV *av;
79072805 241 register SV** ary;
242
a0d0e21e 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 249 SvPVX(av) = (char*)ary;
250 AvFILL(av) = size - 1;
251 AvMAX(av) = size - 1;
79072805 252 while (size--) {
a0d0e21e 253 assert (*strp);
254 SvTEMP_off(*strp);
79072805 255 strp++;
256 }
463ee0b2 257 return av;
79072805 258}
259
260void
463ee0b2 261av_clear(av)
262register AV *av;
79072805 263{
264 register I32 key;
a0d0e21e 265 SV** ary;
79072805 266
a0d0e21e 267 if (!av || AvMAX(av) < 0)
79072805 268 return;
269 /*SUPPRESS 560*/
a0d0e21e 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 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 284}
285
286void
463ee0b2 287av_undef(av)
288register AV *av;
79072805 289{
290 register I32 key;
291
463ee0b2 292 if (!av)
79072805 293 return;
294 /*SUPPRESS 560*/
a0d0e21e 295 if (AvREAL(av)) {
296 key = AvFILL(av) + 1;
297 while (key)
298 SvREFCNT_dec(AvARRAY(av)[--key]);
299 }
463ee0b2 300 if (key = AvARRAY(av) - AvALLOC(av)) {
301 AvMAX(av) += key;
a0d0e21e 302 SvPVX(av) = (char*)AvALLOC(av);
79072805 303 }
463ee0b2 304 Safefree(AvALLOC(av));
305 AvALLOC(av) = 0;
306 SvPVX(av) = 0;
307 AvMAX(av) = AvFILL(av) = -1;
79072805 308}
309
a0d0e21e 310void
463ee0b2 311av_push(av,val)
312register AV *av;
79072805 313SV *val;
314{
a0d0e21e 315 if (!av)
316 return;
317 av_store(av,AvFILL(av)+1,val);
79072805 318}
319
320SV *
463ee0b2 321av_pop(av)
322register AV *av;
79072805 323{
324 SV *retval;
325
a0d0e21e 326 if (!av || AvFILL(av) < 0)
327 return &sv_undef;
463ee0b2 328 retval = AvARRAY(av)[AvFILL(av)];
a0d0e21e 329 AvARRAY(av)[AvFILL(av)--] = &sv_undef;
8990e307 330 if (SvSMAGICAL(av))
463ee0b2 331 mg_set((SV*)av);
79072805 332 return retval;
333}
334
335void
463ee0b2 336av_unshift(av,num)
337register AV *av;
79072805 338register I32 num;
339{
340 register I32 i;
341 register SV **sstr,**dstr;
342
a0d0e21e 343 if (!av || num <= 0)
79072805 344 return;
a0d0e21e 345 if (!AvREAL(av)) {
346 if (AvREIFY(av))
347 av_reify(av);
348 else
349 croak("Can't unshift");
79072805 350 }
a0d0e21e 351 i = AvARRAY(av) - AvALLOC(av);
352 if (i) {
353 if (i > num)
354 i = num;
355 num -= i;
356
357 AvMAX(av) += i;
358 AvFILL(av) += i;
359 SvPVX(av) = (char*)(AvARRAY(av) - i);
360 }
361 if (num) {
362 av_extend(av,AvFILL(av)+num);
363 AvFILL(av) += num;
463ee0b2 364 dstr = AvARRAY(av) + AvFILL(av);
79072805 365 sstr = dstr - num;
366#ifdef BUGGY_MSC5
367 # pragma loop_opt(off) /* don't loop-optimize the following code */
368#endif /* BUGGY_MSC5 */
a0d0e21e 369 for (i = AvFILL(av) - num; i >= 0; --i) {
79072805 370 *dstr-- = *sstr--;
371#ifdef BUGGY_MSC5
372 # pragma loop_opt() /* loop-optimization back to command-line setting */
373#endif /* BUGGY_MSC5 */
374 }
a0d0e21e 375 while (num)
376 AvARRAY(av)[--num] = &sv_undef;
79072805 377 }
378}
379
380SV *
463ee0b2 381av_shift(av)
382register AV *av;
79072805 383{
384 SV *retval;
385
a0d0e21e 386 if (!av || AvFILL(av) < 0)
387 return &sv_undef;
463ee0b2 388 retval = *AvARRAY(av);
a0d0e21e 389 if (AvREAL(av))
390 *AvARRAY(av) = &sv_undef;
463ee0b2 391 SvPVX(av) = (char*)(AvARRAY(av) + 1);
392 AvMAX(av)--;
393 AvFILL(av)--;
8990e307 394 if (SvSMAGICAL(av))
463ee0b2 395 mg_set((SV*)av);
79072805 396 return retval;
397}
398
399I32
463ee0b2 400av_len(av)
401register AV *av;
79072805 402{
463ee0b2 403 return AvFILL(av);
79072805 404}
405
406void
463ee0b2 407av_fill(av, fill)
408register AV *av;
79072805 409I32 fill;
410{
a0d0e21e 411 if (!av)
412 croak("panic: null array");
79072805 413 if (fill < 0)
414 fill = -1;
463ee0b2 415 if (fill <= AvMAX(av)) {
a0d0e21e 416 I32 key = AvFILL(av);
417 SV** ary = AvARRAY(av);
418
419 if (AvREAL(av)) {
420 while (key > fill) {
421 SvREFCNT_dec(ary[key]);
422 ary[key--] = &sv_undef;
423 }
424 }
425 else {
426 while (key < fill)
427 ary[++key] = &sv_undef;
428 }
429
463ee0b2 430 AvFILL(av) = fill;
8990e307 431 if (SvSMAGICAL(av))
463ee0b2 432 mg_set((SV*)av);
433 }
a0d0e21e 434 else
435 (void)av_store(av,fill,&sv_undef);
79072805 436}