Changeset d39c46e0 in mainline


Ignore:
Timestamp:
2018-01-16T19:12:36Z (6 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
33b8d024
Parents:
aec41c8
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2018-01-16 19:04:19)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2018-01-16 19:12:36)
Message:

Implement the full suite of standard string-to-int conversion functions in libc.

Location:
uspace/lib
Files:
1 added
1 deleted
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/Makefile

    raec41c8 rd39c46e0  
    8585        generic/str.c \
    8686        generic/str_error.c \
     87        generic/strtol.c \
    8788        generic/l18n/langs.c \
    8889        generic/fibril.c \
  • uspace/lib/c/generic/str.c

    raec41c8 rd39c46e0  
    12731273}
    12741274
    1275 /** Convert string to a number.
    1276  * Core of strtol and strtoul functions.
    1277  *
    1278  * @param nptr          Pointer to string.
    1279  * @param endptr        If not NULL, function stores here pointer to the first
    1280  *                      invalid character.
    1281  * @param base          Zero or number between 2 and 36 inclusive.
    1282  * @param sgn           It's set to 1 if minus found.
    1283  * @return              Result of conversion.
    1284  */
    1285 static unsigned long
    1286 _strtoul(const char *nptr, char **endptr, int base, char *sgn)
    1287 {
    1288         unsigned char c;
    1289         unsigned long result = 0;
    1290         unsigned long a, b;
    1291         const char *str = nptr;
    1292         const char *tmpptr;
    1293        
    1294         while (isspace(*str))
    1295                 str++;
    1296        
    1297         if (*str == '-') {
    1298                 *sgn = 1;
    1299                 ++str;
    1300         } else if (*str == '+')
    1301                 ++str;
    1302        
    1303         if (base) {
    1304                 if ((base == 1) || (base > 36)) {
    1305                         /* FIXME: set errno to EINVAL */
    1306                         return 0;
    1307                 }
    1308                 if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
    1309                     (str[1] == 'X'))) {
    1310                         str += 2;
    1311                 }
    1312         } else {
    1313                 base = 10;
    1314                
    1315                 if (*str == '0') {
    1316                         base = 8;
    1317                         if ((str[1] == 'X') || (str[1] == 'x'))  {
    1318                                 base = 16;
    1319                                 str += 2;
    1320                         }
    1321                 }
    1322         }
    1323        
    1324         tmpptr = str;
    1325 
    1326         while (*str) {
    1327                 c = *str;
    1328                 c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
    1329                     (c <= '9' ? c - '0' : 0xff)));
    1330                 if (c >= base) {
    1331                         break;
    1332                 }
    1333                
    1334                 a = (result & 0xff) * base + c;
    1335                 b = (result >> 8) * base + (a >> 8);
    1336                
    1337                 if (b > (ULONG_MAX >> 8)) {
    1338                         /* overflow */
    1339                         /* FIXME: errno = ERANGE*/
    1340                         return ULONG_MAX;
    1341                 }
    1342        
    1343                 result = (b << 8) + (a & 0xff);
    1344                 ++str;
    1345         }
    1346        
    1347         if (str == tmpptr) {
    1348                 /*
    1349                  * No number was found => first invalid character is the first
    1350                  * character of the string.
    1351                  */
    1352                 /* FIXME: set errno to EINVAL */
    1353                 str = nptr;
    1354                 result = 0;
    1355         }
    1356        
    1357         if (endptr)
    1358                 *endptr = (char *) str;
    1359 
    1360         if (nptr == str) {
    1361                 /*FIXME: errno = EINVAL*/
    1362                 return 0;
    1363         }
    1364 
    1365         return result;
    1366 }
    1367 
    1368 /** Convert initial part of string to long int according to given base.
    1369  * The number may begin with an arbitrary number of whitespaces followed by
    1370  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
    1371  * inserted and the number will be taken as hexadecimal one. If the base is 0
    1372  * and the number begin with a zero, number will be taken as octal one (as with
    1373  * base 8). Otherwise the base 0 is taken as decimal.
    1374  *
    1375  * @param nptr          Pointer to string.
    1376  * @param endptr        If not NULL, function stores here pointer to the first
    1377  *                      invalid character.
    1378  * @param base          Zero or number between 2 and 36 inclusive.
    1379  * @return              Result of conversion.
    1380  */
    1381 long int strtol(const char *nptr, char **endptr, int base)
    1382 {
    1383         char sgn = 0;
    1384         unsigned long number = 0;
    1385        
    1386         number = _strtoul(nptr, endptr, base, &sgn);
    1387 
    1388         if (number > LONG_MAX) {
    1389                 if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
    1390                         /* FIXME: set 0 to errno */
    1391                         return number;
    1392                 }
    1393                 /* FIXME: set ERANGE to errno */
    1394                 return (sgn ? LONG_MIN : LONG_MAX);
    1395         }
    1396        
    1397         return (sgn ? -number : number);
    1398 }
    13991275
    14001276/** Duplicate string.
     
    14571333        str_ncpy(dest, size + 1, src, size);
    14581334        return dest;
    1459 }
    1460 
    1461 /** Convert initial part of string to unsigned long according to given base.
    1462  * The number may begin with an arbitrary number of whitespaces followed by
    1463  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
    1464  * inserted and the number will be taken as hexadecimal one. If the base is 0
    1465  * and the number begin with a zero, number will be taken as octal one (as with
    1466  * base 8). Otherwise the base 0 is taken as decimal.
    1467  *
    1468  * @param nptr          Pointer to string.
    1469  * @param endptr        If not NULL, function stores here pointer to the first
    1470  *                      invalid character
    1471  * @param base          Zero or number between 2 and 36 inclusive.
    1472  * @return              Result of conversion.
    1473  */
    1474 unsigned long strtoul(const char *nptr, char **endptr, int base)
    1475 {
    1476         char sgn = 0;
    1477         unsigned long number = 0;
    1478        
    1479         number = _strtoul(nptr, endptr, base, &sgn);
    1480 
    1481         return (sgn ? -number : number);
    14821335}
    14831336
  • uspace/lib/c/include/inttypes.h

    raec41c8 rd39c46e0  
    3838#include <_bits/inttypes.h>
    3939
     40#ifndef __HELENOS_DISABLE_INTMAX__
     41intmax_t strtoimax(const char *__restrict__ nptr,
     42    char **__restrict__ endptr, int base);
     43uintmax_t strtoumax(const char *__restrict__ nptr,
     44    char **__restrict__ endptr, int base);
     45#endif
     46
    4047#endif
    4148
  • uspace/lib/c/include/stdlib.h

    raec41c8 rd39c46e0  
    4848extern void exit(int) __attribute__((noreturn));
    4949
     50extern int atoi(const char *);
     51extern long atol(const char *);
     52extern long long atoll(const char *);
     53
     54extern long strtol(const char *__restrict__, char **__restrict__, int);
     55extern long long strtoll(const char *__restrict__, char **__restrict__, int);
     56extern unsigned long strtoul(const char *__restrict__, char **__restrict__, int);
     57extern unsigned long long strtoull(const char *__restrict__, char **__restrict__, int);
     58
    5059#endif
    5160
  • uspace/lib/posix/Makefile

    raec41c8 rd39c46e0  
    7676        source/stdio/scanf.c \
    7777        source/stdlib.c \
    78         source/stdlib/strtol.c \
    7978        source/stdlib/strtold.c \
    8079        source/string.c \
  • uspace/lib/posix/include/posix/inttypes.h

    raec41c8 rd39c46e0  
    4343#include "libc/inttypes.h"
    4444
    45 extern intmax_t __POSIX_DEF__(strtoimax)(const char *__restrict__ nptr,
    46     char **__restrict__ endptr, int base);
    47 extern uintmax_t __POSIX_DEF__(strtoumax)(const char *__restrict__ nptr,
    48     char **__restrict__ endptr, int base);
    49 
    50 
    5145#endif /* POSIX_INTTYPES_H_ */
    5246
  • uspace/lib/posix/include/posix/stdlib.h

    raec41c8 rd39c46e0  
    101101
    102102/* Integer Conversion */
    103 extern int __POSIX_DEF__(atoi)(const char *nptr);
    104 extern long int __POSIX_DEF__(atol)(const char *nptr);
    105 extern long long int __POSIX_DEF__(atoll)(const char *nptr);
    106 extern long int __POSIX_DEF__(strtol)(const char *__restrict__ nptr,
     103extern int atoi(const char *nptr);
     104extern long int atol(const char *nptr);
     105extern long long int atoll(const char *nptr);
     106extern long int strtol(const char *__restrict__ nptr,
    107107    char **__restrict__ endptr, int base);
    108 extern long long int __POSIX_DEF__(strtoll)(const char *__restrict__ nptr,
     108extern long long int strtoll(const char *__restrict__ nptr,
    109109    char **__restrict__ endptr, int base);
    110 extern unsigned long int __POSIX_DEF__(strtoul)(const char *__restrict__ nptr,
     110extern unsigned long int strtoul(const char *__restrict__ nptr,
    111111    char **__restrict__ endptr, int base);
    112 extern unsigned long long int __POSIX_DEF__(strtoull)(
     112extern unsigned long long int strtoull(
    113113    const char *__restrict__ nptr, char **__restrict__ endptr, int base);
    114114
  • uspace/lib/posix/source/stdio/scanf.c

    raec41c8 rd39c46e0  
    563563                                }
    564564                                char *fmt_new = NULL;
    565                                 width = posix_strtol(fmt, &fmt_new, 10);
     565                                width = strtol(fmt, &fmt_new, 10);
    566566                                if (width != 0) {
    567567                                        fmt = fmt_new;
     
    648648                                /* Try to convert the integer. */
    649649                                if (int_conv_unsigned) {
    650                                         ures = posix_strtoull(cur_limited, &cur_updated, int_conv_base);
     650                                        ures = strtoull(cur_limited, &cur_updated, int_conv_base);
    651651                                } else {
    652                                         sres = posix_strtoll(cur_limited, &cur_updated, int_conv_base);
     652                                        sres = strtoll(cur_limited, &cur_updated, int_conv_base);
    653653                                }
    654654
Note: See TracChangeset for help on using the changeset viewer.