~ubuntu-branches/ubuntu/natty/diffutils/natty

« back to all changes in this revision

Viewing changes to lib/xstrtol.c

  • Committer: Bazaar Package Importer
  • Author(s): Santiago Vila
  • Date: 2010-05-04 20:38:00 UTC
  • mfrom: (2.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100504203800-f67xd9rsa9xl9qqj
Tags: 1:3.0-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* A more useful interface to strtol.
2
 
   Copyright (C) 1995, 1996, 1998-2001 Free Software Foundation, Inc.
3
 
 
4
 
   This program is free software; you can redistribute it and/or modify
 
2
 
 
3
   Copyright (C) 1995-1996, 1998-2001, 2003-2007, 2009-2010 Free Software
 
4
   Foundation, Inc.
 
5
 
 
6
   This program is free software: you can redistribute it and/or modify
5
7
   it under the terms of the GNU General Public License as published by
6
 
   the Free Software Foundation; either version 2, or (at your option)
7
 
   any later version.
 
8
   the Free Software Foundation; either version 3 of the License, or
 
9
   (at your option) any later version.
8
10
 
9
11
   This program is distributed in the hope that it will be useful,
10
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
14
   GNU General Public License for more details.
13
15
 
14
16
   You should have received a copy of the GNU General Public License
15
 
   along with this program; if not, write to the Free Software Foundation,
16
 
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18
 
18
19
/* Written by Jim Meyering. */
19
20
 
20
 
#if HAVE_CONFIG_H
21
 
# include <config.h>
22
 
#endif
23
 
 
24
21
#ifndef __strtol
25
22
# define __strtol strtol
26
23
# define __strtol_t long int
27
24
# define __xstrtol xstrtol
 
25
# define STRTOL_T_MINIMUM LONG_MIN
 
26
# define STRTOL_T_MAXIMUM LONG_MAX
28
27
#endif
29
28
 
 
29
#include <config.h>
 
30
 
 
31
#include "xstrtol.h"
 
32
 
30
33
/* Some pre-ANSI implementations (e.g. SunOS 4)
31
34
   need stderr defined if assertion checking is enabled.  */
32
35
#include <stdio.h>
33
36
 
34
 
#if STDC_HEADERS
35
 
# include <stdlib.h>
36
 
#endif
37
 
 
38
 
#if HAVE_STRING_H
39
 
# include <string.h>
40
 
#else
41
 
# include <strings.h>
42
 
# ifndef strchr
43
 
#  define strchr index
44
 
# endif
45
 
#endif
46
 
 
47
37
#include <assert.h>
48
38
#include <ctype.h>
49
 
 
50
39
#include <errno.h>
51
 
#ifndef errno
52
 
extern int errno;
53
 
#endif
54
 
 
55
 
#if HAVE_LIMITS_H
56
 
# include <limits.h>
57
 
#endif
58
 
 
59
 
#ifndef CHAR_BIT
60
 
# define CHAR_BIT 8
61
 
#endif
62
 
 
63
 
/* The extra casts work around common compiler bugs.  */
64
 
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
65
 
/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
66
 
   It is necessary at least when t == time_t.  */
67
 
#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
68
 
                              ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
69
 
#define TYPE_MAXIMUM(t) (~ (t) 0 - TYPE_MINIMUM (t))
70
 
 
71
 
#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
72
 
# define IN_CTYPE_DOMAIN(c) 1
73
 
#else
74
 
# define IN_CTYPE_DOMAIN(c) isascii(c)
75
 
#endif
76
 
 
77
 
#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
78
 
 
79
 
#include "xstrtol.h"
80
 
 
81
 
#if !HAVE_DECL_STRTOL && !defined strtol
82
 
long int strtol ();
83
 
#endif
84
 
 
85
 
#if !HAVE_DECL_STRTOUL && !defined strtoul
86
 
unsigned long int strtoul ();
87
 
#endif
88
 
 
89
 
#if !HAVE_DECL_STRTOIMAX && !defined strtoimax
90
 
intmax_t strtoimax ();
91
 
#endif
92
 
 
93
 
#if !HAVE_DECL_STRTOUMAX && !defined strtoumax
94
 
uintmax_t strtoumax ();
95
 
#endif
96
 
 
97
 
static int
 
40
#include <limits.h>
 
41
#include <stdlib.h>
 
42
#include <string.h>
 
43
 
 
44
#include "intprops.h"
 
45
 
 
46
static strtol_error
98
47
bkm_scale (__strtol_t *x, int scale_factor)
99
48
{
100
 
  __strtol_t product = *x * scale_factor;
101
 
  if (*x != product / scale_factor)
102
 
    return 1;
103
 
  *x = product;
104
 
  return 0;
 
49
  if (TYPE_SIGNED (__strtol_t) && *x < STRTOL_T_MINIMUM / scale_factor)
 
50
    {
 
51
      *x = STRTOL_T_MINIMUM;
 
52
      return LONGINT_OVERFLOW;
 
53
    }
 
54
  if (STRTOL_T_MAXIMUM / scale_factor < *x)
 
55
    {
 
56
      *x = STRTOL_T_MAXIMUM;
 
57
      return LONGINT_OVERFLOW;
 
58
    }
 
59
  *x *= scale_factor;
 
60
  return LONGINT_OK;
105
61
}
106
62
 
107
 
static int
 
63
static strtol_error
108
64
bkm_scale_by_power (__strtol_t *x, int base, int power)
109
65
{
 
66
  strtol_error err = LONGINT_OK;
110
67
  while (power--)
111
 
    if (bkm_scale (x, base))
112
 
      return 1;
113
 
 
114
 
  return 0;
 
68
    err |= bkm_scale (x, base);
 
69
  return err;
115
70
}
116
71
 
117
72
/* FIXME: comment.  */
118
73
 
119
74
strtol_error
120
75
__xstrtol (const char *s, char **ptr, int strtol_base,
121
 
           __strtol_t *val, const char *valid_suffixes)
 
76
           __strtol_t *val, const char *valid_suffixes)
122
77
{
123
78
  char *t_ptr;
124
79
  char **p;
125
80
  __strtol_t tmp;
 
81
  strtol_error err = LONGINT_OK;
126
82
 
127
83
  assert (0 <= strtol_base && strtol_base <= 36);
128
84
 
131
87
  if (! TYPE_SIGNED (__strtol_t))
132
88
    {
133
89
      const char *q = s;
134
 
      while (ISSPACE ((unsigned char) *q))
135
 
        ++q;
136
 
      if (*q == '-')
137
 
        return LONGINT_INVALID;
 
90
      unsigned char ch = *q;
 
91
      while (isspace (ch))
 
92
        ch = *++q;
 
93
      if (ch == '-')
 
94
        return LONGINT_INVALID;
138
95
    }
139
96
 
140
97
  errno = 0;
141
98
  tmp = __strtol (s, p, strtol_base);
142
 
  if (errno != 0)
143
 
    return LONGINT_OVERFLOW;
144
99
 
145
100
  if (*p == s)
146
101
    {
147
102
      /* If there is no number but there is a valid suffix, assume the
148
 
         number is 1.  The string is invalid otherwise.  */
 
103
         number is 1.  The string is invalid otherwise.  */
149
104
      if (valid_suffixes && **p && strchr (valid_suffixes, **p))
150
 
        tmp = 1;
 
105
        tmp = 1;
151
106
      else
152
 
        return LONGINT_INVALID;
 
107
        return LONGINT_INVALID;
 
108
    }
 
109
  else if (errno != 0)
 
110
    {
 
111
      if (errno != ERANGE)
 
112
        return LONGINT_INVALID;
 
113
      err = LONGINT_OVERFLOW;
153
114
    }
154
115
 
155
116
  /* Let valid_suffixes == NULL mean `allow any suffix'.  */
158
119
  if (!valid_suffixes)
159
120
    {
160
121
      *val = tmp;
161
 
      return LONGINT_OK;
 
122
      return err;
162
123
    }
163
124
 
164
125
  if (**p != '\0')
165
126
    {
166
127
      int base = 1024;
167
128
      int suffixes = 1;
168
 
      int overflow;
 
129
      strtol_error overflow;
169
130
 
170
131
      if (!strchr (valid_suffixes, **p))
171
 
        {
172
 
          *val = tmp;
173
 
          return LONGINT_INVALID_SUFFIX_CHAR;
174
 
        }
 
132
        {
 
133
          *val = tmp;
 
134
          return err | LONGINT_INVALID_SUFFIX_CHAR;
 
135
        }
175
136
 
176
137
      if (strchr (valid_suffixes, '0'))
177
 
        {
178
 
          /* The ``valid suffix'' '0' is a special flag meaning that
179
 
             an optional second suffix is allowed, which can change
180
 
             the base.  A suffix "B" (e.g. "100MB") stands for a power
181
 
             of 1000, whereas a suffix "iB" (e.g. "100MiB") stands for
182
 
             a power of 1024.  If no suffix (e.g. "100M"), assume
183
 
             power-of-1024.  */
184
 
 
185
 
          switch (p[0][1])
186
 
            {
187
 
            case 'i':
188
 
              if (p[0][2] == 'B')
189
 
                suffixes += 2;
190
 
              break;
191
 
 
192
 
            case 'B':
193
 
            case 'D': /* 'D' is obsolescent */
194
 
              base = 1000;
195
 
              suffixes++;
196
 
              break;
197
 
            }
198
 
        }
 
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
          switch (p[0][1])
 
147
            {
 
148
            case 'i':
 
149
              if (p[0][2] == 'B')
 
150
                suffixes += 2;
 
151
              break;
 
152
 
 
153
            case 'B':
 
154
            case 'D': /* 'D' is obsolescent */
 
155
              base = 1000;
 
156
              suffixes++;
 
157
              break;
 
158
            }
 
159
        }
199
160
 
200
161
      switch (**p)
201
 
        {
202
 
        case 'b':
203
 
          overflow = bkm_scale (&tmp, 512);
204
 
          break;
205
 
 
206
 
        case 'B':
207
 
          overflow = bkm_scale (&tmp, 1024);
208
 
          break;
209
 
 
210
 
        case 'c':
211
 
          overflow = 0;
212
 
          break;
213
 
 
214
 
        case 'E': /* exa or exbi */
215
 
          overflow = bkm_scale_by_power (&tmp, base, 6);
216
 
          break;
217
 
 
218
 
        case 'G': /* giga or gibi */
219
 
        case 'g': /* 'g' is undocumented; for compatibility only */
220
 
          overflow = bkm_scale_by_power (&tmp, base, 3);
221
 
          break;
222
 
 
223
 
        case 'k': /* kilo */
224
 
        case 'K': /* kibi */
225
 
          overflow = bkm_scale_by_power (&tmp, base, 1);
226
 
          break;
227
 
 
228
 
        case 'M': /* mega or mebi */
229
 
        case 'm': /* 'm' is undocumented; for compatibility only */
230
 
          overflow = bkm_scale_by_power (&tmp, base, 2);
231
 
          break;
232
 
 
233
 
        case 'P': /* peta or pebi */
234
 
          overflow = bkm_scale_by_power (&tmp, base, 5);
235
 
          break;
236
 
 
237
 
        case 'T': /* tera or tebi */
238
 
        case 't': /* 't' is undocumented; for compatibility only */
239
 
          overflow = bkm_scale_by_power (&tmp, base, 4);
240
 
          break;
241
 
 
242
 
        case 'w':
243
 
          overflow = bkm_scale (&tmp, 2);
244
 
          break;
245
 
 
246
 
        case 'Y': /* yotta or 2**80 */
247
 
          overflow = bkm_scale_by_power (&tmp, base, 8);
248
 
          break;
249
 
 
250
 
        case 'Z': /* zetta or 2**70 */
251
 
          overflow = bkm_scale_by_power (&tmp, base, 7);
252
 
          break;
253
 
 
254
 
        default:
255
 
          *val = tmp;
256
 
          return LONGINT_INVALID_SUFFIX_CHAR;
257
 
          break;
258
 
        }
259
 
 
260
 
      if (overflow)
261
 
        return LONGINT_OVERFLOW;
262
 
 
263
 
      (*p) += suffixes;
 
162
        {
 
163
        case 'b':
 
164
          overflow = bkm_scale (&tmp, 512);
 
165
          break;
 
166
 
 
167
        case 'B':
 
168
          overflow = bkm_scale (&tmp, 1024);
 
169
          break;
 
170
 
 
171
        case 'c':
 
172
          overflow = 0;
 
173
          break;
 
174
 
 
175
        case 'E': /* exa or exbi */
 
176
          overflow = bkm_scale_by_power (&tmp, base, 6);
 
177
          break;
 
178
 
 
179
        case 'G': /* giga or gibi */
 
180
        case 'g': /* 'g' is undocumented; for compatibility only */
 
181
          overflow = bkm_scale_by_power (&tmp, base, 3);
 
182
          break;
 
183
 
 
184
        case 'k': /* kilo */
 
185
        case 'K': /* kibi */
 
186
          overflow = bkm_scale_by_power (&tmp, base, 1);
 
187
          break;
 
188
 
 
189
        case 'M': /* mega or mebi */
 
190
        case 'm': /* 'm' is undocumented; for compatibility only */
 
191
          overflow = bkm_scale_by_power (&tmp, base, 2);
 
192
          break;
 
193
 
 
194
        case 'P': /* peta or pebi */
 
195
          overflow = bkm_scale_by_power (&tmp, base, 5);
 
196
          break;
 
197
 
 
198
        case 'T': /* tera or tebi */
 
199
        case 't': /* 't' is undocumented; for compatibility only */
 
200
          overflow = bkm_scale_by_power (&tmp, base, 4);
 
201
          break;
 
202
 
 
203
        case 'w':
 
204
          overflow = bkm_scale (&tmp, 2);
 
205
          break;
 
206
 
 
207
        case 'Y': /* yotta or 2**80 */
 
208
          overflow = bkm_scale_by_power (&tmp, base, 8);
 
209
          break;
 
210
 
 
211
        case 'Z': /* zetta or 2**70 */
 
212
          overflow = bkm_scale_by_power (&tmp, base, 7);
 
213
          break;
 
214
 
 
215
        default:
 
216
          *val = tmp;
 
217
          return err | LONGINT_INVALID_SUFFIX_CHAR;
 
218
        }
 
219
 
 
220
      err |= overflow;
 
221
      *p += suffixes;
 
222
      if (**p)
 
223
        err |= LONGINT_INVALID_SUFFIX_CHAR;
264
224
    }
265
225
 
266
226
  *val = tmp;
267
 
  return LONGINT_OK;
268
 
}
269
 
 
270
 
#ifdef TESTING_XSTRTO
271
 
 
272
 
# include <stdio.h>
273
 
# include "error.h"
274
 
 
275
 
char *program_name;
276
 
 
277
 
int
278
 
main (int argc, char** argv)
279
 
{
280
 
  strtol_error s_err;
281
 
  int i;
282
 
 
283
 
  program_name = argv[0];
284
 
  for (i=1; i<argc; i++)
285
 
    {
286
 
      char *p;
287
 
      __strtol_t val;
288
 
 
289
 
      s_err = __xstrtol (argv[i], &p, 0, &val, "bckmw");
290
 
      if (s_err == LONGINT_OK)
291
 
        {
292
 
          printf ("%s->%lu (%s)\n", argv[i], val, p);
293
 
        }
294
 
      else
295
 
        {
296
 
          STRTOL_FATAL_ERROR (argv[i], "arg", s_err);
297
 
        }
298
 
    }
299
 
  exit (0);
300
 
}
301
 
 
302
 
#endif /* TESTING_XSTRTO */
 
227
  return err;
 
228
}