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