perl 4.0 patch 18: patch #11, continued
[p5sagit/p5-mst-13.2.git] / array.c
1 /* $RCSfile: array.c,v $$Revision: 4.0.1.2 $$Date: 91/11/05 16:00:14 $
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:        array.c,v $
9  * Revision 4.0.1.2  91/11/05  16:00:14  lwall
10  * patch11: random cleanup
11  * patch11: passing non-existend array elements to subrouting caused core dump
12  * 
13  * Revision 4.0.1.1  91/06/07  10:19:08  lwall
14  * patch4: new copyright notice
15  * 
16  * Revision 4.0  91/03/20  01:03:32  lwall
17  * 4.0 baseline.
18  * 
19  */
20
21 #include "EXTERN.h"
22 #include "perl.h"
23
24 STR *
25 afetch(ar,key,lval)
26 register ARRAY *ar;
27 int key;
28 int lval;
29 {
30     STR *str;
31
32     if (key < 0 || key > ar->ary_fill) {
33         if (lval && key >= 0) {
34             if (ar->ary_flags & ARF_REAL)
35                 str = Str_new(5,0);
36             else
37                 str = str_mortal(&str_undef);
38             (void)astore(ar,key,str);
39             return str;
40         }
41         else
42             return &str_undef;
43     }
44     if (!ar->ary_array[key]) {
45         if (lval) {
46             str = Str_new(6,0);
47             (void)astore(ar,key,str);
48             return str;
49         }
50         return &str_undef;
51     }
52     return ar->ary_array[key];
53 }
54
55 bool
56 astore(ar,key,val)
57 register ARRAY *ar;
58 int key;
59 STR *val;
60 {
61     int retval;
62
63     if (key < 0)
64         return FALSE;
65     if (key > ar->ary_max) {
66         int newmax;
67
68         if (ar->ary_alloc != ar->ary_array) {
69             retval = ar->ary_array - ar->ary_alloc;
70             Copy(ar->ary_array, ar->ary_alloc, ar->ary_max+1, STR*);
71             Zero(ar->ary_alloc+ar->ary_max+1, retval, STR*);
72             ar->ary_max += retval;
73             ar->ary_array -= retval;
74             if (key > ar->ary_max - 10) {
75                 newmax = key + ar->ary_max;
76                 goto resize;
77             }
78         }
79         else {
80             if (ar->ary_alloc) {
81                 newmax = key + ar->ary_max / 5;
82               resize:
83                 Renew(ar->ary_alloc,newmax+1, STR*);
84                 Zero(&ar->ary_alloc[ar->ary_max+1], newmax - ar->ary_max, STR*);
85             }
86             else {
87                 newmax = key < 4 ? 4 : key;
88                 Newz(2,ar->ary_alloc, newmax+1, STR*);
89             }
90             ar->ary_array = ar->ary_alloc;
91             ar->ary_max = newmax;
92         }
93     }
94     if (ar->ary_flags & ARF_REAL) {
95         if (ar->ary_fill < key) {
96             while (++ar->ary_fill < key) {
97                 if (ar->ary_array[ar->ary_fill] != Nullstr) {
98                     str_free(ar->ary_array[ar->ary_fill]);
99                     ar->ary_array[ar->ary_fill] = Nullstr;
100                 }
101             }
102         }
103         retval = (ar->ary_array[key] != Nullstr);
104         if (retval)
105             str_free(ar->ary_array[key]);
106     }
107     else
108         retval = 0;
109     ar->ary_array[key] = val;
110     return retval;
111 }
112
113 ARRAY *
114 anew(stab)
115 STAB *stab;
116 {
117     register ARRAY *ar;
118
119     New(1,ar,1,ARRAY);
120     ar->ary_magic = Str_new(7,0);
121     ar->ary_alloc = ar->ary_array = 0;
122     str_magic(ar->ary_magic, stab, '#', Nullch, 0);
123     ar->ary_max = ar->ary_fill = -1;
124     ar->ary_flags = ARF_REAL;
125     return ar;
126 }
127
128 ARRAY *
129 afake(stab,size,strp)
130 STAB *stab;
131 register int size;
132 register STR **strp;
133 {
134     register ARRAY *ar;
135
136     New(3,ar,1,ARRAY);
137     New(4,ar->ary_alloc,size+1,STR*);
138     Copy(strp,ar->ary_alloc,size,STR*);
139     ar->ary_array = ar->ary_alloc;
140     ar->ary_magic = Str_new(8,0);
141     str_magic(ar->ary_magic, stab, '#', Nullch, 0);
142     ar->ary_fill = size - 1;
143     ar->ary_max = size - 1;
144     ar->ary_flags = 0;
145     while (size--) {
146         if (*strp)
147             (*strp)->str_pok &= ~SP_TEMP;
148         strp++;
149     }
150     return ar;
151 }
152
153 void
154 aclear(ar)
155 register ARRAY *ar;
156 {
157     register int key;
158
159     if (!ar || !(ar->ary_flags & ARF_REAL) || ar->ary_max < 0)
160         return;
161     /*SUPPRESS 560*/
162     if (key = ar->ary_array - ar->ary_alloc) {
163         ar->ary_max += key;
164         ar->ary_array -= key;
165     }
166     for (key = 0; key <= ar->ary_max; key++)
167         str_free(ar->ary_array[key]);
168     ar->ary_fill = -1;
169     Zero(ar->ary_array, ar->ary_max+1, STR*);
170 }
171
172 void
173 afree(ar)
174 register ARRAY *ar;
175 {
176     register int key;
177
178     if (!ar)
179         return;
180     /*SUPPRESS 560*/
181     if (key = ar->ary_array - ar->ary_alloc) {
182         ar->ary_max += key;
183         ar->ary_array -= key;
184     }
185     if (ar->ary_flags & ARF_REAL) {
186         for (key = 0; key <= ar->ary_max; key++)
187             str_free(ar->ary_array[key]);
188     }
189     str_free(ar->ary_magic);
190     Safefree(ar->ary_alloc);
191     Safefree(ar);
192 }
193
194 bool
195 apush(ar,val)
196 register ARRAY *ar;
197 STR *val;
198 {
199     return astore(ar,++(ar->ary_fill),val);
200 }
201
202 STR *
203 apop(ar)
204 register ARRAY *ar;
205 {
206     STR *retval;
207
208     if (ar->ary_fill < 0)
209         return Nullstr;
210     retval = ar->ary_array[ar->ary_fill];
211     ar->ary_array[ar->ary_fill--] = Nullstr;
212     return retval;
213 }
214
215 aunshift(ar,num)
216 register ARRAY *ar;
217 register int num;
218 {
219     register int i;
220     register STR **sstr,**dstr;
221
222     if (num <= 0)
223         return;
224     if (ar->ary_array - ar->ary_alloc >= num) {
225         ar->ary_max += num;
226         ar->ary_fill += num;
227         while (num--)
228             *--ar->ary_array = Nullstr;
229     }
230     else {
231         (void)astore(ar,ar->ary_fill+num,(STR*)0);      /* maybe extend array */
232         dstr = ar->ary_array + ar->ary_fill;
233         sstr = dstr - num;
234 #ifdef BUGGY_MSC5
235  # pragma loop_opt(off) /* don't loop-optimize the following code */
236 #endif /* BUGGY_MSC5 */
237         for (i = ar->ary_fill - num; i >= 0; i--) {
238             *dstr-- = *sstr--;
239 #ifdef BUGGY_MSC5
240  # pragma loop_opt()    /* loop-optimization back to command-line setting */
241 #endif /* BUGGY_MSC5 */
242         }
243         Zero(ar->ary_array, num, STR*);
244     }
245 }
246
247 STR *
248 ashift(ar)
249 register ARRAY *ar;
250 {
251     STR *retval;
252
253     if (ar->ary_fill < 0)
254         return Nullstr;
255     retval = *ar->ary_array;
256     *(ar->ary_array++) = Nullstr;
257     ar->ary_max--;
258     ar->ary_fill--;
259     return retval;
260 }
261
262 int
263 alen(ar)
264 register ARRAY *ar;
265 {
266     return ar->ary_fill;
267 }
268
269 afill(ar, fill)
270 register ARRAY *ar;
271 int fill;
272 {
273     if (fill < 0)
274         fill = -1;
275     if (fill <= ar->ary_max)
276         ar->ary_fill = fill;
277     else
278         (void)astore(ar,fill,Nullstr);
279 }