Subversion Repositories HelenOS

Rev

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

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