1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
3 Copyright (C) 1996, 1997, 1998, 2000, 2001 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 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.
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.
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 not,
19 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
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. */
84 addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
87 /* If the pointer is NULL we have to use the stored value of
90 #if __BOUNDED_POINTERS__
93 /* Save bounds of incoming non-NULL STR into save area. */
94 movl 4+STR(%esp), %eax
96 movl 8+STR(%esp), %eax
98 CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
100 L(0): movl SAVE_PTR, %edx
101 CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
107 #ifdef USE_AS_STRTOK_R
108 /* The value is stored in the third argument. */
109 movl SAVE(%esp), %edx
112 /* The value is in the local variable defined above. But
113 we have to take care for PIC code. */
120 /* First we create a table with flags for all possible characters.
121 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
122 supported by the C string functions we have 256 characters.
123 Before inserting marks for the stop characters we clear the whole
124 table. The unrolled form is much faster than a loop. */
125 xorl %ecx, %ecx /* %ecx = 0 !!! */
127 pushl %ecx /* make a 256 bytes long block filled with 0 */
185 pushl $0 /* These immediate values make the label 2 */
186 pushl $0 /* to be aligned on a 16 byte boundary to */
187 pushl $0 /* get a better performance of the loop. */
192 /* For understanding the following code remember that %ecx == 0 now.
193 Although all the following instruction only modify %cl we always
194 have a correct zero-extended 32-bit value in %ecx. */
196 L(2): movb (%eax), %cl /* get byte from stopset */
197 testb %cl, %cl /* is NUL char? */
198 jz L(1_1) /* yes => start compare loop */
199 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
201 movb 1(%eax), %cl /* get byte from stopset */
202 testb $0xff, %cl /* is NUL char? */
203 jz L(1_2) /* yes => start compare loop */
204 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
206 movb 2(%eax), %cl /* get byte from stopset */
207 testb $0xff, %cl /* is NUL char? */
208 jz L(1_3) /* yes => start compare loop */
209 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
211 movb 3(%eax), %cl /* get byte from stopset */
212 addl $4, %eax /* increment stopset pointer */
213 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
214 testb $0xff, %cl /* is NUL char? */
215 jnz L(2) /* no => process next dword from stopset */
217 #if __BOUNDED_POINTERS__
218 jmp L(1_0) /* pointer is correct for bounds check */
219 L(1_3): incl %eax /* adjust pointer for bounds check */
220 L(1_2): incl %eax /* ditto */
221 L(1_1): incl %eax /* ditto */
222 L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe)
224 L(1_3):; L(1_2):; L(1_1): /* fall through */
226 leal -4(%edx), %eax /* prepare loop */
228 /* We use a neat trick for the following loop. Normally we would
229 have to test for two termination conditions
230 1. a character in the stopset was found
232 2. the end of the string was found
233 As a sign that the character is in the stopset we store its
234 value in the table. The value of NUL is NUL so the loop
235 terminates for NUL in every case. */
237 L(3): addl $4, %eax /* adjust pointer for full loop round */
239 movb (%eax), %cl /* get byte from string */
240 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
241 jz L(4) /* no => start of token */
243 movb 1(%eax), %cl /* get byte from string */
244 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
245 jz L(5) /* no => start of token */
247 movb 2(%eax), %cl /* get byte from string */
248 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
249 jz L(6) /* no => start of token */
251 movb 3(%eax), %cl /* get byte from string */
252 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
253 jnz L(3) /* yes => start of loop */
255 incl %eax /* adjust pointer */
259 /* Now we have to terminate the string. */
261 L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */
263 L(7): addl $4, %edx /* adjust pointer for full loop round */
265 movb (%edx), %cl /* get byte from string */
266 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
267 je L(8) /* yes => return */
269 movb 1(%edx), %cl /* get byte from string */
270 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
271 je L(9) /* yes => return */
273 movb 2(%edx), %cl /* get byte from string */
274 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
275 je L(10) /* yes => return */
277 movb 3(%edx), %cl /* get byte from string */
278 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
279 jne L(7) /* no => start loop again */
281 incl %edx /* adjust pointer */
285 L(8): /* Remove the stopset table. */
289 je L(returnNULL) /* There was no token anymore. */
291 movb $0, (%edx) /* Terminate string. */
293 /* Are we at end of string? */
300 /* Store the pointer to the next character. */
301 #ifdef USE_AS_STRTOK_R
302 movl SAVE(%esp), %ecx
305 CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
306 RETURN_BOUNDED_POINTER (SAVE_PTR)
309 #if !defined USE_AS_STRTOK_R && defined PIC
317 RETURN_NULL_BOUNDED_POINTER
320 END (BP_SYM (FUNCTION))