(file) Return to strtol.c CVS log (file) (dir) Up to [RizwankCVS] / testProject / compat

  1 rizwank 1.1 /* strtol - Convert string representation of a number into an integer value.
  2                Copyright (C) 1991, 92, 94, 95, 96, 97 Free Software Foundation, Inc.
  3                This file is part of the GNU C Library.
  4             
  5                The GNU C Library is free software; you can redistribute it and/or
  6                modify it under the terms of the GNU Library General Public License as
  7                published by the Free Software Foundation; either version 2 of the
  8                License, or (at your option) any later version.
  9             
 10                The GNU C Library 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 GNU
 13                Library General Public License for more details.
 14             
 15                You should have received a copy of the GNU Library General Public
 16                License along with the GNU C Library; see the file COPYING.LIB.  If not,
 17                write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 18                Boston, MA 02111-1307, USA.  */
 19             
 20             #if HAVE_CONFIG_H
 21             # include <config.h>
 22 rizwank 1.1 #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 rizwank 1.1 #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 `strtouq', 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 rizwank 1.1 #endif
 65             
 66             /* Determine the name.  */
 67             #if UNSIGNED
 68             # ifdef USE_WIDE_CHAR
 69             #  ifdef QUAD
 70             #   define strtol wcstouq
 71             #  else
 72             #   define strtol wcstoul
 73             #  endif
 74             # else
 75             #  ifdef QUAD
 76             #   define strtol strtouq
 77             #  else
 78             #   define strtol strtoul
 79             #  endif
 80             # endif
 81             #else
 82             # ifdef USE_WIDE_CHAR
 83             #  ifdef QUAD
 84             #   define strtol wcstoq
 85 rizwank 1.1 #  else
 86             #   define strtol wcstol
 87             #  endif
 88             # else
 89             #  ifdef QUAD
 90             #   define strtol strtoq
 91             #  endif
 92             # endif
 93             #endif
 94             
 95             /* If QUAD is defined, we are defining `strtoq' or `strtouq',
 96                operating on `long long int's.  */
 97             #ifdef QUAD
 98             # define LONG long long
 99             # undef LONG_MIN
100             # define LONG_MIN LONG_LONG_MIN
101             # undef LONG_MAX
102             # define LONG_MAX LONG_LONG_MAX
103             # undef ULONG_MAX
104             # define ULONG_MAX ULONG_LONG_MAX
105             # if __GNUC__ == 2 && __GNUC_MINOR__ < 7
106 rizwank 1.1    /* Work around gcc bug with using this constant.  */
107                static const unsigned long long int maxquad = ULONG_LONG_MAX;
108             #  undef ULONG_MAX
109             #  define ULONG_MAX maxquad
110             # endif
111             #else
112             # define LONG long
113             
114             #ifndef ULONG_MAX
115             # define ULONG_MAX ((unsigned long) ~(unsigned long) 0)
116             #endif
117             #ifndef LONG_MAX
118             # define LONG_MAX ((long int) (ULONG_MAX >> 1))
119             #endif
120             #endif
121             
122             #ifdef USE_WIDE_CHAR
123             # include <wchar.h>
124             # include <wctype.h>
125             # define L_(Ch) L##Ch
126             # define UCHAR_TYPE wint_t
127 rizwank 1.1 # define STRING_TYPE wchar_t
128             # define ISSPACE(Ch) iswspace (Ch)
129             # define ISALPHA(Ch) iswalpha (Ch)
130             # define TOUPPER(Ch) towupper (Ch)
131             #else
132             # define L_(Ch) Ch
133             # define UCHAR_TYPE unsigned char
134             # define STRING_TYPE char
135             # define ISSPACE(Ch) isspace (Ch)
136             # define ISALPHA(Ch) isalpha (Ch)
137             # define TOUPPER(Ch) toupper (Ch)
138             #endif
139             
140             #ifdef __STDC__
141             # define INTERNAL(X) INTERNAL1(X)
142             # define INTERNAL1(X) __##X##_internal
143             # define WEAKNAME(X) WEAKNAME1(X)
144             #else
145             # define INTERNAL(X) __/**/X/**/_internal
146             #endif
147             
148 rizwank 1.1 #ifdef USE_NUMBER_GROUPING
149             /* This file defines a function to check for correct grouping.  */
150             # include "grouping.h"
151             #endif
152             
153             
154             /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
155                If BASE is 0 the base is determined by the presence of a leading
156                zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
157                If BASE is < 2 or > 36, it is reset to 10.
158                If ENDPTR is not NULL, a pointer to the character after the last
159                one converted is stored in *ENDPTR.  */
160             
161             INT
162             INTERNAL (strtol) (nptr, endptr, base, group)
163                  const STRING_TYPE *nptr;
164                  STRING_TYPE **endptr;
165                  int base;
166                  int group;
167             {
168               int negative;
169 rizwank 1.1   register unsigned LONG int cutoff;
170               register unsigned int cutlim;
171               register unsigned LONG int i;
172               register const STRING_TYPE *s;
173               register UCHAR_TYPE c;
174               const STRING_TYPE *save, *end;
175               int overflow;
176             
177             #ifdef USE_NUMBER_GROUPING
178               /* The thousands character of the current locale.  */
179               wchar_t thousands;
180               /* The numeric grouping specification of the current locale,
181                  in the format described in <locale.h>.  */
182               const char *grouping;
183             
184               if (group)
185                 {
186                   grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
187                   if (*grouping <= 0 || *grouping == CHAR_MAX)
188             	grouping = NULL;
189                   else
190 rizwank 1.1 	{
191             	  /* Figure out the thousands separator character.  */
192             	  if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
193             		      strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
194             	    thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
195             	  if (thousands == L'\0')
196             	    grouping = NULL;
197             	}
198                 }
199               else
200                 grouping = NULL;
201             #endif
202             
203               if (base < 0 || base == 1 || base > 36)
204                 {
205                   __set_errno (EINVAL);
206                   return 0;
207                 }
208             
209               save = s = nptr;
210             
211 rizwank 1.1   /* Skip white space.  */
212               while (ISSPACE (*s))
213                 ++s;
214               if (*s == L_('\0'))
215                 goto noconv;
216             
217               /* Check for a sign.  */
218               if (*s == L_('-'))
219                 {
220                   negative = 1;
221                   ++s;
222                 }
223               else if (*s == L_('+'))
224                 {
225                   negative = 0;
226                   ++s;
227                 }
228               else
229                 negative = 0;
230             
231               if (base == 16 && s[0] == L_('0') && TOUPPER (s[1]) == L_('X'))
232 rizwank 1.1     s += 2;
233             
234               /* If BASE is zero, figure it out ourselves.  */
235               if (base == 0)
236                 if (*s == L_('0'))
237                   {
238             	if (TOUPPER (s[1]) == L_('X'))
239             	  {
240             	    s += 2;
241             	    base = 16;
242             	  }
243             	else
244             	  base = 8;
245                   }
246                 else
247                   base = 10;
248             
249               /* Save the pointer so we can check later if anything happened.  */
250               save = s;
251             
252             #ifdef USE_NUMBER_GROUPING
253 rizwank 1.1   if (group)
254                 {
255                   /* Find the end of the digit string and check its grouping.  */
256                   end = s;
257                   for (c = *end; c != L_('\0'); c = *++end)
258             	if ((wchar_t) c != thousands
259             	    && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9'))
260             	    && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base))
261             	  break;
262                   if (*s == thousands)
263             	end = s;
264                   else
265             	end = correctly_grouped_prefix (s, end, thousands, grouping);
266                 }
267               else
268             #endif
269                 end = NULL;
270             
271               cutoff = ULONG_MAX / (unsigned LONG int) base;
272               cutlim = ULONG_MAX % (unsigned LONG int) base;
273             
274 rizwank 1.1   overflow = 0;
275               i = 0;
276               for (c = *s; c != L_('\0'); c = *++s)
277                 {
278                   if (s == end)
279             	break;
280                   if (c >= L_('0') && c <= L_('9'))
281             	c -= L_('0');
282                   else if (ISALPHA (c))
283             	c = TOUPPER (c) - L_('A') + 10;
284                   else
285             	break;
286                   if ((int) c >= base)
287             	break;
288                   /* Check for overflow.  */
289                   if (i > cutoff || (i == cutoff && c > cutlim))
290             	overflow = 1;
291                   else
292             	{
293             	  i *= (unsigned LONG int) base;
294             	  i += c;
295 rizwank 1.1 	}
296                 }
297             
298               /* Check if anything actually happened.  */
299               if (s == save)
300                 goto noconv;
301             
302               /* Store in ENDPTR the address of one character
303                  past the last character we converted.  */
304               if (endptr != NULL)
305                 *endptr = (STRING_TYPE *) s;
306             
307             #if !UNSIGNED
308               /* Check for a value that is within the range of
309                  `unsigned LONG int', but outside the range of `LONG int'.  */
310               if (overflow == 0
311                   && i > (negative
312             	      ? -((unsigned LONG int) (LONG_MIN + 1)) + 1
313             	      : (unsigned LONG int) LONG_MAX))
314                 overflow = 1;
315             #endif
316 rizwank 1.1 
317               if (overflow)
318                 {
319                   __set_errno (ERANGE);
320             #if UNSIGNED
321                   return ULONG_MAX;
322             #else
323                   return negative ? LONG_MIN : LONG_MAX;
324             #endif
325                 }
326             
327               /* Return the result of the appropriate sign.  */
328               return (negative ? -i : i);
329             
330             noconv:
331               /* We must handle a special case here: the base is 0 or 16 and the
332                  first two characters are '0' and 'x', but the rest are no
333                  hexadecimal digits.  This is no error case.  We return 0 and
334                  ENDPTR points to the `x`.  */
335               if (endptr != NULL)
336                 if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
337 rizwank 1.1 	&& save[-2] == L_('0'))
338                   *endptr = (STRING_TYPE *) &save[-1];
339                 else
340                   /*  There was no number to convert.  */
341                   *endptr = (STRING_TYPE *) nptr;
342             
343               return 0L;
344             }
345             
346             /* External user entry point.  */
347             
348             #if _LIBC - 0 == 0
349             # undef PARAMS
350             # if defined (__STDC__) && __STDC__
351             #  define PARAMS(Args) Args
352             # else
353             #  define PARAMS(Args) ()
354             # endif
355             
356             /* Prototype.  */
357             INT strtol PARAMS ((const STRING_TYPE *nptr, STRING_TYPE **endptr, int base));
358 rizwank 1.1 #endif
359             
360             
361             INT
362             #ifdef weak_function
363             weak_function
364             #endif
365             strtol (nptr, endptr, base)
366                  const STRING_TYPE *nptr;
367                  STRING_TYPE **endptr;
368                  int base;
369             {
370               return INTERNAL (strtol) (nptr, endptr, base, 0);
371             }

Rizwan Kassim
Powered by
ViewCVS 0.9.2