Subversion Repositories HelenOS

Rev

Rev 3728 | Rev 3730 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
999 palkovsky 1
/*
2071 jermar 2
 * Copyright (c) 2005 Martin Decky
3427 post 3
 * Copyright (C) 1998 by Wes Peters <wes@softweyr.com>
4
 * Copyright (c) 1988, 1993 The Regents of the University of California.
999 palkovsky 5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 *
11
 * - Redistributions of source code must retain the above copyright
12
 *   notice, this list of conditions and the following disclaimer.
13
 * - Redistributions in binary form must reproduce the above copyright
14
 *   notice, this list of conditions and the following disclaimer in the
15
 *   documentation and/or other materials provided with the distribution.
16
 * - The name of the author may not be used to endorse or promote products
17
 *   derived from this software without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 */
30
 
1719 decky 31
/** @addtogroup libc
1653 cejka 32
 * @{
33
 */
34
/** @file
35
 */
36
 
999 palkovsky 37
#include <string.h>
1314 cejka 38
#include <unistd.h>
39
#include <ctype.h>
40
#include <limits.h>
1538 palkovsky 41
#include <align.h>
2541 jermar 42
#include <sys/types.h>
3238 jermar 43
#include <malloc.h>
999 palkovsky 44
 
3728 svoboda 45
/** Fill memory block with a constant value. */
46
void *memset(void *dest, int b, size_t n)
47
{
48
	char *pb;
49
	unsigned long *pw;
50
	size_t word_size;
51
	size_t n_words;
999 palkovsky 52
 
3728 svoboda 53
	unsigned long pattern;
54
	size_t i;
55
	size_t fill;
56
 
57
	/* Fill initial segment. */
58
	word_size = sizeof(unsigned long);
59
	fill = word_size - ((uintptr_t) dest & (word_size - 1));
60
	if (fill > n) fill = n;
61
 
62
	pb = dest;
63
 
64
	i = fill;
65
	while (i-- != 0)
66
		*pb++ = b;
67
 
68
	/* Compute remaining size. */
69
	n -= fill;
70
	if (n == 0) return dest;
71
 
72
	n_words = n / word_size;
73
	n = n % word_size;
74
	pw = (unsigned long *) pb;
75
 
76
	/* Create word-sized pattern for aligned segment. */
77
	pattern = 0;
78
	i = word_size;
79
	while (i-- != 0)
80
		pattern = (pattern << 8) | (uint8_t) b;
81
 
82
	/* Fill aligned segment. */
83
	i = n_words;
84
	while (i-- != 0)
85
		*pw++ = pattern;
86
 
87
	pb = (char *) pw;
88
 
89
	/* Fill final segment. */
90
	i = n;
91
	while (i-- != 0)
92
		*pb++ = b;
93
 
94
	return dest;
999 palkovsky 95
}
96
 
1719 decky 97
struct along {
98
	unsigned long n;
99
} __attribute__ ((packed));
1538 palkovsky 100
 
1719 decky 101
static void *unaligned_memcpy(void *dst, const void *src, size_t n)
1538 palkovsky 102
{
103
	int i, j;
104
	struct along *adst = dst;
105
	const struct along *asrc = src;
106
 
1719 decky 107
	for (i = 0; i < n / sizeof(unsigned long); i++)
1538 palkovsky 108
		adst[i].n = asrc[i].n;
109
 
1719 decky 110
	for (j = 0; j < n % sizeof(unsigned long); j++)
3261 jermar 111
		((unsigned char *) (((unsigned long *) dst) + i))[j] =
112
		    ((unsigned char *) (((unsigned long *) src) + i))[j];
1538 palkovsky 113
 
3274 jermar 114
	return (char *) dst;
1538 palkovsky 115
}
116
 
3727 svoboda 117
/** Copy memory block. */
1719 decky 118
void *memcpy(void *dst, const void *src, size_t n)
999 palkovsky 119
{
3727 svoboda 120
	size_t i;
121
	size_t mod, fill;
122
	size_t word_size;
123
	size_t n_words;
1485 palkovsky 124
 
3727 svoboda 125
	const unsigned long *srcw;
126
	unsigned long *dstw;
127
	const uint8_t *srcb;
128
	uint8_t *dstb;
129
 
130
	word_size = sizeof(unsigned long);
131
 
132
	/*
133
	 * Are source and destination addresses congruent modulo word_size?
134
	 * If not, use unaligned_memcpy().
135
	 */
136
 
137
	if (((uintptr_t) dst & (word_size - 1)) !=
138
	    ((uintptr_t) src & (word_size - 1)))
1538 palkovsky 139
 		return unaligned_memcpy(dst, src, n);
140
 
3727 svoboda 141
	/*
142
	 * mod is the address modulo word size. fill is the length of the
143
	 * initial buffer segment before the first word boundary.
144
	 * If the buffer is very short, use unaligned_memcpy(), too.
145
	 */
146
 
147
	mod = (uintptr_t) dst & (word_size - 1);
148
	fill = word_size - mod;
149
	if (fill > n) fill = n;
150
 
151
	/* Copy the initial segment. */
152
 
153
	srcb = src;
154
	dstb = dst;
155
 
156
	i = fill;
3728 svoboda 157
	while (i-- != 0)
3727 svoboda 158
		*dstb++ = *srcb++;
159
 
160
	/* Compute remaining length. */
161
 
162
	n -= fill;
163
	if (n == 0) return dst;
164
 
165
	/* Pointers to aligned segment. */
166
 
167
	dstw = (unsigned long *) dstb;
168
	srcw = (const unsigned long *) srcb;
169
 
170
	n_words = n / word_size;	/* Number of whole words to copy. */
171
	n -= n_words * word_size;	/* Remaining bytes at the end. */
172
 
173
	/* "Fast" copy. */
174
	i = n_words;
3728 svoboda 175
	while (i-- != 0)
3727 svoboda 176
		*dstw++ = *srcw++;
177
 
178
	/*
179
	 * Copy the rest.
180
	 */
181
 
182
	srcb = (const uint8_t *) srcw;
183
	dstb = (uint8_t *) dstw;
184
 
185
	i = n;
3728 svoboda 186
	while (i-- != 0)
3727 svoboda 187
		*dstb++ = *srcb++;
188
 
189
	return dst;
999 palkovsky 190
}
1173 cejka 191
 
3729 svoboda 192
/** Move memory block with possible overlapping. */
1719 decky 193
void *memmove(void *dst, const void *src, size_t n)
1485 palkovsky 194
{
3729 svoboda 195
	uint8_t *dp, *sp;
196
 
197
	/* Nothing to do? */
198
	if (src == dst)
199
		return dst;
200
 
201
	/* Non-overlapping? */
202
	if (dst >= src + n || src >= dst + n) {	
1485 palkovsky 203
		return memcpy(dst, src, n);
3729 svoboda 204
	}
1485 palkovsky 205
 
3729 svoboda 206
	/* Which direction? */
207
	if (src > dst) {
208
		/* Forwards. */
209
		sp = src;
210
		dp = dst;
1485 palkovsky 211
 
3729 svoboda 212
		while (n-- != 0)
213
			*dp++ = *sp++;
214
	} else {
215
		/* Backwards. */
216
		sp = src + (n - 1);
217
		dp = dst + (n - 1);
218
 
219
		while (n-- != 0)
220
			*dp-- = *sp--;
221
	}
222
 
223
	return dst;
1485 palkovsky 224
}
225
 
2072 jermar 226
/** Compare two memory areas.
227
 *
3261 jermar 228
 * @param s1		Pointer to the first area to compare.
229
 * @param s2		Pointer to the second area to compare.
230
 * @param len		Size of the first area in bytes. Both areas must have
231
 * 			the same length.
232
 * @return		If len is 0, return zero. If the areas match, return
233
 * 			zero. Otherwise return non-zero.
2072 jermar 234
 */
235
int bcmp(const char *s1, const char *s2, size_t len)
236
{
237
	for (; len && *s1++ == *s2++; len--)
238
		;
239
	return len;
240
}
1485 palkovsky 241
 
1314 cejka 242
/** Count the number of characters in the string, not including terminating 0.
3261 jermar 243
 *
244
 * @param str		String.
245
 * @return		Number of characters in string.
1314 cejka 246
 */
1173 cejka 247
size_t strlen(const char *str) 
248
{
1197 cejka 249
	size_t counter = 0;
1173 cejka 250
 
1719 decky 251
	while (str[counter] != 0)
1173 cejka 252
		counter++;
253
 
254
	return counter;
255
}
1314 cejka 256
 
1719 decky 257
int strcmp(const char *a, const char *b)
1319 vana 258
{
1719 decky 259
	int c = 0;
1319 vana 260
 
1719 decky 261
	while (a[c] && b[c] && (!(a[c] - b[c])))
262
		c++;
1319 vana 263
 
1719 decky 264
	return (a[c] - b[c]);
1319 vana 265
}
266
 
2640 cejka 267
int strncmp(const char *a, const char *b, size_t n)
268
{
269
	size_t c = 0;
1319 vana 270
 
2640 cejka 271
	while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
272
		c++;
273
 
274
	return ( c < n ? a[c] - b[c] : 0);
275
 
276
}
277
 
3271 jermar 278
int stricmp(const char *a, const char *b)
279
{
280
	int c = 0;
281
 
282
	while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
283
		c++;
284
 
285
	return (tolower(a[c]) - tolower(b[c]));
286
}
287
 
3261 jermar 288
/** Return pointer to the first occurence of character c in string.
289
 *
290
 * @param str		Scanned string.
291
 * @param c		Searched character (taken as one byte).
292
 * @return		Pointer to the matched character or NULL if it is not
293
 * 			found in given string.
1314 cejka 294
 */
295
char *strchr(const char *str, int c)
296
{
297
	while (*str != '\0') {
1719 decky 298
		if (*str == (char) c)
299
			return (char *) str;
1314 cejka 300
		str++;
301
	}
302
 
303
	return NULL;
304
}
305
 
3261 jermar 306
/** Return pointer to the last occurence of character c in string.
307
 *
308
 * @param str		Scanned string.
309
 * @param c		Searched character (taken as one byte).
310
 * @return		Pointer to the matched character or NULL if it is not
311
 * 			found in given string.
1314 cejka 312
 */
313
char *strrchr(const char *str, int c)
314
{
315
	char *retval = NULL;
316
 
317
	while (*str != '\0') {
1719 decky 318
		if (*str == (char) c)
319
			retval = (char *) str;
1314 cejka 320
		str++;
321
	}
322
 
1719 decky 323
	return (char *) retval;
1314 cejka 324
}
325
 
326
/** Convert string to a number. 
327
 * Core of strtol and strtoul functions.
3261 jermar 328
 *
329
 * @param nptr		Pointer to string.
330
 * @param endptr	If not NULL, function stores here pointer to the first
331
 * 			invalid character.
332
 * @param base		Zero or number between 2 and 36 inclusive.
333
 * @param sgn		It's set to 1 if minus found.
334
 * @return		Result of conversion.
1314 cejka 335
 */
3261 jermar 336
static unsigned long
337
_strtoul(const char *nptr, char **endptr, int base, char *sgn)
1314 cejka 338
{
339
	unsigned char c;
340
	unsigned long result = 0;
341
	unsigned long a, b;
342
	const char *str = nptr;
343
	const char *tmpptr;
344
 
345
	while (isspace(*str))
346
		str++;
347
 
348
	if (*str == '-') {
349
		*sgn = 1;
350
		++str;
351
	} else if (*str == '+')
352
		++str;
353
 
354
	if (base) {
355
		if ((base == 1) || (base > 36)) {
356
			/* FIXME: set errno to EINVAL */
357
			return 0;
358
		}
3261 jermar 359
		if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
360
		    (str[1] == 'X'))) {
1314 cejka 361
			str += 2;
362
		}
363
	} else {
364
		base = 10;
365
 
366
		if (*str == '0') {
367
			base = 8;
368
			if ((str[1] == 'X') || (str[1] == 'x'))  {
369
				base = 16;
370
				str += 2;
371
			}
372
		} 
373
	}
374
 
375
	tmpptr = str;
376
 
377
	while (*str) {
378
		c = *str;
3261 jermar 379
		c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
380
		    (c <= '9' ? c - '0' : 0xff)));
1314 cejka 381
		if (c > base) {
382
			break;
383
		}
384
 
385
		a = (result & 0xff) * base + c;
386
		b = (result >> 8) * base + (a >> 8);
387
 
388
		if (b > (ULONG_MAX >> 8)) {
389
			/* overflow */
390
			/* FIXME: errno = ERANGE*/
391
			return ULONG_MAX;
392
		}
393
 
394
		result = (b << 8) + (a & 0xff);
395
		++str;
396
	}
397
 
398
	if (str == tmpptr) {
3261 jermar 399
		/*
400
		 * No number was found => first invalid character is the first
401
		 * character of the string.
402
		 */
1314 cejka 403
		/* FIXME: set errno to EINVAL */
404
		str = nptr;
405
		result = 0;
406
	}
407
 
408
	if (endptr)
1719 decky 409
		*endptr = (char *) str;
1314 cejka 410
 
411
	if (nptr == str) { 
412
		/*FIXME: errno = EINVAL*/
413
		return 0;
414
	}
415
 
416
	return result;
417
}
418
 
419
/** Convert initial part of string to long int according to given base.
3261 jermar 420
 * The number may begin with an arbitrary number of whitespaces followed by
421
 * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
422
 * inserted and the number will be taken as hexadecimal one. If the base is 0
423
 * and the number begin with a zero, number will be taken as octal one (as with
424
 * base 8). Otherwise the base 0 is taken as decimal.
425
 *
426
 * @param nptr		Pointer to string.
427
 * @param endptr	If not NULL, function stores here pointer to the first
428
 * 			invalid character.
429
 * @param base		Zero or number between 2 and 36 inclusive.
430
 * @return		Result of conversion.
1314 cejka 431
 */
432
long int strtol(const char *nptr, char **endptr, int base)
433
{
434
	char sgn = 0;
435
	unsigned long number = 0;
436
 
437
	number = _strtoul(nptr, endptr, base, &sgn);
438
 
439
	if (number > LONG_MAX) {
1719 decky 440
		if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
1314 cejka 441
			/* FIXME: set 0 to errno */
442
			return number;		
443
		}
444
		/* FIXME: set ERANGE to errno */
1719 decky 445
		return (sgn ? LONG_MIN : LONG_MAX);	
1314 cejka 446
	}
447
 
1719 decky 448
	return (sgn ? -number : number);
1314 cejka 449
}
450
 
451
 
452
/** Convert initial part of string to unsigned long according to given base.
3261 jermar 453
 * The number may begin with an arbitrary number of whitespaces followed by
454
 * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
455
 * inserted and the number will be taken as hexadecimal one. If the base is 0
456
 * and the number begin with a zero, number will be taken as octal one (as with
457
 * base 8). Otherwise the base 0 is taken as decimal.
458
 *
459
 * @param nptr		Pointer to string.
460
 * @param endptr	If not NULL, function stores here pointer to the first
461
 * 			invalid character
462
 * @param base		Zero or number between 2 and 36 inclusive.
463
 * @return		Result of conversion.
1314 cejka 464
 */
465
unsigned long strtoul(const char *nptr, char **endptr, int base)
466
{
467
	char sgn = 0;
468
	unsigned long number = 0;
469
 
470
	number = _strtoul(nptr, endptr, base, &sgn);
471
 
1719 decky 472
	return (sgn ? -number : number);
1314 cejka 473
}
1472 palkovsky 474
 
475
char *strcpy(char *dest, const char *src)
476
{
1719 decky 477
	char *orig = dest;
478
 
2754 jermar 479
	while ((*(dest++) = *(src++)))
480
		;
1719 decky 481
	return orig;
1472 palkovsky 482
}
483
 
484
char *strncpy(char *dest, const char *src, size_t n)
485
{
1719 decky 486
	char *orig = dest;
487
 
2754 jermar 488
	while ((*(dest++) = *(src++)) && --n)
489
		;
1719 decky 490
	return orig;
1472 palkovsky 491
}
1653 cejka 492
 
2754 jermar 493
char *strcat(char *dest, const char *src)
494
{
495
	char *orig = dest;
496
	while (*dest++)
497
		;
498
	--dest;
499
	while ((*dest++ = *src++))
500
		;
501
	return orig;
502
}
503
 
3238 jermar 504
char * strdup(const char *s1)
505
{
506
	size_t len = strlen(s1) + 1;
507
	void *ret = malloc(len);
508
 
509
	if (ret == NULL)
510
		return (char *) NULL;
511
 
512
	return (char *) memcpy(ret, s1, len);
513
}
514
 
3427 post 515
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
516
char * strtok_r(char *s, const char *delim, char **last)
517
{
518
	char *spanp, *tok;
519
	int c, sc;
520
 
521
	if (s == NULL && (s = *last) == NULL)
522
		return (NULL);
523
 
524
cont:
525
	c = *s++;
526
	for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
527
		if (c == sc)
528
			goto cont;
529
	}
530
 
531
	if (c == 0) {		/* no non-delimiter characters */
532
		*last = NULL;
533
		return (NULL);
534
	}
535
 
536
	tok = s - 1;
537
 
538
	for (;;) {
539
		c = *s++;
540
		spanp = (char *)delim;
541
		do {
542
			if ((sc = *spanp++) == c) {
543
				if (c == 0)
544
					s = NULL;
545
				else
546
					s[-1] = '\0';
547
				*last = s;
548
				return (tok);
549
			}
550
		} while (sc != 0);
551
	}
552
}
553
 
554
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
555
char * strtok(char *s, const char *delim)
556
{
557
	static char *last;
558
 
559
	return (strtok_r(s, delim, &last));
560
}
561
 
1719 decky 562
/** @}
1653 cejka 563
 */