]>
Commit | Line | Data |
---|---|---|
63bda0c1 UD |
1 | /* strtok (str, delim) -- Return next DELIM separated token from STR. |
2 | For Intel 80686. | |
bc795d0b | 3 | Copyright (C) 1998, 2000, 2001, 2005, 2006 Free Software Foundation, Inc. |
63bda0c1 UD |
4 | This file is part of the GNU C Library. |
5 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. | |
6 | ||
7 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
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. | |
63bda0c1 UD |
11 | |
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 | |
41bdb6e2 | 15 | Lesser General Public License for more details. |
63bda0c1 | 16 | |
41bdb6e2 AJ |
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 | |
20 | 02111-1307 USA. */ | |
63bda0c1 UD |
21 | |
22 | #include <sysdep.h> | |
23 | #include "asm-syntax.h" | |
2fc08826 GM |
24 | #include "bp-sym.h" |
25 | #include "bp-asm.h" | |
63bda0c1 UD |
26 | |
27 | /* This file can be used for three variants of the strtok function: | |
28 | ||
29 | strtok: | |
30 | INPUT PARAMETER: | |
31 | str (sp + 4) | |
32 | delim (sp + 8) | |
33 | ||
34 | strtok_r: | |
35 | INPUT PARAMETER: | |
36 | str (sp + 4) | |
37 | delim (sp + 8) | |
38 | save_ptr (sp + 12) | |
39 | ||
40 | We do a common implementation here. */ | |
41 | ||
2ed5fd9a GM |
42 | #ifdef USE_AS_STRTOK_R |
43 | # define SAVE_PTR 0(%ecx) | |
44 | #else | |
63bda0c1 UD |
45 | .bss |
46 | .local save_ptr | |
47 | ASM_TYPE_DIRECTIVE (save_ptr, @object) | |
48 | .size save_ptr, 4 | |
49 | save_ptr: | |
2ed5fd9a GM |
50 | # if __BOUNDED_POINTERS__ |
51 | .space 12 | |
52 | # else | |
63bda0c1 | 53 | .space 4 |
2ed5fd9a | 54 | # endif |
63bda0c1 | 55 | |
2ed5fd9a GM |
56 | # ifdef PIC |
57 | # define SAVE_PTR save_ptr@GOTOFF(%ebx) | |
58 | # else | |
59 | # define SAVE_PTR save_ptr | |
60 | # endif | |
61 | ||
62 | # define FUNCTION strtok | |
63 | #endif | |
64 | ||
65 | #if !defined USE_AS_STRTOK_R && defined PIC | |
66 | # define PARMS LINKAGE+256+4 /* space for table and saved PIC register */ | |
67 | #else | |
68 | # define PARMS LINKAGE+256 /* space for table */ | |
69 | #endif | |
70 | #define RTN PARMS | |
71 | #define STR RTN+RTN_SIZE | |
72 | #define DELIM STR+PTR_SIZE | |
73 | #ifdef USE_AS_STRTOK_R | |
74 | # define SAVE DELIM+PTR_SIZE | |
63bda0c1 UD |
75 | #endif |
76 | ||
77 | .text | |
78 | ||
79 | #if !defined USE_AS_STRTOK_R && defined PIC | |
80 | 0: movl (%esp), %ebx | |
81 | ret | |
82 | #endif | |
83 | ||
2fc08826 GM |
84 | ENTRY (BP_SYM (FUNCTION)) |
85 | ENTER | |
63bda0c1 UD |
86 | |
87 | #if !defined USE_AS_STRTOK_R && defined PIC | |
88 | pushl %ebx /* Save PIC register. */ | |
1ad9da69 UD |
89 | cfi_adjust_cfa_offset (4) |
90 | cfi_rel_offset (ebx, 0) | |
63bda0c1 UD |
91 | call 0b |
92 | addl $_GLOBAL_OFFSET_TABLE_, %ebx | |
93 | #endif | |
94 | ||
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 | |
99 | table. */ | |
100 | movl %edi, %edx | |
101 | subl $256, %esp | |
1ad9da69 | 102 | cfi_adjust_cfa_offset (256) |
63bda0c1 UD |
103 | movl $64, %ecx |
104 | movl %esp, %edi | |
105 | xorl %eax, %eax | |
118bad87 | 106 | cld |
63bda0c1 UD |
107 | rep |
108 | stosl | |
109 | ||
110 | /* Note: %ecx = 0 !!! */ | |
111 | movl %edx, %edi | |
112 | ||
2ed5fd9a | 113 | movl STR(%esp), %edx /* Get start of string. */ |
63bda0c1 UD |
114 | |
115 | #ifdef USE_AS_STRTOK_R | |
116 | /* The value is stored in the third argument. */ | |
2ed5fd9a | 117 | movl SAVE(%esp), %eax |
63bda0c1 UD |
118 | movl (%eax), %eax |
119 | #else | |
120 | /* The value is in the local variable defined above. But | |
121 | we have to take care for PIC code. */ | |
2ed5fd9a | 122 | movl SAVE_PTR, %eax |
63bda0c1 UD |
123 | #endif |
124 | ||
125 | /* If the pointer is NULL we have to use the stored value of | |
126 | the last run. */ | |
127 | cmpl $0, %edx | |
128 | cmove %eax, %edx | |
1999031e UD |
129 | testl %edx, %edx |
130 | jz L(returnNULL) | |
2ed5fd9a GM |
131 | #if __BOUNDED_POINTERS__ |
132 | # ifdef USE_AS_STRTOK_R | |
133 | movl SAVE(%esp), %ecx /* borrow %ecx for a moment */ | |
134 | # endif | |
135 | je L(0) | |
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 */ | |
144 | # endif | |
63bda0c1 | 145 | #endif |
2ed5fd9a GM |
146 | movl DELIM(%esp), %eax /* Get start of delimiter set. */ |
147 | CHECK_BOUNDS_LOW (%eax, DELIM(%esp)) | |
63bda0c1 UD |
148 | |
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. */ | |
152 | ||
153 | L(2): movb (%eax), %cl /* get byte from stopset */ | |
154 | testb %cl, %cl /* is NUL char? */ | |
2ed5fd9a | 155 | jz L(1_1) /* yes => start compare loop */ |
63bda0c1 UD |
156 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
157 | ||
158 | movb 1(%eax), %cl /* get byte from stopset */ | |
159 | testb $0xff, %cl /* is NUL char? */ | |
2ed5fd9a | 160 | jz L(1_2) /* yes => start compare loop */ |
63bda0c1 UD |
161 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
162 | ||
163 | movb 2(%eax), %cl /* get byte from stopset */ | |
164 | testb $0xff, %cl /* is NUL char? */ | |
2ed5fd9a | 165 | jz L(1_3) /* yes => start compare loop */ |
63bda0c1 UD |
166 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ |
167 | ||
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 */ | |
173 | ||
2ed5fd9a GM |
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) | |
180 | #else | |
181 | L(1_3):; L(1_2):; L(1_1): /* fall through */ | |
182 | #endif | |
183 | leal -4(%edx), %eax /* prepare loop */ | |
63bda0c1 UD |
184 | |
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 | |
188 | and | |
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. */ | |
193 | ||
194 | L(3): addl $4, %eax /* adjust pointer for full loop round */ | |
195 | ||
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 */ | |
199 | ||
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 */ | |
203 | ||
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 */ | |
207 | ||
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 */ | |
211 | ||
212 | incl %eax /* adjust pointer */ | |
213 | L(6): incl %eax | |
214 | L(5): incl %eax | |
215 | ||
216 | /* Now we have to terminate the string. */ | |
217 | ||
218 | L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */ | |
219 | ||
220 | L(7): addl $4, %edx /* adjust pointer for full loop round */ | |
221 | ||
222 | movb (%edx), %cl /* get byte from string */ | |
223 | cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */ | |
224 | je L(8) /* yes => return */ | |
225 | ||
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 */ | |
229 | ||
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 */ | |
233 | ||
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 */ | |
237 | ||
238 | incl %edx /* adjust pointer */ | |
239 | L(10): incl %edx | |
240 | L(9): incl %edx | |
241 | ||
2ed5fd9a | 242 | L(8): cmpl %eax, %edx |
63bda0c1 UD |
243 | je L(returnNULL) /* There was no token anymore. */ |
244 | ||
245 | movb $0, (%edx) /* Terminate string. */ | |
246 | ||
247 | /* Are we at end of string? */ | |
248 | cmpb $0, %cl | |
249 | leal 1(%edx), %ecx | |
250 | cmovne %ecx, %edx | |
251 | ||
252 | /* Store the pointer to the next character. */ | |
bc795d0b | 253 | #ifdef USE_AS_STRTOK_R |
2ed5fd9a | 254 | movl SAVE(%esp), %ecx |
bc795d0b | 255 | #endif |
2ed5fd9a GM |
256 | movl %edx, SAVE_PTR |
257 | CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb) | |
258 | RETURN_BOUNDED_POINTER (SAVE_PTR) | |
259 | ||
260 | L(epilogue): | |
261 | /* Remove the stopset table. */ | |
262 | addl $256, %esp | |
1ad9da69 | 263 | cfi_adjust_cfa_offset (-256) |
2ed5fd9a GM |
264 | #if !defined USE_AS_STRTOK_R && defined PIC |
265 | popl %ebx | |
1ad9da69 UD |
266 | cfi_adjust_cfa_offset (-4) |
267 | cfi_restore (ebx) | |
63bda0c1 | 268 | #endif |
2ed5fd9a GM |
269 | LEAVE |
270 | RET_PTR | |
63bda0c1 UD |
271 | |
272 | L(returnNULL): | |
273 | xorl %eax, %eax | |
bc795d0b UD |
274 | #ifdef USE_AS_STRTOK_R |
275 | movl SAVE(%esp), %ecx | |
276 | #endif | |
277 | movl %edx, SAVE_PTR | |
2ed5fd9a GM |
278 | RETURN_NULL_BOUNDED_POINTER |
279 | jmp L(epilogue) | |
280 | ||
2fc08826 | 281 | END (BP_SYM (FUNCTION)) |