Subversion Repositories HelenOS

Rev

Rev 3728 | Rev 3730 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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