perl 5.0 alpha 3
[p5sagit/p5-mst-13.2.git] / do / split
CommitLineData
79072805 1int
2do_split(TARG,spat,limit,gimme,arglast)
3STR *TARG;
4register SPAT *spat;
5register int limit;
6int gimme;
7int *arglast;
8{
9 register ARRAY *ary = stack;
10 STR **st = ary->ary_array;
11 register int sp = arglast[0] + 1;
12 register char *s = str_get(st[sp]);
13 char *strend = s + st[sp--]->str_cur;
14 register STR *dstr;
15 register char *m;
16 int iters = 0;
17 int maxiters = (strend - s) + 10;
18 int i;
19 char *orig;
20 int origlimit = limit;
21 int realarray = 0;
22
23 if (!spat || !s)
24 fatal("panic: do_split");
25 else if (spat->spat_runtime) {
26 nointrp = "|)";
27 sp = eval(spat->spat_runtime,G_SCALAR,sp);
28 st = stack->ary_array;
29 m = str_get(dstr = st[sp--]);
30 nointrp = "";
31 if (*m == ' ' && dstr->str_cur == 1) {
32 str_set(dstr,"\\s+");
33 m = dstr->str_ptr;
34 spat->spat_flags |= SPAT_SKIPWHITE;
35 }
36 if (spat->spat_regexp) {
37 regfree(spat->spat_regexp);
38 spat->spat_regexp = Null(REGEXP*); /* avoid possible double free */
39 }
40 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
41 spat->spat_flags & SPAT_FOLD);
42 if (spat->spat_flags & SPAT_KEEP ||
43 (spat->spat_runtime->arg_type == O_ITEM &&
44 (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
45 arg_free(spat->spat_runtime); /* it won't change, so */
46 spat->spat_runtime = Nullarg; /* no point compiling again */
47 }
48 }
49#ifdef DEBUGGING
50 if (debug & 8) {
51 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
52 }
53#endif
54 ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
55 if (ary && (gimme != G_ARRAY || (spat->spat_flags & SPAT_ONCE))) {
56 realarray = 1;
57 if (!(ary->ary_flags & ARF_REAL)) {
58 ary->ary_flags |= ARF_REAL;
59 for (i = ary->ary_fill; i >= 0; i--)
60 ary->ary_array[i] = Nullstr; /* don't free mere refs */
61 }
62 ary->ary_fill = -1;
63 sp = -1; /* temporarily switch stacks */
64 }
65 else
66 ary = stack;
67 orig = s;
68 if (spat->spat_flags & SPAT_SKIPWHITE) {
69 while (isSPACE(*s))
70 s++;
71 }
72 if (!limit)
73 limit = maxiters + 2;
74 if (strEQ("\\s+",spat->spat_regexp->precomp)) {
75 while (--limit) {
76 /*SUPPRESS 530*/
77 for (m = s; m < strend && !isSPACE(*m); m++) ;
78 if (m >= strend)
79 break;
80 dstr = Str_new(30,m-s);
81 str_nset(dstr,s,m-s);
82 if (!realarray)
83 str_2mortal(dstr);
84 (void)astore(ary, ++sp, dstr);
85 /*SUPPRESS 530*/
86 for (s = m + 1; s < strend && isSPACE(*s); s++) ;
87 }
88 }
89 else if (strEQ("^",spat->spat_regexp->precomp)) {
90 while (--limit) {
91 /*SUPPRESS 530*/
92 for (m = s; m < strend && *m != '\n'; m++) ;
93 m++;
94 if (m >= strend)
95 break;
96 dstr = Str_new(30,m-s);
97 str_nset(dstr,s,m-s);
98 if (!realarray)
99 str_2mortal(dstr);
100 (void)astore(ary, ++sp, dstr);
101 s = m;
102 }
103 }
104 else if (spat->spat_short) {
105 i = spat->spat_short->str_cur;
106 if (i == 1) {
107 int fold = (spat->spat_flags & SPAT_FOLD);
108
109 i = *spat->spat_short->str_ptr;
110 if (fold && isUPPER(i))
111 i = tolower(i);
112 while (--limit) {
113 if (fold) {
114 for ( m = s;
115 m < strend && *m != i &&
116 (!isUPPER(*m) || tolower(*m) != i);
117 m++) /*SUPPRESS 530*/
118 ;
119 }
120 else /*SUPPRESS 530*/
121 for (m = s; m < strend && *m != i; m++) ;
122 if (m >= strend)
123 break;
124 dstr = Str_new(30,m-s);
125 str_nset(dstr,s,m-s);
126 if (!realarray)
127 str_2mortal(dstr);
128 (void)astore(ary, ++sp, dstr);
129 s = m + 1;
130 }
131 }
132 else {
133#ifndef lint
134 while (s < strend && --limit &&
135 (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
136 spat->spat_short)) )
137#endif
138 {
139 dstr = Str_new(31,m-s);
140 str_nset(dstr,s,m-s);
141 if (!realarray)
142 str_2mortal(dstr);
143 (void)astore(ary, ++sp, dstr);
144 s = m + i;
145 }
146 }
147 }
148 else {
149 maxiters += (strend - s) * spat->spat_regexp->nparens;
150 while (s < strend && --limit &&
151 regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
152 if (spat->spat_regexp->subbase
153 && spat->spat_regexp->subbase != orig) {
154 m = s;
155 s = orig;
156 orig = spat->spat_regexp->subbase;
157 s = orig + (m - s);
158 strend = s + (strend - m);
159 }
160 m = spat->spat_regexp->startp[0];
161 dstr = Str_new(32,m-s);
162 str_nset(dstr,s,m-s);
163 if (!realarray)
164 str_2mortal(dstr);
165 (void)astore(ary, ++sp, dstr);
166 if (spat->spat_regexp->nparens) {
167 for (i = 1; i <= spat->spat_regexp->nparens; i++) {
168 s = spat->spat_regexp->startp[i];
169 m = spat->spat_regexp->endp[i];
170 dstr = Str_new(33,m-s);
171 str_nset(dstr,s,m-s);
172 if (!realarray)
173 str_2mortal(dstr);
174 (void)astore(ary, ++sp, dstr);
175 }
176 }
177 s = spat->spat_regexp->endp[0];
178 }
179 }
180 if (realarray)
181 iters = sp + 1;
182 else
183 iters = sp - arglast[0];
184 if (iters > maxiters)
185 fatal("Split loop");
186 if (s < strend || origlimit) { /* keep field after final delim? */
187 dstr = Str_new(34,strend-s);
188 str_nset(dstr,s,strend-s);
189 if (!realarray)
190 str_2mortal(dstr);
191 (void)astore(ary, ++sp, dstr);
192 iters++;
193 }
194 else {
195#ifndef I286x
196 while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
197 iters--,sp--;
198#else
199 char *zaps;
200 int zapb;
201
202 if (iters > 0) {
203 zaps = str_get(afetch(ary,sp,FALSE));
204 zapb = (int) *zaps;
205 }
206
207 while (iters > 0 && (!zapb)) {
208 iters--,sp--;
209 if (iters > 0) {
210 zaps = str_get(afetch(ary,iters-1,FALSE));
211 zapb = (int) *zaps;
212 }
213 }
214#endif
215 }
216 if (realarray) {
217 ary->ary_fill = sp;
218 if (gimme == G_ARRAY) {
219 sp++;
220 astore(stack, arglast[0] + 1 + sp, Nullstr);
221 Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
222 return arglast[0] + sp;
223 }
224 }
225 else {
226 if (gimme == G_ARRAY)
227 return sp;
228 }
229 sp = arglast[0] + 1;
230 str_numset(TARG,(double)iters);
231 STABSET(TARG);
232 st[sp] = TARG;
233 return sp;
234}
235