2 do_splice(ary,gimme,arglast)
7 register STR **st = stack->ary_array;
8 register int sp = arglast[1];
9 int max = arglast[2] + 1;
21 offset = (int)str_gnum(st[sp]);
23 offset += ary->ary_fill + 1;
27 length = (int)str_gnum(st[sp++]);
32 length = ary->ary_max + 1; /* close enough to infinity */
36 length = ary->ary_max + 1;
44 if (offset > ary->ary_fill + 1)
45 offset = ary->ary_fill + 1;
46 after = ary->ary_fill + 1 - (offset + length);
47 if (after < 0) { /* not that much array */
48 length += after; /* offset+length now in array */
50 if (!ary->ary_alloc) {
56 /* At this point, sp .. max-1 is our new LIST */
59 diff = newlen - length;
61 if (diff < 0) { /* shrinking the area */
63 New(451, tmparyval, newlen, STR*); /* so remember insertion */
64 Copy(st+sp, tmparyval, newlen, STR*);
68 if (gimme == G_ARRAY) { /* copy return vals to stack */
69 if (sp + length >= stack->ary_max) {
70 astore(stack,sp + length, Nullstr);
71 st = stack->ary_array;
73 Copy(ary->ary_array+offset, st+sp, length, STR*);
74 if (ary->ary_flags & ARF_REAL) {
75 for (i = length, dst = st+sp; i; i--)
76 str_2mortal(*dst++); /* free them eventualy */
81 st[sp] = ary->ary_array[offset+length-1];
82 if (ary->ary_flags & ARF_REAL) {
84 for (i = length - 1, dst = &ary->ary_array[offset]; i > 0; i--)
85 str_free(*dst++); /* free them now */
88 ary->ary_fill += diff;
90 /* pull up or down? */
92 if (offset < after) { /* easier to pull up */
93 if (offset) { /* esp. if nothing to pull */
94 src = &ary->ary_array[offset-1];
95 dst = src - diff; /* diff is negative */
96 for (i = offset; i > 0; i--) /* can't trust Copy */
99 Zero(ary->ary_array, -diff, STR*);
100 ary->ary_array -= diff; /* diff is negative */
101 ary->ary_max += diff;
104 if (after) { /* anything to pull down? */
105 src = ary->ary_array + offset + length;
106 dst = src + diff; /* diff is negative */
107 Move(src, dst, after, STR*);
109 Zero(&ary->ary_array[ary->ary_fill+1], -diff, STR*);
110 /* avoid later double free */
113 for (src = tmparyval, dst = ary->ary_array + offset;
115 *dst = Str_new(46,0);
116 str_sset(*dst++,*src++);
121 else { /* no, expanding (or same) */
123 New(452, tmparyval, length, STR*); /* so remember deletion */
124 Copy(ary->ary_array+offset, tmparyval, length, STR*);
127 if (diff > 0) { /* expanding */
129 /* push up or down? */
131 if (offset < after && diff <= ary->ary_array - ary->ary_alloc) {
133 src = ary->ary_array;
135 Move(src, dst, offset, STR*);
137 ary->ary_array -= diff; /* diff is positive */
138 ary->ary_max += diff;
139 ary->ary_fill += diff;
142 if (ary->ary_fill + diff >= ary->ary_max) /* oh, well */
143 astore(ary, ary->ary_fill + diff, Nullstr);
145 ary->ary_fill += diff;
146 dst = ary->ary_array + ary->ary_fill;
147 for (i = diff; i > 0; i--) {
148 if (*dst) /* TARG was hanging around */
149 str_free(*dst); /* after $#foo */
153 dst = ary->ary_array + ary->ary_fill;
155 for (i = after; i; i--) {
162 for (src = st+sp, dst = ary->ary_array + offset; newlen; newlen--) {
163 *dst = Str_new(46,0);
164 str_sset(*dst++,*src++);
167 if (gimme == G_ARRAY) { /* copy return vals to stack */
169 Copy(tmparyval, st+sp, length, STR*);
170 if (ary->ary_flags & ARF_REAL) {
171 for (i = length, dst = st+sp; i; i--)
172 str_2mortal(*dst++); /* free them eventualy */
179 st[sp] = tmparyval[length];
180 if (ary->ary_flags & ARF_REAL) {
183 str_free(tmparyval[length]);