1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
3 Copyright (C) 1996-2014 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
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 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, see
19 <http://www.gnu.org/licenses/>. */
22 #include "asm-syntax.h"
24 /* This file can be used for three variants of the strtok function:
37 We do a common implementation here. */
39 #ifdef USE_AS_STRTOK_R
40 # define SAVE_PTR 0(%ecx)
44 .type save_ptr, @object
50 # define SAVE_PTR save_ptr@GOTOFF(%ebx)
52 # define SAVE_PTR save_ptr
55 # define FUNCTION strtok
58 #define PARMS 4 /* no space for saved regs */
68 movl DELIM(%esp), %eax
70 #if !defined USE_AS_STRTOK_R && defined PIC
71 pushl %ebx /* Save PIC register. */
72 cfi_adjust_cfa_offset (4)
74 cfi_adjust_cfa_offset (4)
75 cfi_rel_offset (ebx, 0)
78 cfi_adjust_cfa_offset (-4)
79 addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
82 /* If the pointer is NULL we have to use the stored value of
87 #ifdef USE_AS_STRTOK_R
88 /* The value is stored in the third argument. */
92 /* The value is in the local variable defined above. But
93 we have to take care for PIC code. */
100 /* First we create a table with flags for all possible characters.
101 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
102 supported by the C string functions we have 256 characters.
103 Before inserting marks for the stop characters we clear the whole
104 table. The unrolled form is much faster than a loop. */
105 xorl %ecx, %ecx /* %ecx = 0 !!! */
107 pushl %ecx /* make a 256 bytes long block filled with 0 */
108 cfi_adjust_cfa_offset (4)
110 cfi_adjust_cfa_offset (4)
112 cfi_adjust_cfa_offset (4)
114 cfi_adjust_cfa_offset (4)
116 cfi_adjust_cfa_offset (4)
118 cfi_adjust_cfa_offset (4)
120 cfi_adjust_cfa_offset (4)
122 cfi_adjust_cfa_offset (4)
124 cfi_adjust_cfa_offset (4)
126 cfi_adjust_cfa_offset (4)
128 cfi_adjust_cfa_offset (4)
130 cfi_adjust_cfa_offset (4)
132 cfi_adjust_cfa_offset (4)
134 cfi_adjust_cfa_offset (4)
136 cfi_adjust_cfa_offset (4)
138 cfi_adjust_cfa_offset (4)
140 cfi_adjust_cfa_offset (4)
142 cfi_adjust_cfa_offset (4)
144 cfi_adjust_cfa_offset (4)
146 cfi_adjust_cfa_offset (4)
148 cfi_adjust_cfa_offset (4)
150 cfi_adjust_cfa_offset (4)
152 cfi_adjust_cfa_offset (4)
154 cfi_adjust_cfa_offset (4)
156 cfi_adjust_cfa_offset (4)
158 cfi_adjust_cfa_offset (4)
160 cfi_adjust_cfa_offset (4)
162 cfi_adjust_cfa_offset (4)
164 cfi_adjust_cfa_offset (4)
166 cfi_adjust_cfa_offset (4)
168 cfi_adjust_cfa_offset (4)
170 cfi_adjust_cfa_offset (4)
172 cfi_adjust_cfa_offset (4)
174 cfi_adjust_cfa_offset (4)
176 cfi_adjust_cfa_offset (4)
178 cfi_adjust_cfa_offset (4)
180 cfi_adjust_cfa_offset (4)
182 cfi_adjust_cfa_offset (4)
184 cfi_adjust_cfa_offset (4)
186 cfi_adjust_cfa_offset (4)
188 cfi_adjust_cfa_offset (4)
190 cfi_adjust_cfa_offset (4)
192 cfi_adjust_cfa_offset (4)
194 cfi_adjust_cfa_offset (4)
196 cfi_adjust_cfa_offset (4)
198 cfi_adjust_cfa_offset (4)
200 cfi_adjust_cfa_offset (4)
202 cfi_adjust_cfa_offset (4)
204 cfi_adjust_cfa_offset (4)
206 cfi_adjust_cfa_offset (4)
208 cfi_adjust_cfa_offset (4)
210 cfi_adjust_cfa_offset (4)
212 cfi_adjust_cfa_offset (4)
214 cfi_adjust_cfa_offset (4)
216 cfi_adjust_cfa_offset (4)
218 cfi_adjust_cfa_offset (4)
220 cfi_adjust_cfa_offset (4)
222 cfi_adjust_cfa_offset (4)
223 pushl $0 /* These immediate values make the label 2 */
224 cfi_adjust_cfa_offset (4)
225 pushl $0 /* to be aligned on a 16 byte boundary to */
226 cfi_adjust_cfa_offset (4)
227 pushl $0 /* get a better performance of the loop. */
228 cfi_adjust_cfa_offset (4)
230 cfi_adjust_cfa_offset (4)
232 cfi_adjust_cfa_offset (4)
234 cfi_adjust_cfa_offset (4)
236 /* For understanding the following code remember that %ecx == 0 now.
237 Although all the following instruction only modify %cl we always
238 have a correct zero-extended 32-bit value in %ecx. */
240 L(2): movb (%eax), %cl /* get byte from stopset */
241 testb %cl, %cl /* is NUL char? */
242 jz L(1_1) /* yes => start compare loop */
243 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
245 movb 1(%eax), %cl /* get byte from stopset */
246 testb $0xff, %cl /* is NUL char? */
247 jz L(1_1) /* yes => start compare loop */
248 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
250 movb 2(%eax), %cl /* get byte from stopset */
251 testb $0xff, %cl /* is NUL char? */
252 jz L(1_1) /* yes => start compare loop */
253 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
255 movb 3(%eax), %cl /* get byte from stopset */
256 addl $4, %eax /* increment stopset pointer */
257 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
258 testb $0xff, %cl /* is NUL char? */
259 jnz L(2) /* no => process next dword from stopset */
261 L(1_1): leal -4(%edx), %eax /* prepare loop */
263 /* We use a neat trick for the following loop. Normally we would
264 have to test for two termination conditions
265 1. a character in the stopset was found
267 2. the end of the string was found
268 As a sign that the character is in the stopset we store its
269 value in the table. The value of NUL is NUL so the loop
270 terminates for NUL in every case. */
272 L(3): addl $4, %eax /* adjust pointer for full loop round */
274 movb (%eax), %cl /* get byte from string */
275 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
276 jz L(4) /* no => start of token */
278 movb 1(%eax), %cl /* get byte from string */
279 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
280 jz L(5) /* no => start of token */
282 movb 2(%eax), %cl /* get byte from string */
283 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
284 jz L(6) /* no => start of token */
286 movb 3(%eax), %cl /* get byte from string */
287 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
288 jnz L(3) /* yes => start of loop */
290 incl %eax /* adjust pointer */
294 /* Now we have to terminate the string. */
296 L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */
298 L(7): addl $4, %edx /* adjust pointer for full loop round */
300 movb (%edx), %cl /* get byte from string */
301 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
302 je L(8) /* yes => return */
304 movb 1(%edx), %cl /* get byte from string */
305 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
306 je L(9) /* yes => return */
308 movb 2(%edx), %cl /* get byte from string */
309 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
310 je L(10) /* yes => return */
312 movb 3(%edx), %cl /* get byte from string */
313 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
314 jne L(7) /* no => start loop again */
316 incl %edx /* adjust pointer */
320 L(8): /* Remove the stopset table. */
322 cfi_adjust_cfa_offset (-256)
325 je L(returnNULL) /* There was no token anymore. */
327 movb $0, (%edx) /* Terminate string. */
329 /* Are we at end of string? */
336 /* Store the pointer to the next character. */
337 #ifdef USE_AS_STRTOK_R
338 movl SAVE(%esp), %ecx
343 #if !defined USE_AS_STRTOK_R && defined PIC
345 cfi_adjust_cfa_offset (-4)
352 #ifdef USE_AS_STRTOK_R
353 movl SAVE(%esp), %ecx