Subversion Repositories HelenOS

Rev

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

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