~ubuntu-branches/ubuntu/edgy/renameutils/edgy

« back to all changes in this revision

Viewing changes to src/compat/strtol.c

  • Committer: Bazaar Package Importer
  • Author(s): Francois Marier
  • Date: 2004-12-02 12:07:29 UTC
  • mfrom: (0.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20041202120729-a1ww9q8ltlzfru1f
Tags: 0.5.1-2
* Minor fixes to the copyright file
* Medium urgency to help bring the package up to date on mips

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Convert string representation of a number into an integer value.
2
 
   Copyright (C) 1991, 92, 94, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
3
 
   NOTE: The canonical source of this file is maintained with the GNU C
4
 
   Library.  Bugs can be reported to bug-glibc@gnu.org.
5
 
 
6
 
   This program is free software; you can redistribute it and/or modify it
7
 
   under the terms of the GNU General Public License as published by the
8
 
   Free Software Foundation; either version 2, or (at your option) any
9
 
   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, write to the Free Software Foundation,
18
 
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
 
 
20
 
#if HAVE_CONFIG_H
21
 
# include <config.h>
22
 
#endif
23
 
 
24
 
#ifdef _LIBC
25
 
# define USE_NUMBER_GROUPING
26
 
# define STDC_HEADERS
27
 
# define HAVE_LIMITS_H
28
 
#endif
29
 
 
30
 
#include <ctype.h>
31
 
#include <errno.h>
32
 
#ifndef errno
33
 
extern int errno;
34
 
#endif
35
 
#ifndef __set_errno
36
 
# define __set_errno(Val) errno = (Val)
37
 
#endif
38
 
 
39
 
#ifdef HAVE_LIMITS_H
40
 
# include <limits.h>
41
 
#endif
42
 
 
43
 
#ifdef STDC_HEADERS
44
 
# include <stddef.h>
45
 
# include <stdlib.h>
46
 
# include <string.h>
47
 
#else
48
 
# ifndef NULL
49
 
#  define NULL 0
50
 
# endif
51
 
#endif
52
 
 
53
 
#ifdef USE_NUMBER_GROUPING
54
 
# include "../locale/localeinfo.h"
55
 
#endif
56
 
 
57
 
/* Nonzero if we are defining `strtoul' or `strtoull', operating on
58
 
   unsigned integers.  */
59
 
#ifndef UNSIGNED
60
 
# define UNSIGNED 0
61
 
# define INT LONG int
62
 
#else
63
 
# define INT unsigned LONG int
64
 
#endif
65
 
 
66
 
/* Determine the name.  */
67
 
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
68
 
# if UNSIGNED
69
 
#  ifdef USE_WIDE_CHAR
70
 
#   ifdef QUAD
71
 
#    define strtol __wcstoull_l
72
 
#   else
73
 
#    define strtol __wcstoul_l
74
 
#   endif
75
 
#  else
76
 
#   ifdef QUAD
77
 
#    define strtol __strtoull_l
78
 
#   else
79
 
#    define strtol __strtoul_l
80
 
#   endif
81
 
#  endif
82
 
# else
83
 
#  ifdef USE_WIDE_CHAR
84
 
#   ifdef QUAD
85
 
#    define strtol __wcstoll_l
86
 
#   else
87
 
#    define strtol __wcstol_l
88
 
#   endif
89
 
#  else
90
 
#   ifdef QUAD
91
 
#    define strtol __strtoll_l
92
 
#   else
93
 
#    define strtol __strtol_l
94
 
#   endif
95
 
#  endif
96
 
# endif
97
 
#else
98
 
# if UNSIGNED
99
 
#  ifdef USE_WIDE_CHAR
100
 
#   ifdef QUAD
101
 
#    define strtol wcstoull
102
 
#   else
103
 
#    define strtol wcstoul
104
 
#   endif
105
 
#  else
106
 
#   ifdef QUAD
107
 
#    define strtol strtoull
108
 
#   else
109
 
#    define strtol strtoul
110
 
#   endif
111
 
#  endif
112
 
# else
113
 
#  ifdef USE_WIDE_CHAR
114
 
#   ifdef QUAD
115
 
#    define strtol wcstoll
116
 
#   else
117
 
#    define strtol wcstol
118
 
#   endif
119
 
#  else
120
 
#   ifdef QUAD
121
 
#    define strtol strtoll
122
 
#   endif
123
 
#  endif
124
 
# endif
125
 
#endif
126
 
 
127
 
/* If QUAD is defined, we are defining `strtoll' or `strtoull',
128
 
   operating on `long long int's.  */
129
 
#ifdef QUAD
130
 
# define LONG long long
131
 
# define STRTOL_LONG_MIN LONG_LONG_MIN
132
 
# define STRTOL_LONG_MAX LONG_LONG_MAX
133
 
# define STRTOL_ULONG_MAX ULONG_LONG_MAX
134
 
 
135
 
/* The extra casts work around common compiler bugs,
136
 
   e.g. Cray C 5.0.3.0 when t == time_t.  */
137
 
# ifndef TYPE_SIGNED
138
 
#  define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
139
 
# endif
140
 
# ifndef TYPE_MINIMUM
141
 
#  define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
142
 
                                ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
143
 
                                : (t) 0))
144
 
# endif
145
 
# ifndef TYPE_MAXIMUM
146
 
#  define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
147
 
# endif
148
 
 
149
 
# ifndef ULONG_LONG_MAX
150
 
#  define ULONG_LONG_MAX TYPE_MAXIMUM (unsigned long long)
151
 
# endif
152
 
# ifndef LONG_LONG_MAX
153
 
#  define LONG_LONG_MAX TYPE_MAXIMUM (long long int)
154
 
# endif
155
 
# ifndef LONG_LONG_MIN
156
 
#  define LONG_LONG_MIN TYPE_MINIMUM (long long int)
157
 
# endif
158
 
 
159
 
# if __GNUC__ == 2 && __GNUC_MINOR__ < 7
160
 
   /* Work around gcc bug with using this constant.  */
161
 
   static const unsigned long long int maxquad = ULONG_LONG_MAX;
162
 
#  undef STRTOL_ULONG_MAX
163
 
#  define STRTOL_ULONG_MAX maxquad
164
 
# endif
165
 
#else
166
 
# define LONG long
167
 
 
168
 
# ifndef ULONG_MAX
169
 
#  define ULONG_MAX ((unsigned long) ~(unsigned long) 0)
170
 
# endif
171
 
# ifndef LONG_MAX
172
 
#  define LONG_MAX ((long int) (ULONG_MAX >> 1))
173
 
# endif
174
 
# define STRTOL_LONG_MIN LONG_MIN
175
 
# define STRTOL_LONG_MAX LONG_MAX
176
 
# define STRTOL_ULONG_MAX ULONG_MAX
177
 
#endif
178
 
 
179
 
 
180
 
/* We use this code also for the extended locale handling where the
181
 
   function gets as an additional argument the locale which has to be
182
 
   used.  To access the values we have to redefine the _NL_CURRENT
183
 
   macro.  */
184
 
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
185
 
# undef _NL_CURRENT
186
 
# define _NL_CURRENT(category, item) \
187
 
  (current->values[_NL_ITEM_INDEX (item)].string)
188
 
# define LOCALE_PARAM , loc
189
 
# define LOCALE_PARAM_DECL __locale_t loc;
190
 
#else
191
 
# define LOCALE_PARAM
192
 
# define LOCALE_PARAM_DECL
193
 
#endif
194
 
 
195
 
#if defined _LIBC || defined HAVE_WCHAR_H
196
 
# include <wchar.h>
197
 
#endif
198
 
 
199
 
#ifdef USE_WIDE_CHAR
200
 
# include <wctype.h>
201
 
# define L_(Ch) L##Ch
202
 
# define UCHAR_TYPE wint_t
203
 
# define STRING_TYPE wchar_t
204
 
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
205
 
#  define ISSPACE(Ch) __iswspace_l ((Ch), loc)
206
 
#  define ISALPHA(Ch) __iswalpha_l ((Ch), loc)
207
 
#  define TOUPPER(Ch) __towupper_l ((Ch), loc)
208
 
# else
209
 
#  define ISSPACE(Ch) iswspace (Ch)
210
 
#  define ISALPHA(Ch) iswalpha (Ch)
211
 
#  define TOUPPER(Ch) towupper (Ch)
212
 
# endif
213
 
#else
214
 
# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
215
 
#  define IN_CTYPE_DOMAIN(c) 1
216
 
# else
217
 
#  define IN_CTYPE_DOMAIN(c) isascii(c)
218
 
# endif
219
 
# define L_(Ch) Ch
220
 
# define UCHAR_TYPE unsigned char
221
 
# define STRING_TYPE char
222
 
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
223
 
#  define ISSPACE(Ch) __isspace_l ((Ch), loc)
224
 
#  define ISALPHA(Ch) __isalpha_l ((Ch), loc)
225
 
#  define TOUPPER(Ch) __toupper_l ((Ch), loc)
226
 
# else
227
 
#  define ISSPACE(Ch) (IN_CTYPE_DOMAIN (Ch) && isspace (Ch))
228
 
#  define ISALPHA(Ch) (IN_CTYPE_DOMAIN (Ch) && isalpha (Ch))
229
 
#  define TOUPPER(Ch) (IN_CTYPE_DOMAIN (Ch) ? toupper (Ch) : (Ch))
230
 
# endif
231
 
#endif
232
 
 
233
 
/* For compilers which are ansi but don't define __STDC__, like SGI
234
 
   Irix-4.0.5 cc, also check whether PROTOTYPES is defined. */
235
 
#if defined (__STDC__) || defined (PROTOTYPES)
236
 
# define INTERNAL(X) INTERNAL1(X)
237
 
# define INTERNAL1(X) __##X##_internal
238
 
# define WEAKNAME(X) WEAKNAME1(X)
239
 
#else
240
 
# define INTERNAL(X) __/**/X/**/_internal
241
 
#endif
242
 
 
243
 
#ifdef USE_NUMBER_GROUPING
244
 
/* This file defines a function to check for correct grouping.  */
245
 
# include "grouping.h"
246
 
#endif
247
 
 
248
 
 
249
 
 
250
 
/* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
251
 
   If BASE is 0 the base is determined by the presence of a leading
252
 
   zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
253
 
   If BASE is < 2 or > 36, it is reset to 10.
254
 
   If ENDPTR is not NULL, a pointer to the character after the last
255
 
   one converted is stored in *ENDPTR.  */
256
 
 
257
 
INT
258
 
INTERNAL (strtol) (nptr, endptr, base, group LOCALE_PARAM)
259
 
     const STRING_TYPE *nptr;
260
 
     STRING_TYPE **endptr;
261
 
     int base;
262
 
     int group;
263
 
     LOCALE_PARAM_DECL
264
 
{
265
 
  int negative;
266
 
  register unsigned LONG int cutoff;
267
 
  register unsigned int cutlim;
268
 
  register unsigned LONG int i;
269
 
  register const STRING_TYPE *s;
270
 
  register UCHAR_TYPE c;
271
 
  const STRING_TYPE *save, *end;
272
 
  int overflow;
273
 
 
274
 
#ifdef USE_NUMBER_GROUPING
275
 
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
276
 
  struct locale_data *current = loc->__locales[LC_NUMERIC];
277
 
# endif
278
 
  /* The thousands character of the current locale.  */
279
 
  wchar_t thousands = L'\0';
280
 
  /* The numeric grouping specification of the current locale,
281
 
     in the format described in <locale.h>.  */
282
 
  const char *grouping;
283
 
 
284
 
  if (group)
285
 
    {
286
 
      grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
287
 
      if (*grouping <= 0 || *grouping == CHAR_MAX)
288
 
        grouping = NULL;
289
 
      else
290
 
        {
291
 
          /* Figure out the thousands separator character.  */
292
 
# if defined _LIBC || defined _HAVE_BTOWC
293
 
          thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP));
294
 
          if (thousands == WEOF)
295
 
            thousands = L'\0';
296
 
# endif
297
 
          if (thousands == L'\0')
298
 
            grouping = NULL;
299
 
        }
300
 
    }
301
 
  else
302
 
    grouping = NULL;
303
 
#endif
304
 
 
305
 
  if (base < 0 || base == 1 || base > 36)
306
 
    {
307
 
      __set_errno (EINVAL);
308
 
      return 0;
309
 
    }
310
 
 
311
 
  save = s = nptr;
312
 
 
313
 
  /* Skip white space.  */
314
 
  while (ISSPACE (*s))
315
 
    ++s;
316
 
  if (*s == L_('\0'))
317
 
    goto noconv;
318
 
 
319
 
  /* Check for a sign.  */
320
 
  if (*s == L_('-'))
321
 
    {
322
 
      negative = 1;
323
 
      ++s;
324
 
    }
325
 
  else if (*s == L_('+'))
326
 
    {
327
 
      negative = 0;
328
 
      ++s;
329
 
    }
330
 
  else
331
 
    negative = 0;
332
 
 
333
 
  /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
334
 
  if (*s == L_('0'))
335
 
    {
336
 
      if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
337
 
        {
338
 
          s += 2;
339
 
          base = 16;
340
 
        }
341
 
      else if (base == 0)
342
 
        base = 8;
343
 
    }
344
 
  else if (base == 0)
345
 
    base = 10;
346
 
 
347
 
  /* Save the pointer so we can check later if anything happened.  */
348
 
  save = s;
349
 
 
350
 
#ifdef USE_NUMBER_GROUPING
351
 
  if (group)
352
 
    {
353
 
      /* Find the end of the digit string and check its grouping.  */
354
 
      end = s;
355
 
      for (c = *end; c != L_('\0'); c = *++end)
356
 
        if ((wchar_t) c != thousands
357
 
            && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9'))
358
 
            && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base))
359
 
          break;
360
 
      if (*s == thousands)
361
 
        end = s;
362
 
      else
363
 
        end = correctly_grouped_prefix (s, end, thousands, grouping);
364
 
    }
365
 
  else
366
 
#endif
367
 
    end = NULL;
368
 
 
369
 
  cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;
370
 
  cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;
371
 
 
372
 
  overflow = 0;
373
 
  i = 0;
374
 
  for (c = *s; c != L_('\0'); c = *++s)
375
 
    {
376
 
      if (s == end)
377
 
        break;
378
 
      if (c >= L_('0') && c <= L_('9'))
379
 
        c -= L_('0');
380
 
      else if (ISALPHA (c))
381
 
        c = TOUPPER (c) - L_('A') + 10;
382
 
      else
383
 
        break;
384
 
      if ((int) c >= base)
385
 
        break;
386
 
      /* Check for overflow.  */
387
 
      if (i > cutoff || (i == cutoff && c > cutlim))
388
 
        overflow = 1;
389
 
      else
390
 
        {
391
 
          i *= (unsigned LONG int) base;
392
 
          i += c;
393
 
        }
394
 
    }
395
 
 
396
 
  /* Check if anything actually happened.  */
397
 
  if (s == save)
398
 
    goto noconv;
399
 
 
400
 
  /* Store in ENDPTR the address of one character
401
 
     past the last character we converted.  */
402
 
  if (endptr != NULL)
403
 
    *endptr = (STRING_TYPE *) s;
404
 
 
405
 
#if !UNSIGNED
406
 
  /* Check for a value that is within the range of
407
 
     `unsigned LONG int', but outside the range of `LONG int'.  */
408
 
  if (overflow == 0
409
 
      && i > (negative
410
 
              ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
411
 
              : (unsigned LONG int) STRTOL_LONG_MAX))
412
 
    overflow = 1;
413
 
#endif
414
 
 
415
 
  if (overflow)
416
 
    {
417
 
      __set_errno (ERANGE);
418
 
#if UNSIGNED
419
 
      return STRTOL_ULONG_MAX;
420
 
#else
421
 
      return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
422
 
#endif
423
 
    }
424
 
 
425
 
  /* Return the result of the appropriate sign.  */
426
 
  return negative ? -i : i;
427
 
 
428
 
noconv:
429
 
  /* We must handle a special case here: the base is 0 or 16 and the
430
 
     first two characters are '0' and 'x', but the rest are no
431
 
     hexadecimal digits.  This is no error case.  We return 0 and
432
 
     ENDPTR points to the `x`.  */
433
 
  if (endptr != NULL)
434
 
    {
435
 
      if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
436
 
          && save[-2] == L_('0'))
437
 
        *endptr = (STRING_TYPE *) &save[-1];
438
 
      else
439
 
        /*  There was no number to convert.  */
440
 
        *endptr = (STRING_TYPE *) nptr;
441
 
    }
442
 
 
443
 
  return 0L;
444
 
}
445
 
 
446
 
/* External user entry point.  */
447
 
 
448
 
#if _LIBC - 0 == 0
449
 
# undef PARAMS
450
 
# if defined (__STDC__) && __STDC__
451
 
#  define PARAMS(Args) Args
452
 
# else
453
 
#  define PARAMS(Args) ()
454
 
# endif
455
 
 
456
 
/* Prototype.  */
457
 
INT strtol PARAMS ((const STRING_TYPE *nptr, STRING_TYPE **endptr, int base));
458
 
#endif
459
 
 
460
 
 
461
 
INT
462
 
#ifdef weak_function
463
 
weak_function
464
 
#endif
465
 
strtol (nptr, endptr, base LOCALE_PARAM)
466
 
     const STRING_TYPE *nptr;
467
 
     STRING_TYPE **endptr;
468
 
     int base;
469
 
     LOCALE_PARAM_DECL
470
 
{
471
 
  return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM);
472
 
}