Subversion Repositories HelenOS

Rev

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

Rev 3731 Rev 4226
1
/*
1
/*
2
 * Copyright (c) 2005 Martin Decky
2
 * Copyright (c) 2005 Martin Decky
3
 * Copyright (c) 2008 Jiri Svoboda
3
 * Copyright (c) 2008 Jiri Svoboda
4
 * All rights reserved.
4
 * All rights reserved.
5
 *
5
 *
6
 * Redistribution and use in source and binary forms, with or without
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
7
 * modification, are permitted provided that the following conditions
8
 * are met:
8
 * are met:
9
 *
9
 *
10
 * - Redistributions of source code must retain the above copyright
10
 * - Redistributions of source code must retain the above copyright
11
 *   notice, this list of conditions and the following disclaimer.
11
 *   notice, this list of conditions and the following disclaimer.
12
 * - Redistributions in binary form must reproduce the above copyright
12
 * - Redistributions in binary form must reproduce the above copyright
13
 *   notice, this list of conditions and the following disclaimer in the
13
 *   notice, this list of conditions and the following disclaimer in the
14
 *   documentation and/or other materials provided with the distribution.
14
 *   documentation and/or other materials provided with the distribution.
15
 * - 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
16
 *   derived from this software without specific prior written permission.
16
 *   derived from this software without specific prior written permission.
17
 *
17
 *
18
 * 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
19
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
 * 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,
22
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
 * 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,
24
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (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
27
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
28
 */
29
 
29
 
30
/** @addtogroup libc
30
/** @addtogroup libc
31
 * @{
31
 * @{
32
 */
32
 */
33
/** @file
33
/** @file
34
 */
34
 */
35
 
35
 
36
#include <string.h>
36
#include <string.h>
37
#include <stdlib.h>
37
#include <stdlib.h>
38
#include <limits.h>
38
#include <limits.h>
39
#include <ctype.h>
39
#include <ctype.h>
40
#include <malloc.h>
40
#include <malloc.h>
-
 
41
#include <errno.h>
-
 
42
#include <string.h>
-
 
43
 
-
 
44
/** Byte mask consisting of lowest @n bits (out of 8) */
-
 
45
#define LO_MASK_8(n)  ((uint8_t) ((1 << (n)) - 1))
-
 
46
 
-
 
47
/** Byte mask consisting of lowest @n bits (out of 32) */
-
 
48
#define LO_MASK_32(n)  ((uint32_t) ((1 << (n)) - 1))
-
 
49
 
-
 
50
/** Byte mask consisting of highest @n bits (out of 8) */
-
 
51
#define HI_MASK_8(n)  (~LO_MASK_8(8 - (n)))
-
 
52
 
-
 
53
/** Number of data bits in a UTF-8 continuation byte */
-
 
54
#define CONT_BITS  6
-
 
55
 
-
 
56
/** Decode a single character from a string.
-
 
57
 *
-
 
58
 * Decode a single character from a string of size @a size. Decoding starts
-
 
59
 * at @a offset and this offset is moved to the beginning of the next
-
 
60
 * character. In case of decoding error, offset generally advances at least
-
 
61
 * by one. However, offset is never moved beyond size.
-
 
62
 *
-
 
63
 * @param str    String (not necessarily NULL-terminated).
-
 
64
 * @param offset Byte offset in string where to start decoding.
-
 
65
 * @param size   Size of the string (in bytes).
-
 
66
 *
-
 
67
 * @return Value of decoded character, U_SPECIAL on decoding error or
-
 
68
 *         NULL if attempt to decode beyond @a size.
-
 
69
 *
-
 
70
 */
-
 
71
wchar_t str_decode(const char *str, size_t *offset, size_t size)
-
 
72
{
-
 
73
    if (*offset + 1 > size)
-
 
74
        return 0;
-
 
75
   
-
 
76
    /* First byte read from string */
-
 
77
    uint8_t b0 = (uint8_t) str[(*offset)++];
-
 
78
   
-
 
79
    /* Determine code length */
-
 
80
   
-
 
81
    unsigned int b0_bits;  /* Data bits in first byte */
-
 
82
    unsigned int cbytes;   /* Number of continuation bytes */
-
 
83
   
-
 
84
    if ((b0 & 0x80) == 0) {
-
 
85
        /* 0xxxxxxx (Plain ASCII) */
-
 
86
        b0_bits = 7;
-
 
87
        cbytes = 0;
-
 
88
    } else if ((b0 & 0xe0) == 0xc0) {
-
 
89
        /* 110xxxxx 10xxxxxx */
-
 
90
        b0_bits = 5;
-
 
91
        cbytes = 1;
-
 
92
    } else if ((b0 & 0xf0) == 0xe0) {
-
 
93
        /* 1110xxxx 10xxxxxx 10xxxxxx */
-
 
94
        b0_bits = 4;
-
 
95
        cbytes = 2;
-
 
96
    } else if ((b0 & 0xf8) == 0xf0) {
-
 
97
        /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
-
 
98
        b0_bits = 3;
-
 
99
        cbytes = 3;
-
 
100
    } else {
-
 
101
        /* 10xxxxxx -- unexpected continuation byte */
-
 
102
        return U_SPECIAL;
-
 
103
    }
-
 
104
   
-
 
105
    if (*offset + cbytes > size)
-
 
106
        return U_SPECIAL;
-
 
107
   
-
 
108
    wchar_t ch = b0 & LO_MASK_8(b0_bits);
-
 
109
   
-
 
110
    /* Decode continuation bytes */
-
 
111
    while (cbytes > 0) {
-
 
112
        uint8_t b = (uint8_t) str[(*offset)++];
-
 
113
       
-
 
114
        /* Must be 10xxxxxx */
-
 
115
        if ((b & 0xc0) != 0x80)
-
 
116
            return U_SPECIAL;
-
 
117
       
-
 
118
        /* Shift data bits to ch */
-
 
119
        ch = (ch << CONT_BITS) | (wchar_t) (b & LO_MASK_8(CONT_BITS));
-
 
120
        cbytes--;
-
 
121
    }
-
 
122
   
-
 
123
    return ch;
-
 
124
}
-
 
125
 
-
 
126
/** Encode a single character to string representation.
-
 
127
 *
-
 
128
 * Encode a single character to string representation (i.e. UTF-8) and store
-
 
129
 * it into a buffer at @a offset. Encoding starts at @a offset and this offset
-
 
130
 * is moved to the position where the next character can be written to.
-
 
131
 *
-
 
132
 * @param ch     Input character.
-
 
133
 * @param str    Output buffer.
-
 
134
 * @param offset Byte offset where to start writing.
-
 
135
 * @param size   Size of the output buffer (in bytes).
-
 
136
 *
-
 
137
 * @return EOK if the character was encoded successfully, EOVERFLOW if there
-
 
138
 *     was not enough space in the output buffer or EINVAL if the character
-
 
139
 *     code was invalid.
-
 
140
 */
-
 
141
int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t size)
-
 
142
{
-
 
143
    if (*offset >= size)
-
 
144
        return EOVERFLOW;
-
 
145
   
-
 
146
    if (!chr_check(ch))
-
 
147
        return EINVAL;
-
 
148
   
-
 
149
    /* Unsigned version of ch (bit operations should only be done
-
 
150
       on unsigned types). */
-
 
151
    uint32_t cc = (uint32_t) ch;
-
 
152
   
-
 
153
    /* Determine how many continuation bytes are needed */
-
 
154
   
-
 
155
    unsigned int b0_bits;  /* Data bits in first byte */
-
 
156
    unsigned int cbytes;   /* Number of continuation bytes */
-
 
157
   
-
 
158
    if ((cc & ~LO_MASK_32(7)) == 0) {
-
 
159
        b0_bits = 7;
-
 
160
        cbytes = 0;
-
 
161
    } else if ((cc & ~LO_MASK_32(11)) == 0) {
-
 
162
        b0_bits = 5;
-
 
163
        cbytes = 1;
-
 
164
    } else if ((cc & ~LO_MASK_32(16)) == 0) {
-
 
165
        b0_bits = 4;
-
 
166
        cbytes = 2;
-
 
167
    } else if ((cc & ~LO_MASK_32(21)) == 0) {
-
 
168
        b0_bits = 3;
-
 
169
        cbytes = 3;
-
 
170
    } else {
-
 
171
        /* Codes longer than 21 bits are not supported */
-
 
172
        return EINVAL;
-
 
173
    }
-
 
174
   
-
 
175
    /* Check for available space in buffer */
-
 
176
    if (*offset + cbytes >= size)
-
 
177
        return EOVERFLOW;
-
 
178
   
-
 
179
    /* Encode continuation bytes */
-
 
180
    unsigned int i;
-
 
181
    for (i = cbytes; i > 0; i--) {
-
 
182
        str[*offset + i] = 0x80 | (cc & LO_MASK_32(CONT_BITS));
-
 
183
        cc = cc >> CONT_BITS;
-
 
184
    }
-
 
185
   
-
 
186
    /* Encode first byte */
-
 
187
    str[*offset] = (cc & LO_MASK_32(b0_bits)) | HI_MASK_8(8 - b0_bits - 1);
-
 
188
   
-
 
189
    /* Advance offset */
-
 
190
    *offset += cbytes + 1;
-
 
191
   
-
 
192
    return EOK;
-
 
193
}
-
 
194
 
-
 
195
/** Check whether character is valid
-
 
196
 *
-
 
197
 * @return True if character is a valid Unicode code point.
-
 
198
 *
-
 
199
 */
-
 
200
bool chr_check(const wchar_t ch)
-
 
201
{
-
 
202
    if ((ch >= 0) && (ch <= 1114111))
-
 
203
        return true;
-
 
204
   
-
 
205
    return false;
-
 
206
}
41
 
207
 
42
/** Count the number of characters in the string, not including terminating 0.
208
/** Count the number of characters in the string, not including terminating 0.
43
 *
209
 *
44
 * @param str       String.
210
 * @param str       String.
45
 * @return      Number of characters in string.
211
 * @return      Number of characters in string.
46
 */
212
 */
47
size_t strlen(const char *str)
213
size_t strlen(const char *str)
48
{
214
{
49
    size_t counter = 0;
215
    size_t counter = 0;
50
 
216
 
51
    while (str[counter] != 0)
217
    while (str[counter] != 0)
52
        counter++;
218
        counter++;
53
 
219
 
54
    return counter;
220
    return counter;
55
}
221
}
56
 
222
 
57
int strcmp(const char *a, const char *b)
223
int strcmp(const char *a, const char *b)
58
{
224
{
59
    int c = 0;
225
    int c = 0;
60
   
226
   
61
    while (a[c] && b[c] && (!(a[c] - b[c])))
227
    while (a[c] && b[c] && (!(a[c] - b[c])))
62
        c++;
228
        c++;
63
   
229
   
64
    return (a[c] - b[c]);
230
    return (a[c] - b[c]);
65
}
231
}
66
 
232
 
67
int strncmp(const char *a, const char *b, size_t n)
233
int strncmp(const char *a, const char *b, size_t n)
68
{
234
{
69
    size_t c = 0;
235
    size_t c = 0;
70
 
236
 
71
    while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
237
    while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
72
        c++;
238
        c++;
73
   
239
   
74
    return ( c < n ? a[c] - b[c] : 0);
240
    return ( c < n ? a[c] - b[c] : 0);
75
   
241
   
76
}
242
}
77
 
243
 
78
int stricmp(const char *a, const char *b)
244
int stricmp(const char *a, const char *b)
79
{
245
{
80
    int c = 0;
246
    int c = 0;
81
   
247
   
82
    while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
248
    while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
83
        c++;
249
        c++;
84
   
250
   
85
    return (tolower(a[c]) - tolower(b[c]));
251
    return (tolower(a[c]) - tolower(b[c]));
86
}
252
}
87
 
253
 
88
/** Return pointer to the first occurence of character c in string.
254
/** Return pointer to the first occurence of character c in string.
89
 *
255
 *
90
 * @param str       Scanned string.
256
 * @param str       Scanned string.
91
 * @param c     Searched character (taken as one byte).
257
 * @param c     Searched character (taken as one byte).
92
 * @return      Pointer to the matched character or NULL if it is not
258
 * @return      Pointer to the matched character or NULL if it is not
93
 *          found in given string.
259
 *          found in given string.
94
 */
260
 */
95
char *strchr(const char *str, int c)
261
char *strchr(const char *str, int c)
96
{
262
{
97
    while (*str != '\0') {
263
    while (*str != '\0') {
98
        if (*str == (char) c)
264
        if (*str == (char) c)
99
            return (char *) str;
265
            return (char *) str;
100
        str++;
266
        str++;
101
    }
267
    }
102
 
268
 
103
    return NULL;
269
    return NULL;
104
}
270
}
105
 
271
 
106
/** Return pointer to the last occurence of character c in string.
272
/** Return pointer to the last occurence of character c in string.
107
 *
273
 *
108
 * @param str       Scanned string.
274
 * @param str       Scanned string.
109
 * @param c     Searched character (taken as one byte).
275
 * @param c     Searched character (taken as one byte).
110
 * @return      Pointer to the matched character or NULL if it is not
276
 * @return      Pointer to the matched character or NULL if it is not
111
 *          found in given string.
277
 *          found in given string.
112
 */
278
 */
113
char *strrchr(const char *str, int c)
279
char *strrchr(const char *str, int c)
114
{
280
{
115
    char *retval = NULL;
281
    char *retval = NULL;
116
 
282
 
117
    while (*str != '\0') {
283
    while (*str != '\0') {
118
        if (*str == (char) c)
284
        if (*str == (char) c)
119
            retval = (char *) str;
285
            retval = (char *) str;
120
        str++;
286
        str++;
121
    }
287
    }
122
 
288
 
123
    return (char *) retval;
289
    return (char *) retval;
124
}
290
}
125
 
291
 
126
/** Convert string to a number.
292
/** Convert string to a number.
127
 * Core of strtol and strtoul functions.
293
 * Core of strtol and strtoul functions.
128
 *
294
 *
129
 * @param nptr      Pointer to string.
295
 * @param nptr      Pointer to string.
130
 * @param endptr    If not NULL, function stores here pointer to the first
296
 * @param endptr    If not NULL, function stores here pointer to the first
131
 *          invalid character.
297
 *          invalid character.
132
 * @param base      Zero or number between 2 and 36 inclusive.
298
 * @param base      Zero or number between 2 and 36 inclusive.
133
 * @param sgn       It's set to 1 if minus found.
299
 * @param sgn       It's set to 1 if minus found.
134
 * @return      Result of conversion.
300
 * @return      Result of conversion.
135
 */
301
 */
136
static unsigned long
302
static unsigned long
137
_strtoul(const char *nptr, char **endptr, int base, char *sgn)
303
_strtoul(const char *nptr, char **endptr, int base, char *sgn)
138
{
304
{
139
    unsigned char c;
305
    unsigned char c;
140
    unsigned long result = 0;
306
    unsigned long result = 0;
141
    unsigned long a, b;
307
    unsigned long a, b;
142
    const char *str = nptr;
308
    const char *str = nptr;
143
    const char *tmpptr;
309
    const char *tmpptr;
144
   
310
   
145
    while (isspace(*str))
311
    while (isspace(*str))
146
        str++;
312
        str++;
147
   
313
   
148
    if (*str == '-') {
314
    if (*str == '-') {
149
        *sgn = 1;
315
        *sgn = 1;
150
        ++str;
316
        ++str;
151
    } else if (*str == '+')
317
    } else if (*str == '+')
152
        ++str;
318
        ++str;
153
   
319
   
154
    if (base) {
320
    if (base) {
155
        if ((base == 1) || (base > 36)) {
321
        if ((base == 1) || (base > 36)) {
156
            /* FIXME: set errno to EINVAL */
322
            /* FIXME: set errno to EINVAL */
157
            return 0;
323
            return 0;
158
        }
324
        }
159
        if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
325
        if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
160
            (str[1] == 'X'))) {
326
            (str[1] == 'X'))) {
161
            str += 2;
327
            str += 2;
162
        }
328
        }
163
    } else {
329
    } else {
164
        base = 10;
330
        base = 10;
165
       
331
       
166
        if (*str == '0') {
332
        if (*str == '0') {
167
            base = 8;
333
            base = 8;
168
            if ((str[1] == 'X') || (str[1] == 'x'))  {
334
            if ((str[1] == 'X') || (str[1] == 'x'))  {
169
                base = 16;
335
                base = 16;
170
                str += 2;
336
                str += 2;
171
            }
337
            }
172
        }
338
        }
173
    }
339
    }
174
   
340
   
175
    tmpptr = str;
341
    tmpptr = str;
176
 
342
 
177
    while (*str) {
343
    while (*str) {
178
        c = *str;
344
        c = *str;
179
        c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
345
        c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
180
            (c <= '9' ? c - '0' : 0xff)));
346
            (c <= '9' ? c - '0' : 0xff)));
181
        if (c > base) {
347
        if (c > base) {
182
            break;
348
            break;
183
        }
349
        }
184
       
350
       
185
        a = (result & 0xff) * base + c;
351
        a = (result & 0xff) * base + c;
186
        b = (result >> 8) * base + (a >> 8);
352
        b = (result >> 8) * base + (a >> 8);
187
       
353
       
188
        if (b > (ULONG_MAX >> 8)) {
354
        if (b > (ULONG_MAX >> 8)) {
189
            /* overflow */
355
            /* overflow */
190
            /* FIXME: errno = ERANGE*/
356
            /* FIXME: errno = ERANGE*/
191
            return ULONG_MAX;
357
            return ULONG_MAX;
192
        }
358
        }
193
   
359
   
194
        result = (b << 8) + (a & 0xff);
360
        result = (b << 8) + (a & 0xff);
195
        ++str;
361
        ++str;
196
    }
362
    }
197
   
363
   
198
    if (str == tmpptr) {
364
    if (str == tmpptr) {
199
        /*
365
        /*
200
         * No number was found => first invalid character is the first
366
         * No number was found => first invalid character is the first
201
         * character of the string.
367
         * character of the string.
202
         */
368
         */
203
        /* FIXME: set errno to EINVAL */
369
        /* FIXME: set errno to EINVAL */
204
        str = nptr;
370
        str = nptr;
205
        result = 0;
371
        result = 0;
206
    }
372
    }
207
   
373
   
208
    if (endptr)
374
    if (endptr)
209
        *endptr = (char *) str;
375
        *endptr = (char *) str;
210
 
376
 
211
    if (nptr == str) {
377
    if (nptr == str) {
212
        /*FIXME: errno = EINVAL*/
378
        /*FIXME: errno = EINVAL*/
213
        return 0;
379
        return 0;
214
    }
380
    }
215
 
381
 
216
    return result;
382
    return result;
217
}
383
}
218
 
384
 
219
/** Convert initial part of string to long int according to given base.
385
/** Convert initial part of string to long int according to given base.
220
 * The number may begin with an arbitrary number of whitespaces followed by
386
 * The number may begin with an arbitrary number of whitespaces followed by
221
 * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
387
 * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
222
 * inserted and the number will be taken as hexadecimal one. If the base is 0
388
 * inserted and the number will be taken as hexadecimal one. If the base is 0
223
 * and the number begin with a zero, number will be taken as octal one (as with
389
 * and the number begin with a zero, number will be taken as octal one (as with
224
 * base 8). Otherwise the base 0 is taken as decimal.
390
 * base 8). Otherwise the base 0 is taken as decimal.
225
 *
391
 *
226
 * @param nptr      Pointer to string.
392
 * @param nptr      Pointer to string.
227
 * @param endptr    If not NULL, function stores here pointer to the first
393
 * @param endptr    If not NULL, function stores here pointer to the first
228
 *          invalid character.
394
 *          invalid character.
229
 * @param base      Zero or number between 2 and 36 inclusive.
395
 * @param base      Zero or number between 2 and 36 inclusive.
230
 * @return      Result of conversion.
396
 * @return      Result of conversion.
231
 */
397
 */
232
long int strtol(const char *nptr, char **endptr, int base)
398
long int strtol(const char *nptr, char **endptr, int base)
233
{
399
{
234
    char sgn = 0;
400
    char sgn = 0;
235
    unsigned long number = 0;
401
    unsigned long number = 0;
236
   
402
   
237
    number = _strtoul(nptr, endptr, base, &sgn);
403
    number = _strtoul(nptr, endptr, base, &sgn);
238
 
404
 
239
    if (number > LONG_MAX) {
405
    if (number > LONG_MAX) {
240
        if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
406
        if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
241
            /* FIXME: set 0 to errno */
407
            /* FIXME: set 0 to errno */
242
            return number;     
408
            return number;     
243
        }
409
        }
244
        /* FIXME: set ERANGE to errno */
410
        /* FIXME: set ERANGE to errno */
245
        return (sgn ? LONG_MIN : LONG_MAX);
411
        return (sgn ? LONG_MIN : LONG_MAX);
246
    }
412
    }
247
   
413
   
248
    return (sgn ? -number : number);
414
    return (sgn ? -number : number);
249
}
415
}
250
 
416
 
251
 
417
 
252
/** Convert initial part of string to unsigned long according to given base.
418
/** Convert initial part of string to unsigned long according to given base.
253
 * 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
254
 * 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
255
 * 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
256
 * 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
257
 * base 8). Otherwise the base 0 is taken as decimal.
423
 * base 8). Otherwise the base 0 is taken as decimal.
258
 *
424
 *
259
 * @param nptr      Pointer to string.
425
 * @param nptr      Pointer to string.
260
 * @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
261
 *          invalid character
427
 *          invalid character
262
 * @param base      Zero or number between 2 and 36 inclusive.
428
 * @param base      Zero or number between 2 and 36 inclusive.
263
 * @return      Result of conversion.
429
 * @return      Result of conversion.
264
 */
430
 */
265
unsigned long strtoul(const char *nptr, char **endptr, int base)
431
unsigned long strtoul(const char *nptr, char **endptr, int base)
266
{
432
{
267
    char sgn = 0;
433
    char sgn = 0;
268
    unsigned long number = 0;
434
    unsigned long number = 0;
269
   
435
   
270
    number = _strtoul(nptr, endptr, base, &sgn);
436
    number = _strtoul(nptr, endptr, base, &sgn);
271
 
437
 
272
    return (sgn ? -number : number);
438
    return (sgn ? -number : number);
273
}
439
}
274
 
440
 
275
char *strcpy(char *dest, const char *src)
441
char *strcpy(char *dest, const char *src)
276
{
442
{
277
    char *orig = dest;
443
    char *orig = dest;
278
   
444
   
279
    while ((*(dest++) = *(src++)))
445
    while ((*(dest++) = *(src++)))
280
        ;
446
        ;
281
    return orig;
447
    return orig;
282
}
448
}
283
 
449
 
284
char *strncpy(char *dest, const char *src, size_t n)
450
char *strncpy(char *dest, const char *src, size_t n)
285
{
451
{
286
    char *orig = dest;
452
    char *orig = dest;
287
   
453
   
288
    while ((*(dest++) = *(src++)) && --n)
454
    while ((*(dest++) = *(src++)) && --n)
289
        ;
455
        ;
290
    return orig;
456
    return orig;
291
}
457
}
292
 
458
 
293
char *strcat(char *dest, const char *src)
459
char *strcat(char *dest, const char *src)
294
{
460
{
295
    char *orig = dest;
461
    char *orig = dest;
296
    while (*dest++)
462
    while (*dest++)
297
        ;
463
        ;
298
    --dest;
464
    --dest;
299
    while ((*dest++ = *src++))
465
    while ((*dest++ = *src++))
300
        ;
466
        ;
301
    return orig;
467
    return orig;
302
}
468
}
303
 
469
 
304
char * strdup(const char *s1)
470
char * strdup(const char *s1)
305
{
471
{
306
    size_t len = strlen(s1) + 1;
472
    size_t len = strlen(s1) + 1;
307
    void *ret = malloc(len);
473
    void *ret = malloc(len);
308
 
474
 
309
    if (ret == NULL)
475
    if (ret == NULL)
310
        return (char *) NULL;
476
        return (char *) NULL;
311
 
477
 
312
    return (char *) memcpy(ret, s1, len);
478
    return (char *) memcpy(ret, s1, len);
313
}
479
}
314
 
480
 
315
char *strtok(char *s, const char *delim)
481
char *strtok(char *s, const char *delim)
316
{
482
{
317
    static char *next;
483
    static char *next;
318
 
484
 
319
    return strtok_r(s, delim, &next);
485
    return strtok_r(s, delim, &next);
320
}
486
}
321
 
487
 
322
char *strtok_r(char *s, const char *delim, char **next)
488
char *strtok_r(char *s, const char *delim, char **next)
323
{
489
{
324
    char *start, *end;
490
    char *start, *end;
325
 
491
 
326
    if (s == NULL)
492
    if (s == NULL)
327
        s = *next;
493
        s = *next;
328
 
494
 
329
    /* Skip over leading delimiters. */
495
    /* Skip over leading delimiters. */
330
    while (*s && (strchr(delim, *s) != NULL)) ++s;
496
    while (*s && (strchr(delim, *s) != NULL)) ++s;
331
    start = s;
497
    start = s;
332
 
498
 
333
    /* Skip over token characters. */
499
    /* Skip over token characters. */
334
    while (*s && (strchr(delim, *s) == NULL)) ++s;
500
    while (*s && (strchr(delim, *s) == NULL)) ++s;
335
    end = s;
501
    end = s;
336
    *next = (*s ? s + 1 : s);
502
    *next = (*s ? s + 1 : s);
337
 
503
 
338
    if (start == end) {
504
    if (start == end) {
339
        return NULL;    /* No more tokens. */
505
        return NULL;    /* No more tokens. */
340
    }
506
    }
341
 
507
 
342
    /* Overwrite delimiter with NULL terminator. */
508
    /* Overwrite delimiter with NULL terminator. */
343
    *end = '\0';
509
    *end = '\0';
344
    return start;
510
    return start;
345
}
511
}
346
 
512
 
347
/** @}
513
/** @}
348
 */
514
 */
349
 
515