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, 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 ASM_TYPE_DIRECTIVE (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 #define PARMS LINKAGE /* no space for saved regs */
66 #define STR RTN+RTN_SIZE
67 #define DELIM STR+PTR_SIZE
68 #define SAVE DELIM+PTR_SIZE
71 ENTRY (BP_SYM (FUNCTION))
75 movl DELIM(%esp), %eax
76 CHECK_BOUNDS_LOW (%eax, DELIM(%esp))
78 #if !defined USE_AS_STRTOK_R && defined PIC
79 pushl %ebx /* Save PIC register. */
80 cfi_adjust_cfa_offset (4)
82 cfi_adjust_cfa_offset (4)
83 cfi_rel_offset (ebx, 0)
86 cfi_adjust_cfa_offset (-4)
87 addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
90 /* If the pointer is NULL we have to use the stored value of
93 #if __BOUNDED_POINTERS__
96 /* Save bounds of incoming non-NULL STR into save area. */
97 movl 4+STR(%esp), %eax
99 movl 8+STR(%esp), %eax
100 movl %eax, 8+SAVE_PTR
101 CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
103 L(0): movl SAVE_PTR, %edx
104 CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
110 #ifdef USE_AS_STRTOK_R
111 /* The value is stored in the third argument. */
112 movl SAVE(%esp), %edx
115 /* The value is in the local variable defined above. But
116 we have to take care for PIC code. */
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 !!! */
130 pushl %ecx /* make a 256 bytes long block filled with 0 */
131 cfi_adjust_cfa_offset (4)
133 cfi_adjust_cfa_offset (4)
135 cfi_adjust_cfa_offset (4)
137 cfi_adjust_cfa_offset (4)
139 cfi_adjust_cfa_offset (4)
141 cfi_adjust_cfa_offset (4)
143 cfi_adjust_cfa_offset (4)
145 cfi_adjust_cfa_offset (4)
147 cfi_adjust_cfa_offset (4)
149 cfi_adjust_cfa_offset (4)
151 cfi_adjust_cfa_offset (4)
153 cfi_adjust_cfa_offset (4)
155 cfi_adjust_cfa_offset (4)
157 cfi_adjust_cfa_offset (4)
159 cfi_adjust_cfa_offset (4)
161 cfi_adjust_cfa_offset (4)
163 cfi_adjust_cfa_offset (4)
165 cfi_adjust_cfa_offset (4)
167 cfi_adjust_cfa_offset (4)
169 cfi_adjust_cfa_offset (4)
171 cfi_adjust_cfa_offset (4)
173 cfi_adjust_cfa_offset (4)
175 cfi_adjust_cfa_offset (4)
177 cfi_adjust_cfa_offset (4)
179 cfi_adjust_cfa_offset (4)
181 cfi_adjust_cfa_offset (4)
183 cfi_adjust_cfa_offset (4)
185 cfi_adjust_cfa_offset (4)
187 cfi_adjust_cfa_offset (4)
189 cfi_adjust_cfa_offset (4)
191 cfi_adjust_cfa_offset (4)
193 cfi_adjust_cfa_offset (4)
195 cfi_adjust_cfa_offset (4)
197 cfi_adjust_cfa_offset (4)
199 cfi_adjust_cfa_offset (4)
201 cfi_adjust_cfa_offset (4)
203 cfi_adjust_cfa_offset (4)
205 cfi_adjust_cfa_offset (4)
207 cfi_adjust_cfa_offset (4)
209 cfi_adjust_cfa_offset (4)
211 cfi_adjust_cfa_offset (4)
213 cfi_adjust_cfa_offset (4)
215 cfi_adjust_cfa_offset (4)
217 cfi_adjust_cfa_offset (4)
219 cfi_adjust_cfa_offset (4)
221 cfi_adjust_cfa_offset (4)
223 cfi_adjust_cfa_offset (4)
225 cfi_adjust_cfa_offset (4)
227 cfi_adjust_cfa_offset (4)
229 cfi_adjust_cfa_offset (4)
231 cfi_adjust_cfa_offset (4)
233 cfi_adjust_cfa_offset (4)
235 cfi_adjust_cfa_offset (4)
237 cfi_adjust_cfa_offset (4)
239 cfi_adjust_cfa_offset (4)
241 cfi_adjust_cfa_offset (4)
243 cfi_adjust_cfa_offset (4)
245 cfi_adjust_cfa_offset (4)
246 pushl $0 /* These immediate values make the label 2 */
247 cfi_adjust_cfa_offset (4)
248 pushl $0 /* to be aligned on a 16 byte boundary to */
249 cfi_adjust_cfa_offset (4)
250 pushl $0 /* get a better performance of the loop. */
251 cfi_adjust_cfa_offset (4)
253 cfi_adjust_cfa_offset (4)
255 cfi_adjust_cfa_offset (4)
257 cfi_adjust_cfa_offset (4)
259 /* For understanding the following code remember that %ecx == 0 now.
260 Although all the following instruction only modify %cl we always
261 have a correct zero-extended 32-bit value in %ecx. */
263 L(2): movb (%eax), %cl /* get byte from stopset */
264 testb %cl, %cl /* is NUL char? */
265 jz L(1_1) /* yes => start compare loop */
266 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
268 movb 1(%eax), %cl /* get byte from stopset */
269 testb $0xff, %cl /* is NUL char? */
270 jz L(1_2) /* yes => start compare loop */
271 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
273 movb 2(%eax), %cl /* get byte from stopset */
274 testb $0xff, %cl /* is NUL char? */
275 jz L(1_3) /* yes => start compare loop */
276 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
278 movb 3(%eax), %cl /* get byte from stopset */
279 addl $4, %eax /* increment stopset pointer */
280 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
281 testb $0xff, %cl /* is NUL char? */
282 jnz L(2) /* no => process next dword from stopset */
284 #if __BOUNDED_POINTERS__
285 jmp L(1_0) /* pointer is correct for bounds check */
286 L(1_3): incl %eax /* adjust pointer for bounds check */
287 L(1_2): incl %eax /* ditto */
288 L(1_1): incl %eax /* ditto */
289 L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe)
291 L(1_3):; L(1_2):; L(1_1): /* fall through */
293 leal -4(%edx), %eax /* prepare loop */
295 /* We use a neat trick for the following loop. Normally we would
296 have to test for two termination conditions
297 1. a character in the stopset was found
299 2. the end of the string was found
300 As a sign that the character is in the stopset we store its
301 value in the table. The value of NUL is NUL so the loop
302 terminates for NUL in every case. */
304 L(3): addl $4, %eax /* adjust pointer for full loop round */
306 movb (%eax), %cl /* get byte from string */
307 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
308 jz L(4) /* no => start of token */
310 movb 1(%eax), %cl /* get byte from string */
311 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
312 jz L(5) /* no => start of token */
314 movb 2(%eax), %cl /* get byte from string */
315 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
316 jz L(6) /* no => start of token */
318 movb 3(%eax), %cl /* get byte from string */
319 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
320 jnz L(3) /* yes => start of loop */
322 incl %eax /* adjust pointer */
326 /* Now we have to terminate the string. */
328 L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */
330 L(7): addl $4, %edx /* adjust pointer for full loop round */
332 movb (%edx), %cl /* get byte from string */
333 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
334 je L(8) /* yes => return */
336 movb 1(%edx), %cl /* get byte from string */
337 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
338 je L(9) /* yes => return */
340 movb 2(%edx), %cl /* get byte from string */
341 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
342 je L(10) /* yes => return */
344 movb 3(%edx), %cl /* get byte from string */
345 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
346 jne L(7) /* no => start loop again */
348 incl %edx /* adjust pointer */
352 L(8): /* Remove the stopset table. */
354 cfi_adjust_cfa_offset (-256)
357 je L(returnNULL) /* There was no token anymore. */
359 movb $0, (%edx) /* Terminate string. */
361 /* Are we at end of string? */
368 /* Store the pointer to the next character. */
369 #ifdef USE_AS_STRTOK_R
370 movl SAVE(%esp), %ecx
373 CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
374 RETURN_BOUNDED_POINTER (SAVE_PTR)
377 #if !defined USE_AS_STRTOK_R && defined PIC
379 cfi_adjust_cfa_offset (-4)
387 #ifdef USE_AS_STRTOK_R
388 movl SAVE(%esp), %ecx
391 RETURN_NULL_BOUNDED_POINTER
394 END (BP_SYM (FUNCTION))