1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
3 Copyright (C) 1996-1998,2000,2001,2005,2006 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, write to the Free
19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 #include "asm-syntax.h"
27 /* This file can be used for three variants of the strtok function:
40 We do a common implementation here. */
42 #ifdef USE_AS_STRTOK_R
43 # define SAVE_PTR 0(%ecx)
47 ASM_TYPE_DIRECTIVE (save_ptr, @object)
50 # if __BOUNDED_POINTERS__
57 # define SAVE_PTR save_ptr@GOTOFF(%ebx)
59 # define SAVE_PTR save_ptr
62 # define FUNCTION strtok
65 #define PARMS LINKAGE /* no space for saved regs */
67 #define STR RTN+RTN_SIZE
68 #define DELIM STR+PTR_SIZE
69 #define SAVE DELIM+PTR_SIZE
72 ENTRY (BP_SYM (FUNCTION))
76 movl DELIM(%esp), %eax
77 CHECK_BOUNDS_LOW (%eax, DELIM(%esp))
79 #if !defined USE_AS_STRTOK_R && defined PIC
80 pushl %ebx /* Save PIC register. */
81 cfi_adjust_cfa_offset (4)
83 cfi_adjust_cfa_offset (4)
84 cfi_rel_offset (ebx, 0)
87 cfi_adjust_cfa_offset (-4)
88 addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
91 /* If the pointer is NULL we have to use the stored value of
94 #if __BOUNDED_POINTERS__
97 /* Save bounds of incoming non-NULL STR into save area. */
98 movl 4+STR(%esp), %eax
100 movl 8+STR(%esp), %eax
101 movl %eax, 8+SAVE_PTR
102 CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
104 L(0): movl SAVE_PTR, %edx
105 CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
111 #ifdef USE_AS_STRTOK_R
112 /* The value is stored in the third argument. */
113 movl SAVE(%esp), %edx
116 /* The value is in the local variable defined above. But
117 we have to take care for PIC code. */
124 /* First we create a table with flags for all possible characters.
125 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
126 supported by the C string functions we have 256 characters.
127 Before inserting marks for the stop characters we clear the whole
128 table. The unrolled form is much faster than a loop. */
129 xorl %ecx, %ecx /* %ecx = 0 !!! */
131 pushl %ecx /* make a 256 bytes long block filled with 0 */
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)
224 cfi_adjust_cfa_offset (4)
226 cfi_adjust_cfa_offset (4)
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 cfi_adjust_cfa_offset (4)
238 cfi_adjust_cfa_offset (4)
240 cfi_adjust_cfa_offset (4)
242 cfi_adjust_cfa_offset (4)
244 cfi_adjust_cfa_offset (4)
246 cfi_adjust_cfa_offset (4)
247 pushl $0 /* These immediate values make the label 2 */
248 cfi_adjust_cfa_offset (4)
249 pushl $0 /* to be aligned on a 16 byte boundary to */
250 cfi_adjust_cfa_offset (4)
251 pushl $0 /* get a better performance of the loop. */
252 cfi_adjust_cfa_offset (4)
254 cfi_adjust_cfa_offset (4)
256 cfi_adjust_cfa_offset (4)
258 cfi_adjust_cfa_offset (4)
260 /* For understanding the following code remember that %ecx == 0 now.
261 Although all the following instruction only modify %cl we always
262 have a correct zero-extended 32-bit value in %ecx. */
264 L(2): movb (%eax), %cl /* get byte from stopset */
265 testb %cl, %cl /* is NUL char? */
266 jz L(1_1) /* yes => start compare loop */
267 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
269 movb 1(%eax), %cl /* get byte from stopset */
270 testb $0xff, %cl /* is NUL char? */
271 jz L(1_2) /* yes => start compare loop */
272 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
274 movb 2(%eax), %cl /* get byte from stopset */
275 testb $0xff, %cl /* is NUL char? */
276 jz L(1_3) /* yes => start compare loop */
277 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
279 movb 3(%eax), %cl /* get byte from stopset */
280 addl $4, %eax /* increment stopset pointer */
281 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
282 testb $0xff, %cl /* is NUL char? */
283 jnz L(2) /* no => process next dword from stopset */
285 #if __BOUNDED_POINTERS__
286 jmp L(1_0) /* pointer is correct for bounds check */
287 L(1_3): incl %eax /* adjust pointer for bounds check */
288 L(1_2): incl %eax /* ditto */
289 L(1_1): incl %eax /* ditto */
290 L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe)
292 L(1_3):; L(1_2):; L(1_1): /* fall through */
294 leal -4(%edx), %eax /* prepare loop */
296 /* We use a neat trick for the following loop. Normally we would
297 have to test for two termination conditions
298 1. a character in the stopset was found
300 2. the end of the string was found
301 As a sign that the character is in the stopset we store its
302 value in the table. The value of NUL is NUL so the loop
303 terminates for NUL in every case. */
305 L(3): addl $4, %eax /* adjust pointer for full loop round */
307 movb (%eax), %cl /* get byte from string */
308 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
309 jz L(4) /* no => start of token */
311 movb 1(%eax), %cl /* get byte from string */
312 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
313 jz L(5) /* no => start of token */
315 movb 2(%eax), %cl /* get byte from string */
316 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
317 jz L(6) /* no => start of token */
319 movb 3(%eax), %cl /* get byte from string */
320 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
321 jnz L(3) /* yes => start of loop */
323 incl %eax /* adjust pointer */
327 /* Now we have to terminate the string. */
329 L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */
331 L(7): addl $4, %edx /* adjust pointer for full loop round */
333 movb (%edx), %cl /* get byte from string */
334 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
335 je L(8) /* yes => return */
337 movb 1(%edx), %cl /* get byte from string */
338 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
339 je L(9) /* yes => return */
341 movb 2(%edx), %cl /* get byte from string */
342 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
343 je L(10) /* yes => return */
345 movb 3(%edx), %cl /* get byte from string */
346 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
347 jne L(7) /* no => start loop again */
349 incl %edx /* adjust pointer */
353 L(8): /* Remove the stopset table. */
355 cfi_adjust_cfa_offset (-256)
358 je L(returnNULL) /* There was no token anymore. */
360 movb $0, (%edx) /* Terminate string. */
362 /* Are we at end of string? */
369 /* Store the pointer to the next character. */
370 #ifdef USE_AS_STRTOK_R
371 movl SAVE(%esp), %ecx
374 CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
375 RETURN_BOUNDED_POINTER (SAVE_PTR)
378 #if !defined USE_AS_STRTOK_R && defined PIC
380 cfi_adjust_cfa_offset (-4)
388 #ifdef USE_AS_STRTOK_R
389 movl SAVE(%esp), %ecx
392 RETURN_NULL_BOUNDED_POINTER
395 END (BP_SYM (FUNCTION))