LCOV - code coverage report
Current view: top level - lib - xstrtol.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 93 99 93.9 %
Date: 2018-01-30 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* A more useful interface to strtol.
       2             : 
       3             :    Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
       4             :    2006, 2007 Free Software Foundation, Inc.
       5             : 
       6             :    This program is free software: you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      18             : 
      19             : /* Written by Jim Meyering. */
      20             : 
      21             : #ifndef __strtol
      22             : # define __strtol strtol
      23             : # define __strtol_t long int
      24             : # define __xstrtol xstrtol
      25             : # define STRTOL_T_MINIMUM LONG_MIN
      26             : # define STRTOL_T_MAXIMUM LONG_MAX
      27             : #endif
      28             : 
      29             : #include <config.h>
      30             : 
      31             : #include "xstrtol.h"
      32             : 
      33             : /* Some pre-ANSI implementations (e.g. SunOS 4)
      34             :    need stderr defined if assertion checking is enabled.  */
      35             : #include <stdio.h>
      36             : 
      37             : #include <assert.h>
      38             : #include <ctype.h>
      39             : #include <errno.h>
      40             : #include <limits.h>
      41             : #include <stdlib.h>
      42             : #include <string.h>
      43             : 
      44             : #include "intprops.h"
      45             : 
      46             : static strtol_error
      47         310 : bkm_scale (__strtol_t *x, int scale_factor)
      48             : {
      49           0 :   if (TYPE_SIGNED (__strtol_t) && *x < STRTOL_T_MINIMUM / scale_factor)
      50             :     {
      51           0 :       *x = STRTOL_T_MINIMUM;
      52           0 :       return LONGINT_OVERFLOW;
      53             :     }
      54         310 :   if (STRTOL_T_MAXIMUM / scale_factor < *x)
      55             :     {
      56          20 :       *x = STRTOL_T_MAXIMUM;
      57          20 :       return LONGINT_OVERFLOW;
      58             :     }
      59         290 :   *x *= scale_factor;
      60         290 :   return LONGINT_OK;
      61             : }
      62             : 
      63             : static strtol_error
      64          60 : bkm_scale_by_power (__strtol_t *x, int base, int power)
      65             : {
      66          60 :   strtol_error err = LONGINT_OK;
      67         404 :   while (power--)
      68         284 :     err |= bkm_scale (x, base);
      69          60 :   return err;
      70             : }
      71             : 
      72             : /* FIXME: comment.  */
      73             : 
      74             : strtol_error
      75         803 : __xstrtol (const char *s, char **ptr, int strtol_base,
      76             :            __strtol_t *val, const char *valid_suffixes)
      77             : {
      78             :   char *t_ptr;
      79             :   char **p;
      80             :   __strtol_t tmp;
      81         803 :   strtol_error err = LONGINT_OK;
      82             : 
      83         803 :   assert (0 <= strtol_base && strtol_base <= 36);
      84             : 
      85         803 :   p = (ptr ? ptr : &t_ptr);
      86             : 
      87             :   if (! TYPE_SIGNED (__strtol_t))
      88             :     {
      89         712 :       const char *q = s;
      90         712 :       unsigned char ch = *q;
      91        1524 :       while (isspace (ch))
      92         100 :         ch = *++q;
      93         712 :       if (ch == '-')
      94         170 :         return LONGINT_INVALID;
      95             :     }
      96             : 
      97         633 :   errno = 0;
      98         633 :   tmp = __strtol (s, p, strtol_base);
      99             : 
     100         633 :   if (*p == s)
     101             :     {
     102             :       /* If there is no number but there is a valid suffix, assume the
     103             :          number is 1.  The string is invalid otherwise.  */
     104         244 :       if (valid_suffixes && **p && strchr (valid_suffixes, **p))
     105          69 :         tmp = 1;
     106             :       else
     107         175 :         return LONGINT_INVALID;
     108             :     }
     109         389 :   else if (errno != 0)
     110             :     {
     111           0 :       if (errno != ERANGE)
     112           0 :         return LONGINT_INVALID;
     113           0 :       err = LONGINT_OVERFLOW;
     114             :     }
     115             : 
     116             :   /* Let valid_suffixes == NULL mean `allow any suffix'.  */
     117             :   /* FIXME: update all callers except the ones that allow suffixes
     118             :      after the number, changing last parameter NULL to `""'.  */
     119         458 :   if (!valid_suffixes)
     120             :     {
     121          63 :       *val = tmp;
     122          63 :       return err;
     123             :     }
     124             : 
     125         395 :   if (**p != '\0')
     126             :     {
     127         181 :       int base = 1024;
     128         181 :       int suffixes = 1;
     129             :       strtol_error overflow;
     130             : 
     131         181 :       if (!strchr (valid_suffixes, **p))
     132             :         {
     133          88 :           *val = tmp;
     134          88 :           return err | LONGINT_INVALID_SUFFIX_CHAR;
     135             :         }
     136             : 
     137          93 :       if (strchr (valid_suffixes, '0'))
     138             :         {
     139             :           /* The ``valid suffix'' '0' is a special flag meaning that
     140             :              an optional second suffix is allowed, which can change
     141             :              the base.  A suffix "B" (e.g. "100MB") stands for a power
     142             :              of 1000, whereas a suffix "iB" (e.g. "100MiB") stands for
     143             :              a power of 1024.  If no suffix (e.g. "100M"), assume
     144             :              power-of-1024.  */
     145             : 
     146          87 :           switch (p[0][1])
     147             :             {
     148           6 :             case 'i':
     149           6 :               if (p[0][2] == 'B')
     150           2 :                 suffixes += 2;
     151           6 :               break;
     152             : 
     153          17 :             case 'B':
     154             :             case 'D': /* 'D' is obsolescent */
     155          17 :               base = 1000;
     156          17 :               suffixes++;
     157          17 :               break;
     158             :             }
     159             :         }
     160             : 
     161          93 :       switch (**p)
     162             :         {
     163          21 :         case 'b':
     164          21 :           overflow = bkm_scale (&tmp, 512);
     165          21 :           break;
     166             : 
     167           4 :         case 'B':
     168           4 :           overflow = bkm_scale (&tmp, 1024);
     169           4 :           break;
     170             : 
     171           3 :         case 'c':
     172           3 :           overflow = 0;
     173           3 :           break;
     174             : 
     175          12 :         case 'E': /* exa or exbi */
     176          12 :           overflow = bkm_scale_by_power (&tmp, base, 6);
     177          12 :           break;
     178             : 
     179           6 :         case 'G': /* giga or gibi */
     180             :         case 'g': /* 'g' is undocumented; for compatibility only */
     181           6 :           overflow = bkm_scale_by_power (&tmp, base, 3);
     182           6 :           break;
     183             : 
     184           8 :         case 'k': /* kilo */
     185             :         case 'K': /* kibi */
     186           8 :           overflow = bkm_scale_by_power (&tmp, base, 1);
     187           8 :           break;
     188             : 
     189           5 :         case 'M': /* mega or mebi */
     190             :         case 'm': /* 'm' is undocumented; for compatibility only */
     191           5 :           overflow = bkm_scale_by_power (&tmp, base, 2);
     192           5 :           break;
     193             : 
     194           7 :         case 'P': /* peta or pebi */
     195           7 :           overflow = bkm_scale_by_power (&tmp, base, 5);
     196           7 :           break;
     197             : 
     198           7 :         case 'T': /* tera or tebi */
     199             :         case 't': /* 't' is undocumented; for compatibility only */
     200           7 :           overflow = bkm_scale_by_power (&tmp, base, 4);
     201           7 :           break;
     202             : 
     203           1 :         case 'w':
     204           1 :           overflow = bkm_scale (&tmp, 2);
     205           1 :           break;
     206             : 
     207           8 :         case 'Y': /* yotta or 2**80 */
     208           8 :           overflow = bkm_scale_by_power (&tmp, base, 8);
     209           8 :           break;
     210             : 
     211           7 :         case 'Z': /* zetta or 2**70 */
     212           7 :           overflow = bkm_scale_by_power (&tmp, base, 7);
     213           7 :           break;
     214             : 
     215           4 :         default:
     216           4 :           *val = tmp;
     217           4 :           return err | LONGINT_INVALID_SUFFIX_CHAR;
     218             :         }
     219             : 
     220          89 :       err |= overflow;
     221          89 :       *p += suffixes;
     222          89 :       if (**p)
     223           6 :         err |= LONGINT_INVALID_SUFFIX_CHAR;
     224             :     }
     225             : 
     226         303 :   *val = tmp;
     227         303 :   return err;
     228             : }

Generated by: LCOV version 1.10