]>
Commit | Line | Data |
---|---|---|
59dd8641 RM |
1 | /* strtok (str, delim) -- Return next DELIM separated token from STR. |
2 | For Intel 80x86, x>=3. | |
3 | Copyright (C) 1996 Free Software Foundation, Inc. | |
4 | This file is part of the GNU C Library. | |
5 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. | |
6 | ||
7 | The GNU C Library is free software; you can redistribute it and/or | |
8 | modify it under the terms of the GNU Library General Public License as | |
9 | published by the Free Software Foundation; either version 2 of the | |
10 | License, or (at your option) any later version. | |
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 | |
15 | Library General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU Library General Public | |
18 | License along with the GNU C Library; see the file COPYING.LIB. If | |
19 | not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | Boston, MA 02111-1307, USA. */ | |
21 | ||
59dd8641 RM |
22 | #include <sysdep.h> |
23 | ||
24 | /* This file can be used for three variants of the strtok function: | |
25 | ||
26 | strtok: | |
27 | INPUT PARAMETER: | |
28 | str (sp + 4) | |
29 | delim (sp + 8) | |
30 | ||
31 | strtok_r: | |
32 | INPUT PARAMETER: | |
33 | str (sp + 4) | |
34 | delim (sp + 8) | |
35 | save_ptr (sp + 12) | |
36 | ||
59dd8641 RM |
37 | We do a common implementation here. */ |
38 | ||
76060ec0 | 39 | #ifndef USE_AS_STRTOK_R |
59dd8641 RM |
40 | .bss |
41 | .local save_ptr | |
42 | ASM_TYPE_DIRECTIVE (save_ptr, @object) | |
43 | .size save_ptr, 4 | |
44 | save_ptr: | |
45 | .space 4 | |
46 | ||
47 | #define FUNCTION strtok | |
48 | #endif | |
49 | ||
59dd8641 | 50 | .text |
59dd8641 RM |
51 | |
52 | ENTRY (FUNCTION) | |
53 | ||
54 | movl 4(%esp), %edx /* Get start of string. */ | |
55 | movl 8(%esp), %eax /* Get start of delimiter set. */ | |
56 | ||
76060ec0 | 57 | #if !defined (USE_AS_STRTOK_R) && defined (PIC) |
59dd8641 RM |
58 | pushl %ebx /* Save PIC register. */ |
59 | call Lhere | |
60 | Lhere: popl %ebx | |
61 | addl $_GLOBAL_OFFSET_TABLE_+[.-Lhere], %ebx | |
76060ec0 | 62 | #endif |
59dd8641 RM |
63 | |
64 | /* If the pointer is NULL we have to use the stored value of | |
65 | the last run. */ | |
66 | cmpl $0, %edx | |
67 | jne L0 | |
68 | ||
76060ec0 | 69 | #ifdef USE_AS_STRTOK_R |
59dd8641 RM |
70 | /* The value is stored in the third argument. */ |
71 | movl 12(%esp), %edx | |
72 | movl (%edx), %edx | |
76060ec0 | 73 | #else |
59dd8641 RM |
74 | /* The value is in the local variable defined above. But |
75 | we have to take care for PIC code. */ | |
76060ec0 | 76 | # ifndef PIC |
59dd8641 | 77 | movl save_ptr, %edx |
76060ec0 | 78 | # else |
59dd8641 | 79 | movl save_ptr@GOTOFF(%ebx), %edx |
59dd8641 RM |
80 | # endif |
81 | #endif | |
82 | ||
59dd8641 | 83 | L0: |
59dd8641 RM |
84 | /* First we create a table with flags for all possible characters. |
85 | For the ASCII (7bit/8bit) or ISO-8859-X character sets which are | |
86 | supported by the C string functions we have 256 characters. | |
87 | Before inserting marks for the stop characters we clear the whole | |
88 | table. The unrolled form is much faster than a loop. */ | |
89 | xorl %ecx, %ecx /* %ecx = 0 !!! */ | |
90 | ||
91 | pushl %ecx /* make a 256 bytes long block filled with 0 */ | |
92 | pushl %ecx | |
93 | pushl %ecx | |
94 | pushl %ecx | |
95 | pushl %ecx | |
96 | pushl %ecx | |
97 | pushl %ecx | |
98 | pushl %ecx | |
99 | pushl %ecx | |
100 | pushl %ecx | |
101 | pushl %ecx | |
102 | pushl %ecx | |
103 | pushl %ecx | |
104 | pushl %ecx | |
105 | pushl %ecx | |
106 | pushl %ecx | |
107 | pushl %ecx | |
108 | pushl %ecx | |
109 | pushl %ecx | |
110 | pushl %ecx | |
111 | pushl %ecx | |
112 | pushl %ecx | |
113 | pushl %ecx | |
114 | pushl %ecx | |
115 | pushl %ecx | |
116 | pushl %ecx | |
117 | pushl %ecx | |
118 | pushl %ecx | |
119 | pushl %ecx | |
120 | pushl %ecx | |
121 | pushl %ecx | |
122 | pushl %ecx | |
123 | pushl %ecx | |
124 | pushl %ecx | |
125 | pushl %ecx | |
126 | pushl %ecx | |
127 | pushl %ecx | |
128 | pushl %ecx | |
129 | pushl %ecx | |
130 | pushl %ecx | |
131 | pushl %ecx | |
132 | pushl %ecx | |
133 | pushl %ecx | |
134 | pushl %ecx | |
135 | pushl %ecx | |
136 | pushl %ecx | |
137 | pushl %ecx | |
138 | pushl %ecx | |
139 | pushl %ecx | |
140 | pushl %ecx | |
141 | pushl %ecx | |
142 | pushl %ecx | |
143 | pushl %ecx | |
144 | pushl %ecx | |
145 | pushl %ecx | |
146 | pushl %ecx | |
147 | pushl %ecx | |
148 | pushl %ecx | |
149 | pushl $0 /* These immediate values make the label 2 */ | |
150 | pushl $0 /* to be aligned on a 16 byte boundary to */ | |
151 | pushl $0 /* get a better performance of the loop. */ | |
152 | pushl $0 | |
153 | pushl $0 | |
154 | pushl $0 | |
155 | ||
156 | /* For understanding the following code remember that %ecx == 0 now. | |
157 | Although all the following instruction only modify %cl we always | |
158 | have a correct zero-extended 32-bit value in %ecx. */ | |
159 | ||
160 | L2: movb (%eax), %cl /* get byte from stopset */ | |
161 | testb %cl, %cl /* is NUL char? */ | |
162 | jz L1 /* yes => start compare loop */ | |
163 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ | |
164 | ||
165 | movb 1(%eax), %cl /* get byte from stopset */ | |
166 | testb $0xff, %cl /* is NUL char? */ | |
167 | jz L1 /* yes => start compare loop */ | |
168 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ | |
169 | ||
170 | movb 2(%eax), %cl /* get byte from stopset */ | |
171 | testb $0xff, %cl /* is NUL char? */ | |
172 | jz L1 /* yes => start compare loop */ | |
173 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ | |
174 | ||
175 | movb 3(%eax), %cl /* get byte from stopset */ | |
176 | addl $4, %eax /* increment stopset pointer */ | |
177 | movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ | |
178 | testb $0xff, %cl /* is NUL char? */ | |
179 | jnz L2 /* no => process next dword from stopset */ | |
180 | ||
181 | L1: leal -4(%edx), %eax /* prepare loop */ | |
182 | ||
183 | /* We use a neat trick for the following loop. Normally we would | |
184 | have to test for two termination conditions | |
185 | 1. a character in the stopset was found | |
186 | and | |
187 | 2. the end of the string was found | |
76060ec0 RM |
188 | As a sign that the character is in the stopset we store its |
189 | value in the table. The value of NUL is NUL so the loop | |
59dd8641 RM |
190 | terminates for NUL in every case. */ |
191 | ||
192 | L3: addl $4, %eax /* adjust pointer for full loop round */ | |
193 | ||
194 | movb (%eax), %cl /* get byte from string */ | |
195 | testb %cl, (%esp,%ecx) /* is it contained in stopset? */ | |
196 | jz L4 /* no => start of token */ | |
197 | ||
198 | movb 1(%eax), %cl /* get byte from string */ | |
199 | testb %cl, (%esp,%ecx) /* is it contained in stopset? */ | |
200 | jz L5 /* no => start of token */ | |
201 | ||
202 | movb 2(%eax), %cl /* get byte from string */ | |
203 | testb %cl, (%esp,%ecx) /* is it contained in stopset? */ | |
204 | jz L6 /* no => start of token */ | |
205 | ||
206 | movb 3(%eax), %cl /* get byte from string */ | |
207 | testb %cl, (%esp,%ecx) /* is it contained in stopset? */ | |
208 | jnz L3 /* yes => start of loop */ | |
209 | ||
210 | incl %eax /* adjust pointer */ | |
211 | L6: incl %eax | |
212 | L5: incl %eax | |
213 | ||
214 | /* Now we have to terminate the string. */ | |
215 | ||
216 | L4: leal -4(%eax), %edx /* We use %EDX for the next run. */ | |
217 | ||
218 | L7: addl $4, %edx /* adjust pointer for full loop round */ | |
219 | ||
220 | movb (%edx), %cl /* get byte from string */ | |
221 | cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */ | |
222 | je L8 /* yes => return */ | |
223 | ||
224 | movb 1(%edx), %cl /* get byte from string */ | |
225 | cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */ | |
226 | je L9 /* yes => return */ | |
227 | ||
228 | movb 2(%edx), %cl /* get byte from string */ | |
229 | cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */ | |
230 | je L10 /* yes => return */ | |
231 | ||
232 | movb 3(%edx), %cl /* get byte from string */ | |
233 | cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */ | |
234 | jne L7 /* no => start loop again */ | |
235 | ||
236 | incl %edx /* adjust pointer */ | |
237 | L10: incl %edx | |
238 | L9: incl %edx | |
239 | ||
240 | L8: /* Remove the stopset table. */ | |
241 | addl $256, %esp | |
242 | ||
243 | cmpl %eax, %edx | |
244 | je LreturnNULL /* There was no token anymore. */ | |
245 | ||
246 | movb $0, (%edx) /* Terminate string. */ | |
247 | ||
248 | /* Are we at end of string? */ | |
249 | cmpb $0, %cl | |
250 | je L11 | |
251 | ||
252 | incl %edx | |
253 | L11: | |
254 | ||
255 | /* Store the pointer to the next character. */ | |
256 | #ifdef USE_AS_STRTOK_R | |
257 | movl 12(%esp), %ecx | |
258 | movl %edx, (%ecx) | |
59dd8641 RM |
259 | #else |
260 | # ifndef PIC | |
261 | movl %edx, save_ptr | |
262 | # else | |
263 | movl %edx, save_ptr@GOTOFF(%ebx) | |
264 | popl %ebx | |
265 | # endif | |
266 | #endif | |
267 | ret | |
268 | ||
269 | LreturnNULL: | |
270 | xorl %eax, %eax | |
271 | ||
ffee1316 | 272 | /* Store current pointer for next round. */ |
59dd8641 RM |
273 | #ifdef USE_AS_STRTOK_R |
274 | movl 12(%esp), %ecx | |
ffee1316 | 275 | movl %edx, (%ecx) |
59dd8641 RM |
276 | #else |
277 | # ifndef PIC | |
ffee1316 | 278 | movl %edx, save_ptr |
59dd8641 | 279 | # else |
ffee1316 | 280 | movl %edx, save_ptr@GOTOFF(%ebx) |
59dd8641 RM |
281 | popl %ebx |
282 | # endif | |
283 | #endif | |
284 | ret | |
cccda09f | 285 | PSEUDO_END (FUNCTION) |