Subversion Repositories HelenOS

Rev

Rev 3427 | Rev 3728 | 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
 
45
/* Dummy implementation of mem/ functions */
46
 
1719 decky 47
void *memset(void *s, int c, size_t n)
999 palkovsky 48
{
49
    char *os = s;
1719 decky 50
 
999 palkovsky 51
    while (n--)
52
        *(os++) = c;
1719 decky 53
 
999 palkovsky 54
    return s;
55
}
56
 
1719 decky 57
struct along {
58
    unsigned long n;
59
} __attribute__ ((packed));
1538 palkovsky 60
 
1719 decky 61
static void *unaligned_memcpy(void *dst, const void *src, size_t n)
1538 palkovsky 62
{
63
    int i, j;
64
    struct along *adst = dst;
65
    const struct along *asrc = src;
66
 
1719 decky 67
    for (i = 0; i < n / sizeof(unsigned long); i++)
1538 palkovsky 68
        adst[i].n = asrc[i].n;
69
 
1719 decky 70
    for (j = 0; j < n % sizeof(unsigned long); j++)
3261 jermar 71
        ((unsigned char *) (((unsigned long *) dst) + i))[j] =
72
            ((unsigned char *) (((unsigned long *) src) + i))[j];
1538 palkovsky 73
 
3274 jermar 74
    return (char *) dst;
1538 palkovsky 75
}
76
 
3727 svoboda 77
/** Copy memory block. */
1719 decky 78
void *memcpy(void *dst, const void *src, size_t n)
999 palkovsky 79
{
3727 svoboda 80
    size_t i;
81
    size_t mod, fill;
82
    size_t word_size;
83
    size_t n_words;
1485 palkovsky 84
 
3727 svoboda 85
    const unsigned long *srcw;
86
    unsigned long *dstw;
87
    const uint8_t *srcb;
88
    uint8_t *dstb;
89
 
90
    word_size = sizeof(unsigned long);
91
 
92
    /*
93
     * Are source and destination addresses congruent modulo word_size?
94
     * If not, use unaligned_memcpy().
95
     */
96
 
97
    if (((uintptr_t) dst & (word_size - 1)) !=
98
        ((uintptr_t) src & (word_size - 1)))
1538 palkovsky 99
        return unaligned_memcpy(dst, src, n);
100
 
3727 svoboda 101
    /*
102
     * mod is the address modulo word size. fill is the length of the
103
     * initial buffer segment before the first word boundary.
104
     * If the buffer is very short, use unaligned_memcpy(), too.
105
     */
106
 
107
    mod = (uintptr_t) dst & (word_size - 1);
108
    fill = word_size - mod;
109
    if (fill > n) fill = n;
110
 
111
    /* Copy the initial segment. */
112
 
113
    srcb = src;
114
    dstb = dst;
115
 
116
    i = fill;
117
    while (i-- > 0)
118
        *dstb++ = *srcb++;
119
 
120
    /* Compute remaining length. */
121
 
122
    n -= fill;
123
    if (n == 0) return dst;
124
 
125
    /* Pointers to aligned segment. */
126
 
127
    dstw = (unsigned long *) dstb;
128
    srcw = (const unsigned long *) srcb;
129
 
130
    n_words = n / word_size;    /* Number of whole words to copy. */
131
    n -= n_words * word_size;   /* Remaining bytes at the end. */
132
 
133
    /* "Fast" copy. */
134
    i = n_words;
135
    while (i-- > 0)
136
        *dstw++ = *srcw++;
137
 
138
    /*
139
     * Copy the rest.
140
     */
141
 
142
    srcb = (const uint8_t *) srcw;
143
    dstb = (uint8_t *) dstw;
144
 
145
    i = n;
146
    while (i-- > 0)
147
        *dstb++ = *srcb++;
148
 
149
    return dst;
999 palkovsky 150
}
1173 cejka 151
 
1719 decky 152
void *memmove(void *dst, const void *src, size_t n)
1485 palkovsky 153
{
154
    int i, j;
155
 
156
    if (src > dst)
157
        return memcpy(dst, src, n);
158
 
1719 decky 159
    for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--)
3261 jermar 160
        ((unsigned char *) ((unsigned long *) dst))[j] =
161
            ((unsigned char *) ((unsigned long *) src))[j];
1485 palkovsky 162
 
1719 decky 163
    for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--)
1485 palkovsky 164
        ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
165
 
3274 jermar 166
    return (char *) dst;
1485 palkovsky 167
}
168
 
2072 jermar 169
/** Compare two memory areas.
170
 *
3261 jermar 171
 * @param s1        Pointer to the first area to compare.
172
 * @param s2        Pointer to the second area to compare.
173
 * @param len       Size of the first area in bytes. Both areas must have
174
 *          the same length.
175
 * @return      If len is 0, return zero. If the areas match, return
176
 *          zero. Otherwise return non-zero.
2072 jermar 177
 */
178
int bcmp(const char *s1, const char *s2, size_t len)
179
{
180
    for (; len && *s1++ == *s2++; len--)
181
        ;
182
    return len;
183
}
1485 palkovsky 184
 
1314 cejka 185
/** Count the number of characters in the string, not including terminating 0.
3261 jermar 186
 *
187
 * @param str       String.
188
 * @return      Number of characters in string.
1314 cejka 189
 */
1173 cejka 190
size_t strlen(const char *str)
191
{
1197 cejka 192
    size_t counter = 0;
1173 cejka 193
 
1719 decky 194
    while (str[counter] != 0)
1173 cejka 195
        counter++;
196
 
197
    return counter;
198
}
1314 cejka 199
 
1719 decky 200
int strcmp(const char *a, const char *b)
1319 vana 201
{
1719 decky 202
    int c = 0;
1319 vana 203
 
1719 decky 204
    while (a[c] && b[c] && (!(a[c] - b[c])))
205
        c++;
1319 vana 206
 
1719 decky 207
    return (a[c] - b[c]);
1319 vana 208
}
209
 
2640 cejka 210
int strncmp(const char *a, const char *b, size_t n)
211
{
212
    size_t c = 0;
1319 vana 213
 
2640 cejka 214
    while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
215
        c++;
216
 
217
    return ( c < n ? a[c] - b[c] : 0);
218
 
219
}
220
 
3271 jermar 221
int stricmp(const char *a, const char *b)
222
{
223
    int c = 0;
224
 
225
    while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
226
        c++;
227
 
228
    return (tolower(a[c]) - tolower(b[c]));
229
}
230
 
3261 jermar 231
/** Return pointer to the first occurence of character c in string.
232
 *
233
 * @param str       Scanned string.
234
 * @param c     Searched character (taken as one byte).
235
 * @return      Pointer to the matched character or NULL if it is not
236
 *          found in given string.
1314 cejka 237
 */
238
char *strchr(const char *str, int c)
239
{
240
    while (*str != '\0') {
1719 decky 241
        if (*str == (char) c)
242
            return (char *) str;
1314 cejka 243
        str++;
244
    }
245
 
246
    return NULL;
247
}
248
 
3261 jermar 249
/** Return pointer to the last occurence of character c in string.
250
 *
251
 * @param str       Scanned string.
252
 * @param c     Searched character (taken as one byte).
253
 * @return      Pointer to the matched character or NULL if it is not
254
 *          found in given string.
1314 cejka 255
 */
256
char *strrchr(const char *str, int c)
257
{
258
    char *retval = NULL;
259
 
260
    while (*str != '\0') {
1719 decky 261
        if (*str == (char) c)
262
            retval = (char *) str;
1314 cejka 263
        str++;
264
    }
265
 
1719 decky 266
    return (char *) retval;
1314 cejka 267
}
268
 
269
/** Convert string to a number.
270
 * Core of strtol and strtoul functions.
3261 jermar 271
 *
272
 * @param nptr      Pointer to string.
273
 * @param endptr    If not NULL, function stores here pointer to the first
274
 *          invalid character.
275
 * @param base      Zero or number between 2 and 36 inclusive.
276
 * @param sgn       It's set to 1 if minus found.
277
 * @return      Result of conversion.
1314 cejka 278
 */
3261 jermar 279
static unsigned long
280
_strtoul(const char *nptr, char **endptr, int base, char *sgn)
1314 cejka 281
{
282
    unsigned char c;
283
    unsigned long result = 0;
284
    unsigned long a, b;
285
    const char *str = nptr;
286
    const char *tmpptr;
287
 
288
    while (isspace(*str))
289
        str++;
290
 
291
    if (*str == '-') {
292
        *sgn = 1;
293
        ++str;
294
    } else if (*str == '+')
295
        ++str;
296
 
297
    if (base) {
298
        if ((base == 1) || (base > 36)) {
299
            /* FIXME: set errno to EINVAL */
300
            return 0;
301
        }
3261 jermar 302
        if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
303
            (str[1] == 'X'))) {
1314 cejka 304
            str += 2;
305
        }
306
    } else {
307
        base = 10;
308
 
309
        if (*str == '0') {
310
            base = 8;
311
            if ((str[1] == 'X') || (str[1] == 'x'))  {
312
                base = 16;
313
                str += 2;
314
            }
315
        }
316
    }
317
 
318
    tmpptr = str;
319
 
320
    while (*str) {
321
        c = *str;
3261 jermar 322
        c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
323
            (c <= '9' ? c - '0' : 0xff)));
1314 cejka 324
        if (c > base) {
325
            break;
326
        }
327
 
328
        a = (result & 0xff) * base + c;
329
        b = (result >> 8) * base + (a >> 8);
330
 
331
        if (b > (ULONG_MAX >> 8)) {
332
            /* overflow */
333
            /* FIXME: errno = ERANGE*/
334
            return ULONG_MAX;
335
        }
336
 
337
        result = (b << 8) + (a & 0xff);
338
        ++str;
339
    }
340
 
341
    if (str == tmpptr) {
3261 jermar 342
        /*
343
         * No number was found => first invalid character is the first
344
         * character of the string.
345
         */
1314 cejka 346
        /* FIXME: set errno to EINVAL */
347
        str = nptr;
348
        result = 0;
349
    }
350
 
351
    if (endptr)
1719 decky 352
        *endptr = (char *) str;
1314 cejka 353
 
354
    if (nptr == str) {
355
        /*FIXME: errno = EINVAL*/
356
        return 0;
357
    }
358
 
359
    return result;
360
}
361
 
362
/** Convert initial part of string to long int according to given base.
3261 jermar 363
 * The number may begin with an arbitrary number of whitespaces followed by
364
 * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
365
 * inserted and the number will be taken as hexadecimal one. If the base is 0
366
 * and the number begin with a zero, number will be taken as octal one (as with
367
 * base 8). Otherwise the base 0 is taken as decimal.
368
 *
369
 * @param nptr      Pointer to string.
370
 * @param endptr    If not NULL, function stores here pointer to the first
371
 *          invalid character.
372
 * @param base      Zero or number between 2 and 36 inclusive.
373
 * @return      Result of conversion.
1314 cejka 374
 */
375
long int strtol(const char *nptr, char **endptr, int base)
376
{
377
    char sgn = 0;
378
    unsigned long number = 0;
379
 
380
    number = _strtoul(nptr, endptr, base, &sgn);
381
 
382
    if (number > LONG_MAX) {
1719 decky 383
        if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
1314 cejka 384
            /* FIXME: set 0 to errno */
385
            return number;     
386
        }
387
        /* FIXME: set ERANGE to errno */
1719 decky 388
        return (sgn ? LONG_MIN : LONG_MAX);
1314 cejka 389
    }
390
 
1719 decky 391
    return (sgn ? -number : number);
1314 cejka 392
}
393
 
394
 
395
/** Convert initial part of string to unsigned long according to given base.
3261 jermar 396
 * The number may begin with an arbitrary number of whitespaces followed by
397
 * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
398
 * inserted and the number will be taken as hexadecimal one. If the base is 0
399
 * and the number begin with a zero, number will be taken as octal one (as with
400
 * base 8). Otherwise the base 0 is taken as decimal.
401
 *
402
 * @param nptr      Pointer to string.
403
 * @param endptr    If not NULL, function stores here pointer to the first
404
 *          invalid character
405
 * @param base      Zero or number between 2 and 36 inclusive.
406
 * @return      Result of conversion.
1314 cejka 407
 */
408
unsigned long strtoul(const char *nptr, char **endptr, int base)
409
{
410
    char sgn = 0;
411
    unsigned long number = 0;
412
 
413
    number = _strtoul(nptr, endptr, base, &sgn);
414
 
1719 decky 415
    return (sgn ? -number : number);
1314 cejka 416
}
1472 palkovsky 417
 
418
char *strcpy(char *dest, const char *src)
419
{
1719 decky 420
    char *orig = dest;
421
 
2754 jermar 422
    while ((*(dest++) = *(src++)))
423
        ;
1719 decky 424
    return orig;
1472 palkovsky 425
}
426
 
427
char *strncpy(char *dest, const char *src, size_t n)
428
{
1719 decky 429
    char *orig = dest;
430
 
2754 jermar 431
    while ((*(dest++) = *(src++)) && --n)
432
        ;
1719 decky 433
    return orig;
1472 palkovsky 434
}
1653 cejka 435
 
2754 jermar 436
char *strcat(char *dest, const char *src)
437
{
438
    char *orig = dest;
439
    while (*dest++)
440
        ;
441
    --dest;
442
    while ((*dest++ = *src++))
443
        ;
444
    return orig;
445
}
446
 
3238 jermar 447
char * strdup(const char *s1)
448
{
449
    size_t len = strlen(s1) + 1;
450
    void *ret = malloc(len);
451
 
452
    if (ret == NULL)
453
        return (char *) NULL;
454
 
455
    return (char *) memcpy(ret, s1, len);
456
}
457
 
3427 post 458
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
459
char * strtok_r(char *s, const char *delim, char **last)
460
{
461
    char *spanp, *tok;
462
    int c, sc;
463
 
464
    if (s == NULL && (s = *last) == NULL)
465
        return (NULL);
466
 
467
cont:
468
    c = *s++;
469
    for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
470
        if (c == sc)
471
            goto cont;
472
    }
473
 
474
    if (c == 0) {       /* no non-delimiter characters */
475
        *last = NULL;
476
        return (NULL);
477
    }
478
 
479
    tok = s - 1;
480
 
481
    for (;;) {
482
        c = *s++;
483
        spanp = (char *)delim;
484
        do {
485
            if ((sc = *spanp++) == c) {
486
                if (c == 0)
487
                    s = NULL;
488
                else
489
                    s[-1] = '\0';
490
                *last = s;
491
                return (tok);
492
            }
493
        } while (sc != 0);
494
    }
495
}
496
 
497
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
498
char * strtok(char *s, const char *delim)
499
{
500
    static char *last;
501
 
502
    return (strtok_r(s, delim, &last));
503
}
504
 
1719 decky 505
/** @}
1653 cejka 506
 */