Browse Source

[libc] Rewrite string functions

Some of the C library string functions have an unknown provenance.
Reimplement all such functions to avoid potential licensing
uncertainty.

Remove the inline-assembler versions of strlen(), memswap(), and
strncmp(); these save a minimal amount of space (around 40 bytes in
total) and are not performance-critical.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
8ee39f7432
6 changed files with 371 additions and 403 deletions
  1. 0
    84
      src/arch/x86/core/x86_string.c
  2. 0
    18
      src/arch/x86/include/bits/string.h
  3. 273
    258
      src/core/string.c
  4. 1
    1
      src/hci/strerror.c
  5. 42
    35
      src/include/string.h
  6. 55
    7
      src/include/strings.h

+ 0
- 84
src/arch/x86/core/x86_string.c View File

@@ -104,87 +104,3 @@ void * __memmove ( void *dest, const void *src, size_t len ) {
104 104
 		return __memcpy_reverse ( dest, src, len );
105 105
 	}
106 106
 }
107
-
108
-/**
109
- * Swap memory areas
110
- *
111
- * @v dest		Destination address
112
- * @v src		Source address
113
- * @v len		Length
114
- * @ret dest		Destination address
115
- */
116
-void * memswap ( void *dest, void *src, size_t len ) {
117
-	size_t discard_c;
118
-	int discard;
119
-
120
-	__asm__ __volatile__ ( "\n1:\n\t"
121
-			       "dec %2\n\t"
122
-			       "js 2f\n\t"
123
-			       "movb (%0,%2), %b3\n\t"
124
-			       "xchgb (%1,%2), %b3\n\t"
125
-			       "movb %b3, (%0,%2)\n\t"
126
-			       "jmp 1b\n\t"
127
-			       "2:\n\t"
128
-			       : "=r" ( src ), "=r" ( dest ),
129
-				 "=&c" ( discard_c ), "=&q" ( discard )
130
-			       : "0" ( src ), "1" ( dest ), "2" ( len )
131
-			       : "memory" );
132
-
133
-	return dest;
134
-}
135
-
136
-/**
137
- * Calculate length of string
138
- *
139
- * @v string		String
140
- * @ret len		Length (excluding NUL)
141
- */
142
-size_t strlen ( const char *string ) {
143
-	const char *discard_D;
144
-	size_t len_plus_one;
145
-
146
-	__asm__ __volatile__ ( "repne scasb\n\t"
147
-			       "not %1\n\t"
148
-			       : "=&D" ( discard_D ), "=&c" ( len_plus_one )
149
-			       : "0" ( string ), "1" ( -1UL ), "a" ( 0 ) );
150
-
151
-	return ( len_plus_one - 1 );
152
-}
153
-
154
-/**
155
- * Compare strings (up to a specified length)
156
- *
157
- * @v str1		First string
158
- * @v str2		Second string
159
- * @v len		Maximum length
160
- * @ret diff		Difference
161
- */
162
-int strncmp ( const char *str1, const char *str2, size_t len ) {
163
-	const void *discard_S;
164
-	const void *discard_D;
165
-	size_t discard_c;
166
-	int diff;
167
-
168
-	__asm__ __volatile__ ( "\n1:\n\t"
169
-			       "dec %2\n\t"
170
-			       "js 2f\n\t"
171
-			       "lodsb\n\t"
172
-			       "scasb\n\t"
173
-			       "jne 3f\n\t"
174
-			       "testb %b3, %b3\n\t"
175
-			       "jnz 1b\n\t"
176
-			       /* Equal */
177
-			       "\n2:\n\t"
178
-			       "xor %3, %3\n\t"
179
-			       "jmp 4f\n\t"
180
-			       /* Not equal; CF indicates difference */
181
-			       "\n3:\n\t"
182
-			       "sbb %3, %3\n\t"
183
-			       "orb $1, %b3\n\t"
184
-			       "\n4:\n\t"
185
-			       : "=&S" ( discard_S ), "=&D" ( discard_D ),
186
-				 "=&c" ( discard_c ), "=&a" ( diff )
187
-			       : "0" ( str1 ), "1" ( str2 ), "2" ( len ) );
188
-
189
-	return diff;
190
-}

+ 0
- 18
src/arch/x86/include/bits/string.h View File

@@ -28,8 +28,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
28 28
  *
29 29
  */
30 30
 
31
-#define __HAVE_ARCH_MEMCPY
32
-
33 31
 extern void * __memcpy ( void *dest, const void *src, size_t len );
34 32
 extern void * __memcpy_reverse ( void *dest, const void *src, size_t len );
35 33
 
@@ -169,8 +167,6 @@ memcpy ( void *dest, const void *src, size_t len ) {
169 167
 	}
170 168
 }
171 169
 
172
-#define __HAVE_ARCH_MEMMOVE
173
-
174 170
 extern void * __memmove ( void *dest, const void *src, size_t len );
175 171
 
176 172
 /**
@@ -196,8 +192,6 @@ memmove ( void *dest, const void *src, size_t len ) {
196 192
 	}
197 193
 }
198 194
 
199
-#define __HAVE_ARCH_MEMSET
200
-
201 195
 /**
202 196
  * Fill memory region
203 197
  *
@@ -217,16 +211,4 @@ static inline void * memset ( void *dest, int fill, size_t len ) {
217 211
 	return dest;
218 212
 }
219 213
 
220
-#define __HAVE_ARCH_MEMSWAP
221
-
222
-extern void * memswap ( void *dest, void *src, size_t len );
223
-
224
-#define __HAVE_ARCH_STRNCMP
225
-
226
-extern int strncmp ( const char *str1, const char *str2, size_t len );
227
-
228
-#define __HAVE_ARCH_STRLEN
229
-
230
-extern size_t strlen ( const char *string );
231
-
232 214
 #endif /* X86_BITS_STRING_H */

+ 273
- 258
src/core/string.c View File

@@ -1,353 +1,368 @@
1 1
 /*
2
- *  Copyright (C) 1991, 1992  Linus Torvalds
3
- *  Copyright (C) 2004 Tobias Lorenz
2
+ * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
4 3
  *
5
- *  string handling functions
6
- *  based on linux/lib/string.c
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or (at your option) any later version.
7 8
  *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License version 2 as
10
- * published by the Free Software Foundation.
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
11 18
  */
12 19
 
13
-FILE_LICENCE ( GPL2_ONLY );
20
+FILE_LICENCE ( GPL2_OR_LATER );
14 21
 
15
-/*
16
- * stupid library routines.. The optimized versions should generally be found
17
- * as inline code in <asm-xx/string.h>
18
- *
19
- * These are buggy as well..
20
- *
21
- * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
22
- * -  Added strsep() which will replace strtok() soon (because strsep() is
23
- *    reentrant and should be faster). Use only strsep() in new code, please.
24
- */
25
- 
22
+#include <stddef.h>
26 23
 #include <stdint.h>
27 24
 #include <stdlib.h>
28 25
 #include <string.h>
29 26
 #include <ctype.h>
30 27
 
31
-/* *** FROM string.c *** */
28
+/** @file
29
+ *
30
+ * String functions
31
+ *
32
+ */
32 33
 
33
-#ifndef __HAVE_ARCH_STRCPY
34 34
 /**
35
- * strcpy - Copy a %NUL terminated string
36
- * @dest: Where to copy the string to
37
- * @src: Where to copy the string from
35
+ * Fill memory region
36
+ *
37
+ * @v dest		Destination region
38
+ * @v character		Fill character
39
+ * @v len		Length
40
+ * @ret dest		Destination region
38 41
  */
39
-char * strcpy(char * dest,const char *src)
40
-{
41
-	char *tmp = dest;
42
+void * generic_memset ( void *dest, int character, size_t len ) {
43
+	uint8_t *dest_bytes = dest;
42 44
 
43
-	while ((*dest++ = *src++) != '\0')
44
-		/* nothing */;
45
-	return tmp;
45
+	while ( len-- )
46
+		*(dest_bytes++) = character;
47
+	return dest;
46 48
 }
47
-#endif
48 49
 
49
-#ifndef __HAVE_ARCH_STRNCPY
50 50
 /**
51
- * strncpy - Copy a length-limited, %NUL-terminated string
52
- * @dest: Where to copy the string to
53
- * @src: Where to copy the string from
54
- * @count: The maximum number of bytes to copy
51
+ * Copy memory region
55 52
  *
56
- * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
57
- * However, the result is not %NUL-terminated if the source exceeds
58
- * @count bytes.
53
+ * @v dest		Destination region
54
+ * @v src		Source region
55
+ * @v len		Length
56
+ * @ret dest		Destination region
59 57
  */
60
-char * strncpy(char * dest,const char *src,size_t count)
61
-{
62
-	char *tmp = dest;
63
-
64
-	while (count-- && (*dest++ = *src++) != '\0')
65
-		/* nothing */;
58
+void * generic_memcpy ( void *dest, const void *src, size_t len ) {
59
+	const uint8_t *src_bytes = src;
60
+	uint8_t *dest_bytes = dest;
66 61
 
67
-	return tmp;
62
+	while ( len-- )
63
+		*(dest_bytes++) = *(src_bytes++);
64
+	return dest;
68 65
 }
69
-#endif
70 66
 
71
-#ifndef __HAVE_ARCH_STRCAT
72 67
 /**
73
- * strcat - Append one %NUL-terminated string to another
74
- * @dest: The string to be appended to
75
- * @src: The string to append to it
68
+ * Copy (possibly overlapping) memory region
69
+ *
70
+ * @v dest		Destination region
71
+ * @v src		Source region
72
+ * @v len		Length
73
+ * @ret dest		Destination region
76 74
  */
77
-char * strcat(char * dest, const char * src)
78
-{
79
-	char *tmp = dest;
80
-
81
-	while (*dest)
82
-		dest++;
83
-	while ((*dest++ = *src++) != '\0')
84
-		;
85
-
86
-	return tmp;
75
+void * generic_memmove ( void *dest, const void *src, size_t len ) {
76
+	const uint8_t *src_bytes = ( src + len );
77
+	uint8_t *dest_bytes = ( dest + len );
78
+
79
+	if ( dest < src )
80
+		return memcpy ( dest, src, len );
81
+	while ( len-- )
82
+		*(--dest_bytes) = *(--src_bytes);
83
+	return dest;
87 84
 }
88
-#endif
89 85
 
90
-#ifndef __HAVE_ARCH_STRCMP
91 86
 /**
92
- * strcmp - Compare two strings
93
- * @cs: One string
94
- * @ct: Another string
87
+ * Compare memory regions
88
+ *
89
+ * @v first		First region
90
+ * @v second		Second region
91
+ * @v len		Length
92
+ * @ret diff		Difference
95 93
  */
96
-int strcmp(const char * cs,const char * ct)
97
-{
98
-	register signed char __res;
99
-
100
-	while (1) {
101
-		if ((__res = *cs - *ct++) != 0 || !*cs++)
102
-			break;
94
+int memcmp ( const void *first, const void *second, size_t len ) {
95
+	const uint8_t *first_bytes = first;
96
+	const uint8_t *second_bytes = second;
97
+	int diff;
98
+
99
+	while ( len-- ) {
100
+		diff = ( *(second_bytes++) - *(first_bytes++) );
101
+		if ( diff )
102
+			return diff;
103 103
 	}
104
-
105
-	return __res;
104
+	return 0;
106 105
 }
107
-#endif
108 106
 
109
-#ifndef __HAVE_ARCH_STRNCMP
110 107
 /**
111
- * strncmp - Compare two length-limited strings
112
- * @cs: One string
113
- * @ct: Another string
114
- * @count: The maximum number of bytes to compare
108
+ * Find character within a memory region
109
+ *
110
+ * @v src		Source region
111
+ * @v character		Character to find
112
+ * @v len		Length
113
+ * @ret found		Found character, or NULL if not found
115 114
  */
116
-int strncmp(const char * cs,const char * ct,size_t count)
117
-{
118
-	register signed char __res = 0;
115
+void * memchr ( const void *src, int character, size_t len ) {
116
+	const uint8_t *src_bytes = src;
119 117
 
120
-	while (count) {
121
-		if ((__res = *cs - *ct++) != 0 || !*cs++)
122
-			break;
123
-		count--;
118
+	for ( ; len-- ; src_bytes++ ) {
119
+		if ( *src_bytes == character )
120
+			return ( ( void * ) src_bytes );
124 121
 	}
125
-
126
-	return __res;
122
+	return NULL;
127 123
 }
128
-#endif
129 124
 
130
-#ifndef __HAVE_ARCH_STRCASECMP
131
-int strcasecmp(const char *a, const char *b)
132
-{
133
-	while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; }
134
-	return((*a & ~0x20) - (*b & ~0x20));
125
+/**
126
+ * Swap memory regions
127
+ *
128
+ * @v first		First region
129
+ * @v second		Second region
130
+ * @v len		Length
131
+ * @ret first		First region
132
+ */
133
+void * memswap ( void *first, void *second, size_t len ) {
134
+	uint8_t *first_bytes = first;
135
+	uint8_t *second_bytes = second;
136
+	uint8_t temp;
137
+
138
+	for ( ; len-- ; first_bytes++, second_bytes++ ) {
139
+		temp = *first_bytes;
140
+		*first_bytes = *second_bytes;
141
+		*second_bytes = temp;
142
+	}
143
+	return first;
135 144
 }
136
-#endif
137 145
 
138
-#ifndef __HAVE_ARCH_STRCHR
139 146
 /**
140
- * strchr - Find the first occurrence of a character in a string
141
- * @s: The string to be searched
142
- * @c: The character to search for
147
+ * Compare strings
148
+ *
149
+ * @v first		First string
150
+ * @v second		Second string
151
+ * @ret diff		Difference
143 152
  */
144
-char * strchr(const char * s, int c)
145
-{
146
-	for(; *s != (char) c; ++s)
147
-		if (*s == '\0')
148
-			return NULL;
149
-	return (char *) s;
153
+int strcmp ( const char *first, const char *second ) {
154
+
155
+	return strncmp ( first, second, ~( ( size_t ) 0 ) );
150 156
 }
151
-#endif
152 157
 
153
-#ifndef __HAVE_ARCH_STRRCHR
154 158
 /**
155
- * strrchr - Find the last occurrence of a character in a string
156
- * @s: The string to be searched
157
- * @c: The character to search for
159
+ * Compare strings
160
+ *
161
+ * @v first		First string
162
+ * @v second		Second string
163
+ * @v max		Maximum length to compare
164
+ * @ret diff		Difference
158 165
  */
159
-char * strrchr(const char * s, int c)
160
-{
161
-       const char *p = s + strlen(s);
162
-       do {
163
-           if (*p == (char)c)
164
-               return (char *)p;
165
-       } while (--p >= s);
166
-       return NULL;
166
+int strncmp ( const char *first, const char *second, size_t max ) {
167
+	const uint8_t *first_bytes = ( ( const uint8_t * ) first );
168
+	const uint8_t *second_bytes = ( ( const uint8_t * ) second );
169
+	int diff;
170
+
171
+	for ( ; max-- ; first_bytes++, second_bytes++ ) {
172
+		diff = ( *second_bytes - *first_bytes );
173
+		if ( diff )
174
+			return diff;
175
+		if ( ! *first_bytes )
176
+			return 0;
177
+	}
178
+	return 0;
167 179
 }
168
-#endif
169 180
 
170
-#ifndef __HAVE_ARCH_STRLEN
171 181
 /**
172
- * strlen - Find the length of a string
173
- * @s: The string to be sized
182
+ * Compare case-insensitive strings
183
+ *
184
+ * @v first		First string
185
+ * @v second		Second string
186
+ * @ret diff		Difference
174 187
  */
175
-size_t strlen(const char * s)
176
-{
177
-	const char *sc;
178
-
179
-	for (sc = s; *sc != '\0'; ++sc)
180
-		/* nothing */;
181
-	return sc - s;
188
+int strcasecmp ( const char *first, const char *second ) {
189
+	const uint8_t *first_bytes = ( ( const uint8_t * ) first );
190
+	const uint8_t *second_bytes = ( ( const uint8_t * ) second );
191
+	int diff;
192
+
193
+	for ( ; ; first_bytes++, second_bytes++ ) {
194
+		diff = ( toupper ( *second_bytes ) -
195
+			 toupper ( *first_bytes ) );
196
+		if ( diff )
197
+			return diff;
198
+		if ( ! *first_bytes )
199
+			return 0;
200
+	}
182 201
 }
183
-#endif
184 202
 
185
-#ifndef __HAVE_ARCH_STRNLEN
186 203
 /**
187
- * strnlen - Find the length of a length-limited string
188
- * @s: The string to be sized
189
- * @count: The maximum number of bytes to search
204
+ * Get length of string
205
+ *
206
+ * @v src		String
207
+ * @ret len		Length
190 208
  */
191
-size_t strnlen(const char * s, size_t count)
192
-{
193
-	const char *sc;
209
+size_t strlen ( const char *src ) {
194 210
 
195
-	for (sc = s; count-- && *sc != '\0'; ++sc)
196
-		/* nothing */;
197
-	return sc - s;
211
+	return strnlen ( src, ~( ( size_t ) 0 ) );
198 212
 }
199
-#endif
200 213
 
201
-#ifndef __HAVE_ARCH_MEMSET
202 214
 /**
203
- * memset - Fill a region of memory with the given value
204
- * @s: Pointer to the start of the area.
205
- * @c: The byte to fill the area with
206
- * @count: The size of the area.
215
+ * Get length of string
207 216
  *
208
- * Do not use memset() to access IO space, use memset_io() instead.
217
+ * @v src		String
218
+ * @v max		Maximum length
219
+ * @ret len		Length
209 220
  */
210
-void * memset(void * s,int c,size_t count)
211
-{
212
-	char *xs = (char *) s;
213
-
214
-	while (count--)
215
-		*xs++ = c;
221
+size_t strnlen ( const char *src, size_t max ) {
222
+	const uint8_t *src_bytes = ( ( const uint8_t * ) src );
223
+	size_t len = 0;
216 224
 
217
-	return s;
225
+	while ( max-- && *(src_bytes++) )
226
+		len++;
227
+	return len;
218 228
 }
219
-#endif
220 229
 
221
-#ifndef __HAVE_ARCH_MEMCPY
222 230
 /**
223
- * memcpy - Copy one area of memory to another
224
- * @dest: Where to copy to
225
- * @src: Where to copy from
226
- * @count: The size of the area.
231
+ * Find character within a string
227 232
  *
228
- * You should not use this function to access IO space, use memcpy_toio()
229
- * or memcpy_fromio() instead.
233
+ * @v src		String
234
+ * @v character		Character to find
235
+ * @ret found		Found character, or NULL if not found
230 236
  */
231
-void * memcpy(void * dest,const void *src,size_t count)
232
-{
233
-	char *tmp = (char *) dest, *s = (char *) src;
234
-
235
-	while (count--)
236
-		*tmp++ = *s++;
237
+char * strchr ( const char *src, int character ) {
238
+	const uint8_t *src_bytes = ( ( const uint8_t * ) src );
237 239
 
238
-	return dest;
240
+	for ( ; ; src_bytes++ ) {
241
+		if ( *src_bytes == character )
242
+			return ( ( char * ) src_bytes );
243
+		if ( ! *src_bytes )
244
+			return NULL;
245
+	}
239 246
 }
240
-#endif
241 247
 
242
-#ifndef __HAVE_ARCH_MEMMOVE
243 248
 /**
244
- * memmove - Copy one area of memory to another
245
- * @dest: Where to copy to
246
- * @src: Where to copy from
247
- * @count: The size of the area.
249
+ * Find rightmost character within a string
248 250
  *
249
- * Unlike memcpy(), memmove() copes with overlapping areas.
251
+ * @v src		String
252
+ * @v character		Character to find
253
+ * @ret found		Found character, or NULL if not found
250 254
  */
251
-void * memmove(void * dest,const void *src,size_t count)
252
-{
253
-	char *tmp, *s;
254
-
255
-	if (dest <= src) {
256
-		tmp = (char *) dest;
257
-		s = (char *) src;
258
-		while (count--)
259
-			*tmp++ = *s++;
260
-		}
261
-	else {
262
-		tmp = (char *) dest + count;
263
-		s = (char *) src + count;
264
-		while (count--)
265
-			*--tmp = *--s;
266
-		}
267
-
268
-	return dest;
255
+char * strrchr ( const char *src, int character ) {
256
+	const uint8_t *src_bytes = ( ( const uint8_t * ) src );
257
+	const uint8_t *start = src_bytes;
258
+
259
+	while ( *src_bytes )
260
+		src_bytes++;
261
+	for ( src_bytes-- ; src_bytes >= start ; src_bytes-- ) {
262
+		if ( *src_bytes == character )
263
+			return ( ( char * ) src_bytes );
264
+	}
265
+	return NULL;
269 266
 }
270
-#endif
271 267
 
272
-#ifndef __HAVE_ARCH_MEMCMP
273 268
 /**
274
- * memcmp - Compare two areas of memory
275
- * @cs: One area of memory
276
- * @ct: Another area of memory
277
- * @count: The size of the area.
269
+ * Find substring
270
+ *
271
+ * @v haystack		String
272
+ * @v needle		Substring
273
+ * @ret found		Found substring, or NULL if not found
278 274
  */
279
-int memcmp(const void * cs,const void * ct,size_t count)
280
-{
281
-	const unsigned char *su1, *su2;
282
-	int res = 0;
275
+char * strstr ( const char *haystack, const char *needle ) {
276
+	size_t len = strlen ( needle );
283 277
 
284
-	for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
285
-		if ((res = *su1 - *su2) != 0)
286
-			break;
287
-	return res;
278
+	for ( ; *haystack ; haystack++ ) {
279
+		if ( memcmp ( haystack, needle, len ) == 0 )
280
+			return ( ( char * ) haystack );
281
+	}
282
+	return NULL;
288 283
 }
289
-#endif
290 284
 
291
-#ifndef __HAVE_ARCH_STRSTR
292 285
 /**
293
- * strstr - Find the first substring in a %NUL terminated string
294
- * @s1: The string to be searched
295
- * @s2: The string to search for
286
+ * Copy string
287
+ *
288
+ * @v dest		Destination string
289
+ * @v src		Source string
290
+ * @ret dest		Destination string
296 291
  */
297
-char * strstr(const char * s1,const char * s2)
298
-{
299
-	int l1, l2;
300
-
301
-	l2 = strlen(s2);
302
-	if (!l2)
303
-		return (char *) s1;
304
-	l1 = strlen(s1);
305
-	while (l1 >= l2) {
306
-		l1--;
307
-		if (!memcmp(s1,s2,l2))
308
-			return (char *) s1;
309
-		s1++;
292
+char * strcpy ( char *dest, const char *src ) {
293
+	const uint8_t *src_bytes = ( ( const uint8_t * ) src );
294
+	uint8_t *dest_bytes = ( ( uint8_t * ) dest );
295
+
296
+	/* We cannot use strncpy(), since that would pad the destination */
297
+	for ( ; ; src_bytes++, dest_bytes++ ) {
298
+		*dest_bytes = *src_bytes;
299
+		if ( ! *dest_bytes )
300
+			break;
310 301
 	}
311
-	return NULL;
302
+	return dest;
312 303
 }
313
-#endif
314 304
 
315
-#ifndef __HAVE_ARCH_MEMCHR
316 305
 /**
317
- * memchr - Find a character in an area of memory.
318
- * @s: The memory area
319
- * @c: The byte to search for
320
- * @n: The size of the area.
306
+ * Copy string
321 307
  *
322
- * returns the address of the first occurrence of @c, or %NULL
323
- * if @c is not found
308
+ * @v dest		Destination string
309
+ * @v src		Source string
310
+ * @v max		Maximum length
311
+ * @ret dest		Destination string
324 312
  */
325
-void * memchr(const void *s, int c, size_t n)
326
-{
327
-	const unsigned char *p = s;
328
-	while (n-- != 0) {
329
-        	if ((unsigned char)c == *p++) {
330
-			return (void *)(p-1);
331
-		}
313
+char * strncpy ( char *dest, const char *src, size_t max ) {
314
+	const uint8_t *src_bytes = ( ( const uint8_t * ) src );
315
+	uint8_t *dest_bytes = ( ( uint8_t * ) dest );
316
+
317
+	for ( ; max ; max--, src_bytes++, dest_bytes++ ) {
318
+		*dest_bytes = *src_bytes;
319
+		if ( ! *dest_bytes )
320
+			break;
332 321
 	}
333
-	return NULL;
322
+	while ( max-- )
323
+		*(dest_bytes++) = '\0';
324
+	return dest;
334 325
 }
335 326
 
336
-#endif
327
+/**
328
+ * Concatenate string
329
+ *
330
+ * @v dest		Destination string
331
+ * @v src		Source string
332
+ * @ret dest		Destination string
333
+ */
334
+char * strcat ( char *dest, const char *src ) {
335
+
336
+	strcpy ( ( dest + strlen ( dest ) ), src );
337
+	return dest;
338
+}
337 339
 
338
-char * strndup(const char *s, size_t n)
339
-{
340
-        size_t len = strnlen(s,n);
341
-        char *new;
340
+/**
341
+ * Duplicate string
342
+ *
343
+ * @v src		Source string
344
+ * @ret dup		Duplicated string, or NULL if allocation failed
345
+ */
346
+char * strdup ( const char *src ) {
342 347
 
343
-        new = malloc(len+1);
344
-        if (new) {
345
-                new[len] = '\0';
346
-                memcpy(new,s,len);
347
-        }
348
-        return new;
348
+	return strndup ( src, ~( ( size_t ) 0 ) );
349 349
 }
350 350
 
351
-char * strdup(const char *s) {
352
-	return strndup(s, ~((size_t)0));
351
+/**
352
+ * Duplicate string
353
+ *
354
+ * @v src		Source string
355
+ * @v max		Maximum length
356
+ * @ret dup		Duplicated string, or NULL if allocation failed
357
+ */
358
+char * strndup ( const char *src, size_t max ) {
359
+	size_t len = strnlen ( src, max );
360
+        char *dup;
361
+
362
+        dup = malloc ( len + 1 /* NUL */ );
363
+        if ( dup ) {
364
+		memcpy ( dup, src, len );
365
+		dup[len] = '\0';
366
+        }
367
+        return dup;
353 368
 }

+ 1
- 1
src/hci/strerror.c View File

@@ -75,7 +75,7 @@ static struct errortab * find_closest_error ( int errno ) {
75 75
  * call to strerror().
76 76
  *
77 77
  */
78
-const char * strerror ( int errno ) {
78
+char * strerror ( int errno ) {
79 79
 	static char errbuf[64];
80 80
 	struct errortab *errortab;
81 81
 

+ 42
- 35
src/include/string.h View File

@@ -1,46 +1,53 @@
1
-/*
2
- *  Copyright (C) 1991, 1992  Linus Torvalds
3
- *  Copyright (C) 2004 Tobias Lorenz
1
+#ifndef _STRING_H
2
+#define _STRING_H
3
+
4
+/** @file
4 5
  *
5
- *  string handling functions
6
- *  based on linux/include/linux/ctype.h
7
- *       and linux/include/linux/string.h
6
+ * String functions
8 7
  *
9
- * This program is free software; you can redistribute it and/or modify
10
- * it under the terms of the GNU General Public License version 2 as
11
- * published by the Free Software Foundation.
12 8
  */
13 9
 
14
-FILE_LICENCE ( GPL2_ONLY );
15
-
16
-#ifndef ETHERBOOT_STRING_H
17
-#define ETHERBOOT_STRING_H
10
+FILE_LICENCE ( GPL2_OR_LATER );
18 11
 
19 12
 #include <stddef.h>
20 13
 #include <bits/string.h>
21 14
 
22
-char * strcpy(char * dest,const char *src) __nonnull;
23
-char * strncpy(char * dest,const char *src,size_t count) __nonnull;
24
-char * strcat(char * dest, const char * src) __nonnull;
25
-int __pure strcmp(const char * cs,const char * ct) __nonnull;
26
-int __pure strncmp(const char * cs,const char * ct,
27
-				     size_t count) __nonnull;
28
-char * __pure strchr(const char * s, int c) __nonnull;
29
-char * __pure strrchr(const char * s, int c) __nonnull;
30
-size_t __pure strlen(const char * s) __nonnull;
31
-size_t __pure strnlen(const char * s, size_t count) __nonnull;
32
-char * __pure strpbrk(const char * cs,const char * ct) __nonnull;
33
-char * strsep(char **s, const char *ct) __nonnull;
34
-void * memset(void * s,int c,size_t count) __nonnull;
15
+/* Architecture-specific code is expected to provide these functions,
16
+ * but may instead explicitly choose to use the generic versions.
17
+ */
18
+void * memset ( void *dest, int character, size_t len ) __nonnull;
35 19
 void * memcpy ( void *dest, const void *src, size_t len ) __nonnull;
36
-void * memmove(void * dest,const void *src,size_t count) __nonnull;
37
-int __pure memcmp(const void * cs,const void * ct,
38
-				    size_t count) __nonnull;
39
-char * __pure strstr(const char * s1,const char * s2) __nonnull;
40
-void * __pure memchr(const void *s, int c, size_t n) __nonnull;
41
-char * __malloc strdup(const char *s) __nonnull;
42
-char * __malloc strndup(const char *s, size_t n) __nonnull;
20
+void * memmove ( void *dest, const void *src, size_t len ) __nonnull;
21
+extern void * generic_memset ( void *dest, int character,
22
+			       size_t len ) __nonnull;
23
+extern void * generic_memcpy ( void *dest, const void *src,
24
+			       size_t len ) __nonnull;
25
+extern void * generic_memmove ( void *dest, const void *src,
26
+				size_t len ) __nonnull;
27
+
28
+extern int __pure memcmp ( const void *first, const void *second,
29
+			   size_t len ) __nonnull;
30
+extern void * __pure memchr ( const void *src, int character,
31
+			      size_t len ) __nonnull;
32
+extern void * memswap ( void *dest, void *src, size_t len ) __nonnull;
33
+extern int __pure strcmp ( const char *first, const char *second ) __nonnull;
34
+extern int __pure strncmp ( const char *first, const char *second,
35
+			    size_t max ) __nonnull;
36
+extern size_t __pure strlen ( const char *src ) __nonnull;
37
+extern size_t __pure strnlen ( const char *src, size_t max ) __nonnull;
38
+extern char * __pure strchr ( const char *src, int character ) __nonnull;
39
+extern char * __pure strrchr ( const char *src, int character ) __nonnull;
40
+extern char * __pure strstr ( const char *haystack,
41
+			      const char *needle ) __nonnull;
42
+extern char * strcpy ( char *dest, const char *src ) __nonnull;
43
+extern char * strncpy ( char *dest, const char *src, size_t max ) __nonnull;
44
+extern char * strcat ( char *dest, const char *src ) __nonnull;
45
+extern char * __malloc strdup ( const char *src ) __nonnull;
46
+extern char * __malloc strndup ( const char *src, size_t max ) __nonnull;
47
+extern char * __pure strpbrk ( const char *string,
48
+			       const char *delim ) __nonnull;
49
+extern char * strsep ( char **string, const char *delim ) __nonnull;
43 50
 
44
-extern const char * __pure strerror ( int errno );
51
+extern char * __pure strerror ( int errno );
45 52
 
46
-#endif /* ETHERBOOT_STRING */
53
+#endif /* _STRING_H */

+ 55
- 7
src/include/strings.h View File

@@ -1,12 +1,23 @@
1 1
 #ifndef _STRINGS_H
2 2
 #define _STRINGS_H
3 3
 
4
+/** @file
5
+ *
6
+ * String functions
7
+ *
8
+ */
9
+
4 10
 FILE_LICENCE ( GPL2_OR_LATER );
5 11
 
6
-#include <limits.h>
7 12
 #include <string.h>
8 13
 #include <bits/strings.h>
9 14
 
15
+/**
16
+ * Find last (i.e. most significant) set bit
17
+ *
18
+ * @v x			Value
19
+ * @ret msb		Most significant bit set in value (LSB=1), or zero
20
+ */
10 21
 static inline __attribute__ (( always_inline )) int
11 22
 __constant_flsll ( unsigned long long x ) {
12 23
 	int r = 0;
@@ -41,6 +52,12 @@ __constant_flsll ( unsigned long long x ) {
41 52
 	return r;
42 53
 }
43 54
 
55
+/**
56
+ * Find last (i.e. most significant) set bit
57
+ *
58
+ * @v x			Value
59
+ * @ret msb		Most significant bit set in value (LSB=1), or zero
60
+ */
44 61
 static inline __attribute__ (( always_inline )) int
45 62
 __constant_flsl ( unsigned long x ) {
46 63
 	return __constant_flsll ( x );
@@ -49,24 +66,55 @@ __constant_flsl ( unsigned long x ) {
49 66
 int __flsll ( long long x );
50 67
 int __flsl ( long x );
51 68
 
69
+/**
70
+ * Find last (i.e. most significant) set bit
71
+ *
72
+ * @v x			Value
73
+ * @ret msb		Most significant bit set in value (LSB=1), or zero
74
+ */
52 75
 #define flsll( x ) \
53 76
 	( __builtin_constant_p ( x ) ? __constant_flsll ( x ) : __flsll ( x ) )
54 77
 
78
+/**
79
+ * Find last (i.e. most significant) set bit
80
+ *
81
+ * @v x			Value
82
+ * @ret msb		Most significant bit set in value (LSB=1), or zero
83
+ */
55 84
 #define flsl( x ) \
56 85
 	( __builtin_constant_p ( x ) ? __constant_flsl ( x ) : __flsl ( x ) )
57 86
 
87
+/**
88
+ * Find last (i.e. most significant) set bit
89
+ *
90
+ * @v x			Value
91
+ * @ret msb		Most significant bit set in value (LSB=1), or zero
92
+ */
58 93
 #define fls( x ) flsl ( x )
59 94
 
60
-extern int strcasecmp ( const char *s1, const char *s2 );
61
-
95
+/**
96
+ * Copy memory
97
+ *
98
+ * @v src		Source
99
+ * @v dest		Destination
100
+ * @v len		Length
101
+ */
62 102
 static inline __attribute__ (( always_inline )) void
63
-bcopy ( const void *src, void *dest, size_t n ) {
64
-	memmove ( dest, src, n );
103
+bcopy ( const void *src, void *dest, size_t len ) {
104
+	memmove ( dest, src, len );
65 105
 }
66 106
 
107
+/**
108
+ * Zero memory
109
+ *
110
+ * @v dest		Destination
111
+ * @v len		Length
112
+ */
67 113
 static inline __attribute__ (( always_inline )) void
68
-bzero ( void *s, size_t n ) {
69
-	memset ( s, 0, n );
114
+bzero ( void *dest, size_t len ) {
115
+	memset ( dest, 0, len );
70 116
 }
71 117
 
118
+int __pure strcasecmp ( const char *first, const char *second ) __nonnull;
119
+
72 120
 #endif /* _STRINGS_H */

Loading…
Cancel
Save