1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
3 Copyright (C) 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>, 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, 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 #if !defined USE_AS_STRTOK_R && defined PIC
66 # define PARMS LINKAGE+256+4 /* space for table and saved PIC register */
68 # define PARMS LINKAGE+256 /* space for table */
71 #define STR RTN+RTN_SIZE
72 #define DELIM STR+PTR_SIZE
73 #ifdef USE_AS_STRTOK_R
74 # define SAVE DELIM+PTR_SIZE
79 #if !defined USE_AS_STRTOK_R && defined PIC
84 ENTRY (BP_SYM (FUNCTION))
87 #if !defined USE_AS_STRTOK_R && defined PIC
88 pushl %ebx /* Save PIC register. */
89 cfi_adjust_cfa_offset (4)
90 cfi_rel_offset (ebx, 0)
92 addl $_GLOBAL_OFFSET_TABLE_, %ebx
95 /* First we create a table with flags for all possible characters.
96 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
97 supported by the C string functions we have 256 characters.
98 Before inserting marks for the stop characters we clear the whole
102 cfi_adjust_cfa_offset (256)
110 /* Note: %ecx = 0 !!! */
113 movl STR(%esp), %edx /* Get start of string. */
115 #ifdef USE_AS_STRTOK_R
116 /* The value is stored in the third argument. */
117 movl SAVE(%esp), %eax
120 /* The value is in the local variable defined above. But
121 we have to take care for PIC code. */
125 /* If the pointer is NULL we have to use the stored value of
131 #if __BOUNDED_POINTERS__
132 # ifdef USE_AS_STRTOK_R
133 movl SAVE(%esp), %ecx /* borrow %ecx for a moment */
136 /* Save bounds of incoming non-NULL STR into save area. */
137 movl 4+STR(%esp), %eax
138 movl %eax, 4+SAVE_PTR
139 movl 8+STR(%esp), %eax
140 movl %eax, 8+SAVE_PTR
141 L(0): CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
142 # ifdef USE_AS_STRTOK_R
143 xorl %ecx, %ecx /* restore %ecx to zero */
146 movl DELIM(%esp), %eax /* Get start of delimiter set. */
147 CHECK_BOUNDS_LOW (%eax, DELIM(%esp))
149 /* For understanding the following code remember that %ecx == 0 now.
150 Although all the following instruction only modify %cl we always
151 have a correct zero-extended 32-bit value in %ecx. */
153 L(2): movb (%eax), %cl /* get byte from stopset */
154 testb %cl, %cl /* is NUL char? */
155 jz L(1_1) /* yes => start compare loop */
156 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
158 movb 1(%eax), %cl /* get byte from stopset */
159 testb $0xff, %cl /* is NUL char? */
160 jz L(1_2) /* yes => start compare loop */
161 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
163 movb 2(%eax), %cl /* get byte from stopset */
164 testb $0xff, %cl /* is NUL char? */
165 jz L(1_3) /* yes => start compare loop */
166 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
168 movb 3(%eax), %cl /* get byte from stopset */
169 addl $4, %eax /* increment stopset pointer */
170 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
171 testb $0xff, %cl /* is NUL char? */
172 jnz L(2) /* no => process next dword from stopset */
174 #if __BOUNDED_POINTERS__
175 jmp L(1_0) /* pointer is correct for bounds check */
176 L(1_3): incl %eax /* adjust pointer for bounds check */
177 L(1_2): incl %eax /* ditto */
178 L(1_1): incl %eax /* ditto */
179 L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe)
181 L(1_3):; L(1_2):; L(1_1): /* fall through */
183 leal -4(%edx), %eax /* prepare loop */
185 /* We use a neat trick for the following loop. Normally we would
186 have to test for two termination conditions
187 1. a character in the stopset was found
189 2. the end of the string was found
190 As a sign that the character is in the stopset we store its
191 value in the table. The value of NUL is NUL so the loop
192 terminates for NUL in every case. */
194 L(3): addl $4, %eax /* adjust pointer for full loop round */
196 movb (%eax), %cl /* get byte from string */
197 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
198 jz L(4) /* no => start of token */
200 movb 1(%eax), %cl /* get byte from string */
201 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
202 jz L(5) /* no => start of token */
204 movb 2(%eax), %cl /* get byte from string */
205 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
206 jz L(6) /* no => start of token */
208 movb 3(%eax), %cl /* get byte from string */
209 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
210 jnz L(3) /* yes => start of loop */
212 incl %eax /* adjust pointer */
216 /* Now we have to terminate the string. */
218 L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */
220 L(7): addl $4, %edx /* adjust pointer for full loop round */
222 movb (%edx), %cl /* get byte from string */
223 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
224 je L(8) /* yes => return */
226 movb 1(%edx), %cl /* get byte from string */
227 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
228 je L(9) /* yes => return */
230 movb 2(%edx), %cl /* get byte from string */
231 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
232 je L(10) /* yes => return */
234 movb 3(%edx), %cl /* get byte from string */
235 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
236 jne L(7) /* no => start loop again */
238 incl %edx /* adjust pointer */
242 L(8): cmpl %eax, %edx
243 je L(returnNULL) /* There was no token anymore. */
245 movb $0, (%edx) /* Terminate string. */
247 /* Are we at end of string? */
252 /* Store the pointer to the next character. */
253 #ifdef USE_AS_STRTOK_R
254 movl SAVE(%esp), %ecx
257 CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
258 RETURN_BOUNDED_POINTER (SAVE_PTR)
261 /* Remove the stopset table. */
263 cfi_adjust_cfa_offset (-256)
264 #if !defined USE_AS_STRTOK_R && defined PIC
266 cfi_adjust_cfa_offset (-4)
274 #ifdef USE_AS_STRTOK_R
275 movl SAVE(%esp), %ecx
278 RETURN_NULL_BOUNDED_POINTER
281 END (BP_SYM (FUNCTION))