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