1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
3 Copyright (C) 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>, 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. */
90 addl $_GLOBAL_OFFSET_TABLE_, %ebx
93 /* First we create a table with flags for all possible characters.
94 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
95 supported by the C string functions we have 256 characters.
96 Before inserting marks for the stop characters we clear the whole
107 /* Note: %ecx = 0 !!! */
110 movl STR(%esp), %edx /* Get start of string. */
112 #ifdef USE_AS_STRTOK_R
113 /* The value is stored in the third argument. */
114 movl SAVE(%esp), %eax
117 /* The value is in the local variable defined above. But
118 we have to take care for PIC code. */
122 /* If the pointer is NULL we have to use the stored value of
128 #if __BOUNDED_POINTERS__
129 # ifdef USE_AS_STRTOK_R
130 movl SAVE(%esp), %ecx /* borrow %ecx for a moment */
133 /* Save bounds of incoming non-NULL STR into save area. */
134 movl 4+STR(%esp), %eax
135 movl %eax, 4+SAVE_PTR
136 movl 8+STR(%esp), %eax
137 movl %eax, 8+SAVE_PTR
138 L(0): CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
139 # ifdef USE_AS_STRTOK_R
140 xorl %ecx, %ecx /* restore %ecx to zero */
143 movl DELIM(%esp), %eax /* Get start of delimiter set. */
144 CHECK_BOUNDS_LOW (%eax, DELIM(%esp))
146 /* For understanding the following code remember that %ecx == 0 now.
147 Although all the following instruction only modify %cl we always
148 have a correct zero-extended 32-bit value in %ecx. */
150 L(2): movb (%eax), %cl /* get byte from stopset */
151 testb %cl, %cl /* is NUL char? */
152 jz L(1_1) /* yes => start compare loop */
153 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
155 movb 1(%eax), %cl /* get byte from stopset */
156 testb $0xff, %cl /* is NUL char? */
157 jz L(1_2) /* yes => start compare loop */
158 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
160 movb 2(%eax), %cl /* get byte from stopset */
161 testb $0xff, %cl /* is NUL char? */
162 jz L(1_3) /* yes => start compare loop */
163 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
165 movb 3(%eax), %cl /* get byte from stopset */
166 addl $4, %eax /* increment stopset pointer */
167 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
168 testb $0xff, %cl /* is NUL char? */
169 jnz L(2) /* no => process next dword from stopset */
171 #if __BOUNDED_POINTERS__
172 jmp L(1_0) /* pointer is correct for bounds check */
173 L(1_3): incl %eax /* adjust pointer for bounds check */
174 L(1_2): incl %eax /* ditto */
175 L(1_1): incl %eax /* ditto */
176 L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe)
178 L(1_3):; L(1_2):; L(1_1): /* fall through */
180 leal -4(%edx), %eax /* prepare loop */
182 /* We use a neat trick for the following loop. Normally we would
183 have to test for two termination conditions
184 1. a character in the stopset was found
186 2. the end of the string was found
187 As a sign that the character is in the stopset we store its
188 value in the table. The value of NUL is NUL so the loop
189 terminates for NUL in every case. */
191 L(3): addl $4, %eax /* adjust pointer for full loop round */
193 movb (%eax), %cl /* get byte from string */
194 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
195 jz L(4) /* no => start of token */
197 movb 1(%eax), %cl /* get byte from string */
198 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
199 jz L(5) /* no => start of token */
201 movb 2(%eax), %cl /* get byte from string */
202 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
203 jz L(6) /* no => start of token */
205 movb 3(%eax), %cl /* get byte from string */
206 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
207 jnz L(3) /* yes => start of loop */
209 incl %eax /* adjust pointer */
213 /* Now we have to terminate the string. */
215 L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */
217 L(7): addl $4, %edx /* adjust pointer for full loop round */
219 movb (%edx), %cl /* get byte from string */
220 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
221 je L(8) /* yes => return */
223 movb 1(%edx), %cl /* get byte from string */
224 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
225 je L(9) /* yes => return */
227 movb 2(%edx), %cl /* get byte from string */
228 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
229 je L(10) /* yes => return */
231 movb 3(%edx), %cl /* get byte from string */
232 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
233 jne L(7) /* no => start loop again */
235 incl %edx /* adjust pointer */
239 L(8): cmpl %eax, %edx
240 je L(returnNULL) /* There was no token anymore. */
242 movb $0, (%edx) /* Terminate string. */
244 /* Are we at end of string? */
249 /* Store the pointer to the next character. */
250 # ifdef USE_AS_STRTOK_R
251 movl SAVE(%esp), %ecx
254 CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
255 RETURN_BOUNDED_POINTER (SAVE_PTR)
258 /* Remove the stopset table. */
260 #if !defined USE_AS_STRTOK_R && defined PIC
268 RETURN_NULL_BOUNDED_POINTER
271 END (BP_SYM (FUNCTION))