]>
Commit | Line | Data |
---|---|---|
59dd8641 RM |
1 | /* strtok (str, delim) -- Return next DELIM separated token from STR. |
2 | For Intel 80x86, x>=3. | |
3 | Copyright (C) 1996 Free Software Foundation, Inc. | |
4 | This file is part of the GNU C Library. | |
5 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. | |
6 | ||
7 | The GNU C Library is free software; you can redistribute it and/or | |
8 | modify it under the terms of the GNU Library General Public License as | |
9 | published by the Free Software Foundation; either version 2 of the | |
10 | License, or (at your option) any later version. | |
11 | ||
12 | The GNU C Library is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | Library General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU Library General Public | |
18 | License along with the GNU C Library; see the file COPYING.LIB. If | |
19 | not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | Boston, MA 02111-1307, USA. */ | |
21 | ||
22 | #include <errnos.h> | |
23 | #include <sysdep.h> | |
24 | ||
25 | /* This file can be used for three variants of the strtok function: | |
26 | ||
27 | strtok: | |
28 | INPUT PARAMETER: | |
29 | str (sp + 4) | |
30 | delim (sp + 8) | |
31 | ||
32 | strtok_r: | |
33 | INPUT PARAMETER: | |
34 | str (sp + 4) | |
35 | delim (sp + 8) | |
36 | save_ptr (sp + 12) | |
37 | ||
38 | strsep: | |
39 | INPUT PARAMETERS | |
40 | str_ptr (sp + 4) | |
41 | delim (sp + 8) | |
42 | ||
43 | We do a common implementation here. */ | |
44 | ||
45 | #if !defined (USE_AS_STRTOK_R) && !defined (USE_AS_STRSEP) | |
46 | .bss | |
47 | .local save_ptr | |
48 | ASM_TYPE_DIRECTIVE (save_ptr, @object) | |
49 | .size save_ptr, 4 | |
50 | save_ptr: | |
51 | .space 4 | |
52 | ||
53 | #define FUNCTION strtok | |
54 | #endif | |
55 | ||
56 | /* We use the possibility to do some more initialization | |
57 | for the strtok implementation. */ | |
58 | .text | |
59 | Lillegal_argument: | |
60 | #ifndef PIC | |
61 | movl $EINVAL, C_SYMBOL_NAME(errno) | |
62 | xorl %eax, %eax | |
63 | #else | |
64 | # if defined (USE_AS_STRTOK_R) || defined (USE_AS_STRSEP) | |
65 | pushl %ebx /* Save PIC register. */ | |
66 | call Lhere2 | |
67 | Lhere2: popl %ebx | |
68 | addl $_GLOBAL_OFFSET_TABLE_+[.-Lhere2], %ebx | |
69 | # endif | |
70 | movl errno@GOT(%ebx), %ebx | |
71 | movl $EINVAL, (%ebx) | |
72 | xorl %eax, %eax | |
73 | popl %ebx | |
74 | #endif | |
75 | ret | |
76 | ||
77 | ||
78 | ENTRY (FUNCTION) | |
79 | ||
80 | movl 4(%esp), %edx /* Get start of string. */ | |
81 | movl 8(%esp), %eax /* Get start of delimiter set. */ | |
82 | ||
83 | #ifdef USE_AS_STRSEP | |
84 | /* %EDX does not yet contain the string starting point. Only | |
85 | a pointer to the location where it is stored. */ | |
86 | movl (%edx), %edx | |
87 | #else | |
88 | # if !defined (USE_AS_STRTOK_R) && defined (PIC) | |
89 | pushl %ebx /* Save PIC register. */ | |
90 | call Lhere | |
91 | Lhere: popl %ebx | |
92 | addl $_GLOBAL_OFFSET_TABLE_+[.-Lhere], %ebx | |
93 | # endif | |
94 | ||
95 | /* If the pointer is NULL we have to use the stored value of | |
96 | the last run. */ | |
97 | cmpl $0, %edx | |
98 | jne L0 | |
99 | ||
100 | # ifdef USE_AS_STRTOK_R | |
101 | /* The value is stored in the third argument. */ | |
102 | movl 12(%esp), %edx | |
103 | movl (%edx), %edx | |
104 | # else | |
105 | /* The value is in the local variable defined above. But | |
106 | we have to take care for PIC code. */ | |
107 | # ifndef PIC | |
108 | movl save_ptr, %edx | |
109 | # else | |
110 | movl save_ptr@GOTOFF(%ebx), %edx | |
111 | # endif | |
112 | # endif | |
113 | #endif | |
114 | ||
115 | /* Compare whether pointer is NULL. We are tolerant here | |
116 | because the C function do the same. */ | |
117 | cmpl $0, %edx | |
118 | je Lillegal_argument | |
119 | ||
120 | #ifndef USE_AS_STRSEP | |
121 | L0: | |
122 | #endif | |
123 | /* First we create a table with flags for all possible characters. | |
124 | For the ASCII (7bit/8bit) or ISO-8859-X character sets which are | |
125 | supported by the C string functions we have 256 characters. | |
126 | Before inserting marks for the stop characters we clear the whole | |
127 | table. The unrolled form is much faster than a loop. */ | |
128 | xorl %ecx, %ecx /* %ecx = 0 !!! */ | |
129 | ||
130 | pushl %ecx /* make a 256 bytes long block filled with 0 */ | |
131 | pushl %ecx | |
132 | pushl %ecx | |
133 | pushl %ecx | |
134 | pushl %ecx | |
135 | pushl %ecx | |
136 | pushl %ecx | |
137 | pushl %ecx | |
138 | pushl %ecx | |
139 | pushl %ecx | |
140 | pushl %ecx | |
141 | pushl %ecx | |
142 | pushl %ecx | |
143 | pushl %ecx | |
144 | pushl %ecx | |
145 | pushl %ecx | |
146 | pushl %ecx | |
147 | pushl %ecx | |
148 | pushl %ecx | |
149 | pushl %ecx | |
150 | pushl %ecx | |
151 | pushl %ecx | |
152 | pushl %ecx | |
153 | pushl %ecx | |
154 | pushl %ecx | |
155 | pushl %ecx | |
156 | pushl %ecx | |
157 | pushl %ecx | |
158 | pushl %ecx | |
159 | pushl %ecx | |
160 | pushl %ecx | |
161 | pushl %ecx | |
162 | pushl %ecx | |
163 | pushl %ecx | |
164 | pushl %ecx | |
165 | pushl %ecx | |
166 | pushl %ecx | |
167 | pushl %ecx | |
168 | pushl %ecx | |
169 | pushl %ecx | |
170 | pushl %ecx | |
171 | pushl %ecx | |
172 | pushl %ecx | |
173 | pushl %ecx | |
174 | pushl %ecx | |
175 | pushl %ecx | |
176 | pushl %ecx | |
177 | pushl %ecx | |
178 | pushl %ecx | |
179 | pushl %ecx | |
180 | pushl %ecx | |
181 | pushl %ecx | |
182 | pushl %ecx | |
183 | pushl %ecx | |
184 | pushl %ecx | |
185 | pushl %ecx | |
186 | pushl %ecx | |
187 | pushl %ecx | |
188 | pushl $0 /* These immediate values make the label 2 */ | |
189 | pushl $0 /* to be aligned on a 16 byte boundary to */ | |
190 | pushl $0 /* get a better performance of the loop. */ | |
191 | pushl $0 | |
192 | pushl $0 | |
193 | pushl $0 | |
194 | ||
195 | /* For understanding the following code remember that %ecx == 0 now. | |
196 | Although all the following instruction only modify %cl we always | |
197 | have a correct zero-extended 32-bit value in %ecx. */ | |
198 | ||
199 | L2: movb (%eax), %cl /* get byte from stopset */ | |
200 | testb %cl, %cl /* is NUL char? */ | |
201 | jz L1 /* yes => start compare loop */ | |
202 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ | |
203 | ||
204 | movb 1(%eax), %cl /* get byte from stopset */ | |
205 | testb $0xff, %cl /* is NUL char? */ | |
206 | jz L1 /* yes => start compare loop */ | |
207 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ | |
208 | ||
209 | movb 2(%eax), %cl /* get byte from stopset */ | |
210 | testb $0xff, %cl /* is NUL char? */ | |
211 | jz L1 /* yes => start compare loop */ | |
212 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ | |
213 | ||
214 | movb 3(%eax), %cl /* get byte from stopset */ | |
215 | addl $4, %eax /* increment stopset pointer */ | |
216 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ | |
217 | testb $0xff, %cl /* is NUL char? */ | |
218 | jnz L2 /* no => process next dword from stopset */ | |
219 | ||
220 | L1: leal -4(%edx), %eax /* prepare loop */ | |
221 | ||
222 | /* We use a neat trick for the following loop. Normally we would | |
223 | have to test for two termination conditions | |
224 | 1. a character in the stopset was found | |
225 | and | |
226 | 2. the end of the string was found | |
227 | But as a sign that the chracter is in the stopset we store its | |
228 | value in the table. But the value of NUL is NUL so the loop | |
229 | terminates for NUL in every case. */ | |
230 | ||
231 | L3: addl $4, %eax /* adjust pointer for full loop round */ | |
232 | ||
233 | movb (%eax), %cl /* get byte from string */ | |
234 | testb %cl, (%esp,%ecx) /* is it contained in stopset? */ | |
235 | jz L4 /* no => start of token */ | |
236 | ||
237 | movb 1(%eax), %cl /* get byte from string */ | |
238 | testb %cl, (%esp,%ecx) /* is it contained in stopset? */ | |
239 | jz L5 /* no => start of token */ | |
240 | ||
241 | movb 2(%eax), %cl /* get byte from string */ | |
242 | testb %cl, (%esp,%ecx) /* is it contained in stopset? */ | |
243 | jz L6 /* no => start of token */ | |
244 | ||
245 | movb 3(%eax), %cl /* get byte from string */ | |
246 | testb %cl, (%esp,%ecx) /* is it contained in stopset? */ | |
247 | jnz L3 /* yes => start of loop */ | |
248 | ||
249 | incl %eax /* adjust pointer */ | |
250 | L6: incl %eax | |
251 | L5: incl %eax | |
252 | ||
253 | /* Now we have to terminate the string. */ | |
254 | ||
255 | L4: leal -4(%eax), %edx /* We use %EDX for the next run. */ | |
256 | ||
257 | L7: addl $4, %edx /* adjust pointer for full loop round */ | |
258 | ||
259 | movb (%edx), %cl /* get byte from string */ | |
260 | cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */ | |
261 | je L8 /* yes => return */ | |
262 | ||
263 | movb 1(%edx), %cl /* get byte from string */ | |
264 | cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */ | |
265 | je L9 /* yes => return */ | |
266 | ||
267 | movb 2(%edx), %cl /* get byte from string */ | |
268 | cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */ | |
269 | je L10 /* yes => return */ | |
270 | ||
271 | movb 3(%edx), %cl /* get byte from string */ | |
272 | cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */ | |
273 | jne L7 /* no => start loop again */ | |
274 | ||
275 | incl %edx /* adjust pointer */ | |
276 | L10: incl %edx | |
277 | L9: incl %edx | |
278 | ||
279 | L8: /* Remove the stopset table. */ | |
280 | addl $256, %esp | |
281 | ||
282 | cmpl %eax, %edx | |
283 | je LreturnNULL /* There was no token anymore. */ | |
284 | ||
285 | movb $0, (%edx) /* Terminate string. */ | |
286 | ||
287 | /* Are we at end of string? */ | |
288 | cmpb $0, %cl | |
289 | je L11 | |
290 | ||
291 | incl %edx | |
292 | L11: | |
293 | ||
294 | /* Store the pointer to the next character. */ | |
295 | #ifdef USE_AS_STRTOK_R | |
296 | movl 12(%esp), %ecx | |
297 | movl %edx, (%ecx) | |
298 | #elif USE_AS_STRSEP | |
299 | movl 4(%esp), %ecx | |
300 | movl %edx, (%ecx) | |
301 | #else | |
302 | # ifndef PIC | |
303 | movl %edx, save_ptr | |
304 | # else | |
305 | movl %edx, save_ptr@GOTOFF(%ebx) | |
306 | popl %ebx | |
307 | # endif | |
308 | #endif | |
309 | ret | |
310 | ||
311 | LreturnNULL: | |
312 | xorl %eax, %eax | |
313 | ||
314 | /* Store NULL as pointer to the next character. */ | |
315 | #ifdef USE_AS_STRTOK_R | |
316 | movl 12(%esp), %ecx | |
317 | movl %eax, (%ecx) | |
318 | #elif USE_AS_STRSEP | |
319 | movl 4(%esp), %ecx | |
320 | movl %eax, (%ecx) | |
321 | #else | |
322 | # ifndef PIC | |
323 | movl %eax, save_ptr | |
324 | # else | |
325 | movl %eax, save_ptr@GOTOFF(%ebx) | |
326 | popl %ebx | |
327 | # endif | |
328 | #endif | |
329 | ret |