(root)/
coreutils-9.4/
lib/
xdectoint.c
       1  /* Convert decimal strings with bounds checking and exit on error.
       2  
       3     Copyright (C) 2014-2023 Free Software Foundation, Inc.
       4  
       5     This program is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation; either version 3 of the License, or
       8     (at your option) any later version.
       9  
      10     This program is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <config.h>
      19  
      20  #include "xdectoint.h"
      21  
      22  #include <errno.h>
      23  #include <inttypes.h>
      24  #include <stddef.h>
      25  #include <stdlib.h>
      26  
      27  #include "error.h"
      28  #include "quote.h"
      29  #include "xstrtol.h"
      30  
      31  /* Parse numeric string N_STR of base BASE, and return the value.
      32     Exit on parse error or if MIN or MAX are exceeded.
      33     Strings can have multiplicative SUFFIXES if specified.
      34     ERR is printed along with N_STR on error.  */
      35  
      36  __xdectoint_t
      37  __xnumtoint (char const *n_str, int base, __xdectoint_t min, __xdectoint_t max,
      38               char const *suffixes, char const *err, int err_exit)
      39  {
      40    strtol_error s_err;
      41  
      42    __xdectoint_t tnum;
      43    s_err = __xstrtol (n_str, nullptr, base, &tnum, suffixes);
      44  
      45    if (s_err == LONGINT_OK)
      46      {
      47        if (tnum < min || max < tnum)
      48          {
      49            s_err = LONGINT_OVERFLOW;
      50            /* Use have the INT range as a heuristic to distinguish
      51               type overflow rather than other min/max limits.  */
      52            if (tnum > INT_MAX / 2)
      53              errno = EOVERFLOW;
      54  #if __xdectoint_signed
      55            else if (tnum < INT_MIN / 2)
      56              errno = EOVERFLOW;
      57  #endif
      58            else
      59              errno = ERANGE;
      60          }
      61      }
      62    else if (s_err == LONGINT_OVERFLOW)
      63      errno = EOVERFLOW;
      64    else if (s_err == LONGINT_INVALID_SUFFIX_CHAR_WITH_OVERFLOW)
      65      errno = 0; /* Don't show ERANGE errors for invalid numbers.  */
      66  
      67    if (s_err != LONGINT_OK)
      68      {
      69        /* EINVAL error message is redundant in this context.  */
      70        error (err_exit ? err_exit : EXIT_FAILURE, errno == EINVAL ? 0 : errno,
      71               "%s: %s", err, quote (n_str));
      72        unreachable ();
      73      }
      74  
      75    return tnum;
      76  }
      77  
      78  /* Parse decimal string N_STR, and return the value.
      79     Exit on parse error or if MIN or MAX are exceeded.
      80     Strings can have multiplicative SUFFIXES if specified.
      81     ERR is printed along with N_STR on error.  */
      82  
      83  __xdectoint_t
      84  __xdectoint (char const *n_str, __xdectoint_t min, __xdectoint_t max,
      85               char const *suffixes, char const *err, int err_exit)
      86  {
      87    return __xnumtoint (n_str, 10, min, max, suffixes, err, err_exit);
      88  }