Commit | Line | Data |
79072805 |
1 | int |
2 | do_split(TARG,spat,limit,gimme,arglast) |
3 | STR *TARG; |
4 | register SPAT *spat; |
5 | register int limit; |
6 | int gimme; |
7 | int *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 | |