1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
3 Copyright (C) 1998-2013 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
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"
26 /* This file can be used for three variants of the strtok function:
39 We do a common implementation here. */
41 #ifdef USE_AS_STRTOK_R
42 # define SAVE_PTR 0(%ecx)
46 .type save_ptr, @object
49 # if __BOUNDED_POINTERS__
56 # define SAVE_PTR save_ptr@GOTOFF(%ebx)
58 # define SAVE_PTR save_ptr
61 # define FUNCTION strtok
64 #if !defined USE_AS_STRTOK_R && defined PIC
65 # define PARMS LINKAGE+256+4 /* space for table and saved PIC register */
67 # define PARMS LINKAGE+256 /* space for table */
70 #define STR RTN+RTN_SIZE
71 #define DELIM STR+PTR_SIZE
72 #ifdef USE_AS_STRTOK_R
73 # define SAVE DELIM+PTR_SIZE
78 #if !defined USE_AS_STRTOK_R && defined PIC
83 ENTRY (BP_SYM (FUNCTION))
86 #if !defined USE_AS_STRTOK_R && defined PIC
87 pushl %ebx /* Save PIC register. */
88 cfi_adjust_cfa_offset (4)
89 cfi_rel_offset (ebx, 0)
91 addl $_GLOBAL_OFFSET_TABLE_, %ebx
94 /* First we create a table with flags for all possible characters.
95 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
96 supported by the C string functions we have 256 characters.
97 Before inserting marks for the stop characters we clear the whole
101 cfi_adjust_cfa_offset (256)
109 /* Note: %ecx = 0 !!! */
112 movl STR(%esp), %edx /* Get start of string. */
114 #ifdef USE_AS_STRTOK_R
115 /* The value is stored in the third argument. */
116 movl SAVE(%esp), %eax
119 /* The value is in the local variable defined above. But
120 we have to take care for PIC code. */
124 /* If the pointer is NULL we have to use the stored value of
130 #if __BOUNDED_POINTERS__
131 # ifdef USE_AS_STRTOK_R
132 movl SAVE(%esp), %ecx /* borrow %ecx for a moment */
135 /* Save bounds of incoming non-NULL STR into save area. */
136 movl 4+STR(%esp), %eax
137 movl %eax, 4+SAVE_PTR
138 movl 8+STR(%esp), %eax
139 movl %eax, 8+SAVE_PTR
140 L(0): CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
141 # ifdef USE_AS_STRTOK_R
142 xorl %ecx, %ecx /* restore %ecx to zero */
145 movl DELIM(%esp), %eax /* Get start of delimiter set. */
146 CHECK_BOUNDS_LOW (%eax, DELIM(%esp))
148 /* For understanding the following code remember that %ecx == 0 now.
149 Although all the following instruction only modify %cl we always
150 have a correct zero-extended 32-bit value in %ecx. */
152 L(2): movb (%eax), %cl /* get byte from stopset */
153 testb %cl, %cl /* is NUL char? */
154 jz L(1_1) /* yes => start compare loop */
155 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
157 movb 1(%eax), %cl /* get byte from stopset */
158 testb $0xff, %cl /* is NUL char? */
159 jz L(1_2) /* yes => start compare loop */
160 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
162 movb 2(%eax), %cl /* get byte from stopset */
163 testb $0xff, %cl /* is NUL char? */
164 jz L(1_3) /* yes => start compare loop */
165 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
167 movb 3(%eax), %cl /* get byte from stopset */
168 addl $4, %eax /* increment stopset pointer */
169 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
170 testb $0xff, %cl /* is NUL char? */
171 jnz L(2) /* no => process next dword from stopset */
173 #if __BOUNDED_POINTERS__
174 jmp L(1_0) /* pointer is correct for bounds check */
175 L(1_3): incl %eax /* adjust pointer for bounds check */
176 L(1_2): incl %eax /* ditto */
177 L(1_1): incl %eax /* ditto */
178 L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe)
180 L(1_3):; L(1_2):; L(1_1): /* fall through */
182 leal -4(%edx), %eax /* prepare loop */
184 /* We use a neat trick for the following loop. Normally we would
185 have to test for two termination conditions
186 1. a character in the stopset was found
188 2. the end of the string was found
189 As a sign that the character is in the stopset we store its
190 value in the table. The value of NUL is NUL so the loop
191 terminates for NUL in every case. */
193 L(3): addl $4, %eax /* adjust pointer for full loop round */
195 movb (%eax), %cl /* get byte from string */
196 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
197 jz L(4) /* no => start of token */
199 movb 1(%eax), %cl /* get byte from string */
200 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
201 jz L(5) /* no => start of token */
203 movb 2(%eax), %cl /* get byte from string */
204 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
205 jz L(6) /* no => start of token */
207 movb 3(%eax), %cl /* get byte from string */
208 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
209 jnz L(3) /* yes => start of loop */
211 incl %eax /* adjust pointer */
215 /* Now we have to terminate the string. */
217 L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */
219 L(7): addl $4, %edx /* adjust pointer for full loop round */
221 movb (%edx), %cl /* get byte from string */
222 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
223 je L(8) /* yes => return */
225 movb 1(%edx), %cl /* get byte from string */
226 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
227 je L(9) /* yes => return */
229 movb 2(%edx), %cl /* get byte from string */
230 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
231 je L(10) /* yes => return */
233 movb 3(%edx), %cl /* get byte from string */
234 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
235 jne L(7) /* no => start loop again */
237 incl %edx /* adjust pointer */
241 L(8): cmpl %eax, %edx
242 je L(returnNULL) /* There was no token anymore. */
244 movb $0, (%edx) /* Terminate string. */
246 /* Are we at end of string? */
251 /* Store the pointer to the next character. */
252 #ifdef USE_AS_STRTOK_R
253 movl SAVE(%esp), %ecx
256 CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
257 RETURN_BOUNDED_POINTER (SAVE_PTR)
260 /* Remove the stopset table. */
262 cfi_adjust_cfa_offset (-256)
263 #if !defined USE_AS_STRTOK_R && defined PIC
265 cfi_adjust_cfa_offset (-4)
273 #ifdef USE_AS_STRTOK_R
274 movl SAVE(%esp), %ecx
277 RETURN_NULL_BOUNDED_POINTER
280 END (BP_SYM (FUNCTION))