os/ossrv/genericopenlibs/cstdlib/LSTDLIB/STRTOL.C
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 FUNCTION
     3    <<strtol>>---string to long
     4    <<strtoul>>---string to unsigned long
     5 
     6 INDEX
     7 	strtol
     8 INDEX
     9 	_strtol_r
    10 
    11 ANSI_SYNOPSIS
    12 	#include <stdlib.h>
    13         long strtol(const char *<[s]>, char **<[ptr]>,int <[base]>);
    14         unsigned long strtoul(const char *<[s]>, char **<[ptr]>,
    15                               int <[base]>);
    16 
    17 DESCRIPTION
    18 The function <<strtol>> converts the string <<*<[s]>>> to
    19 a <<long>>. First, it breaks down the string into three parts:
    20 leading whitespace, which is ignored; a subject string consisting
    21 of characters resembling an integer in the radix specified by <[base]>;
    22 and a trailing portion consisting of zero or more unparseable characters,
    23 and always including the terminating null character. Then, it attempts
    24 to convert the subject string into a <<long>> and returns the
    25 result.
    26 
    27 If the value of <[base]> is 0, the subject string is expected to look
    28 like a normal C integer constant: an optional sign, a possible `<<0x>>'
    29 indicating a hexadecimal base, and a number. If <[base]> is between
    30 2 and 36, the expected form of the subject is a sequence of letters
    31 and digits representing an integer in the radix specified by <[base]>,
    32 with an optional plus or minus sign. The letters <<a>>--<<z>> (or,
    33 equivalently, <<A>>--<<Z>>) are used to signify values from 10 to 35;
    34 only letters whose ascribed values are less than <[base]> are
    35 permitted. If <[base]> is 16, a leading <<0x>> is permitted.
    36 
    37 The subject sequence is the longest initial sequence of the input
    38 string that has the expected form, starting with the first
    39 non-whitespace character.  If the string is empty or consists entirely
    40 of whitespace, or if the first non-whitespace character is not a
    41 permissible letter or digit, the subject string is empty.
    42 
    43 If the subject string is acceptable, and the value of <[base]> is zero,
    44 <<strtol>> attempts to determine the radix from the input string. A
    45 string with a leading <<0x>> is treated as a hexadecimal value; a string with
    46 a leading 0 and no <<x>> is treated as octal; all other strings are
    47 treated as decimal. If <[base]> is between 2 and 36, it is used as the
    48 conversion radix, as described above. If the subject string begins with
    49 a minus sign, the value is negated. Finally, a pointer to the first
    50 character past the converted subject string is stored in <[ptr]>, if
    51 <[ptr]> is not <<NULL>>.
    52 
    53 If the subject string is empty (or not in acceptable form), no conversion
    54 is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
    55 not <<NULL>>).
    56 
    57 The alternate function <<_strtol_r>> is a reentrant version.  The
    58 extra argument <[reent]> is a pointer to a reentrancy structure.
    59 
    60 The function <<strtoul>> is similar but does not permit an optional sign
    61 and returns an <<unsigned long>>.
    62 
    63 RETURNS
    64 <<strtol>> returns the converted value, if any. If no conversion was
    65 made, 0 is returned.
    66 
    67 <<strtol>> returns <<LONG_MAX>> or <<LONG_MIN>> if the magnitude of
    68 the converted value is too large, and sets <<errno>> to <<ERANGE>>.
    69 
    70 <<strtoul>> returns <<ULONG_MAX>> if the magnitude of the converted
    71 value is too large, and sets <<errno>> to <<ERANGE>>.
    72 
    73 PORTABILITY
    74 <<strtol>> and <<strtoul>> are both ANSI.
    75 
    76 No supporting OS subroutines are required.
    77  */
    78 
    79 /*-
    80  * Copyright (c) 1990 The Regents of the University of California.
    81  * All rights reserved.
    82  *
    83  * Redistribution and use in source and binary forms, with or without
    84  * modification, are permitted provided that the following conditions
    85  * are met:
    86  * 1. Redistributions of source code must retain the above copyright
    87  *    notice, this list of conditions and the following disclaimer.
    88  * 2. Redistributions in binary form must reproduce the above copyright
    89  *    notice, this list of conditions and the following disclaimer in the
    90  *    documentation and/or other materials provided with the distribution.
    91  * 3. All advertising materials mentioning features or use of this software
    92  *    must display the following acknowledgement:
    93  *	This product includes software developed by the University of
    94  *	California, Berkeley and its contributors.
    95  * 4. Neither the name of the University nor the names of its contributors
    96  *    may be used to endorse or promote products derived from this software
    97  *    without specific prior written permission.
    98  *
    99  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   100  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   101  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   102  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   103  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   104  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   105  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   106  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   107  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   108  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   109  * SUCH DAMAGE.
   110  */
   111 
   112 
   113 #include <_ansi.h>
   114 #include <limits.h>
   115 #include <ctype.h>
   116 #include <errno.h>
   117 #include <stdlib.h>
   118 #include <reent.h>
   119 
   120 /*
   121  * Convert a string to a long integer.
   122  *
   123  * Ignores `locale' stuff.  Assumes that the upper and lower case
   124  * alphabets and digits are each contiguous.
   125  */
   126 static unsigned long _do_strtoX (const char *nptr, char **endptr, int base, int issigned)
   127 {
   128 	register const char *s = nptr;
   129 	register unsigned long acc;
   130 	register int c;
   131 	register unsigned long cutoff;
   132 	register int neg = 0, any, cutlim;
   133 	register const unsigned long long_min = (unsigned long)LONG_MIN;
   134 
   135 	/*
   136 	 * Skip white space and pick up leading +/- sign if any.
   137 	 * If base is 0, allow 0x for hex and 0 for octal, else
   138 	 * assume decimal; if base is already 16, allow 0x.
   139 	 */
   140 	do {
   141 		c = *s++;
   142 	} while (isspace(c));
   143 	
   144 	if ((c == '-')||(c == '+')) {
   145 	    issigned = 1;
   146 	}
   147 	
   148 	if (issigned) {
   149 		if (c == '-') {
   150 			neg = 1;
   151 			c = *s++;
   152 		} else if (c == '+')
   153 			c = *s++;
   154 	}
   155 	if ((base == 0 || base == 16) &&
   156 	    c == '0' && (*s == 'x' || *s == 'X')) {
   157 		c = s[1];
   158 		s += 2;
   159 		base = 16;
   160 	}
   161 	if (base == 0)
   162 		base = c == '0' ? 8 : 10;
   163 
   164 	/*
   165 	 * Compute the cutoff value between legal numbers and illegal
   166 	 * numbers.  That is the largest legal value, divided by the
   167 	 * base.  An input number that is greater than this value, if
   168 	 * followed by a legal input character, is too big.  One that
   169 	 * is equal to this value may be valid or not; the limit
   170 	 * between valid and invalid numbers is then based on the last
   171 	 * digit.  For instance, if the range for longs is
   172 	 * [-2147483648..2147483647] and the input base is 10,
   173 	 * cutoff will be set to 214748364 and cutlim to either
   174 	 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
   175 	 * a value > 214748364, or equal but the next digit is > 7 (or 8),
   176 	 * the number is too big, and we will return a range error.
   177 	 *
   178 	 * Set any if any `digits' consumed; make it negative to indicate
   179 	 * overflow.
   180 	 */
   181 	if (issigned)
   182 		cutoff = neg ? long_min : LONG_MAX;
   183 	else
   184 		cutoff = ULONG_MAX;
   185 	cutlim = cutoff % (unsigned long)base;
   186 	cutoff = cutoff / (unsigned long)base;
   187 	for (acc = 0, any = 0;; c = *s++) {
   188 		if (isdigit(c))
   189 			c -= '0';
   190 		else if (isalpha(c))
   191 			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
   192 		else
   193 			break;
   194 		if (c >= base)
   195 			break;
   196 		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
   197 			any = -1;
   198 		else {
   199 			any = 1;
   200 			acc *= base;
   201 			acc += c;
   202 		}
   203 	}
   204 	if (any < 0) {
   205 		if (issigned)
   206 			acc = neg ? LONG_MIN : LONG_MAX;
   207 		else
   208 			acc = ULONG_MAX;
   209 		errno = ERANGE;
   210 	} else if (neg)
   211 		acc = (unsigned long)(-(long)acc);
   212 	if (endptr != 0)
   213 		*endptr = (char *) (any ? s - 1 : nptr);
   214 	return (acc);
   215 }
   216 
   217 /**
   218 Convert string to unsigned long integer.
   219 Parses string interpreting its content as an integer value 
   220 until a character that can not be interpreted is found,
   221 and returns an unsigned long value.
   222 @return The converted unsigned long value from the input string.
   223 If an error occurs or no conversion can be made 0 is returned.
   224 @param s String representing an integer number. 
   225 @param ptr Address of a pointer.
   226 This is filled by the function with the address where scan has ended. 
   227 Serves to determine where there is the first non-numerical character in the string. 
   228 @param base Numeral radix in which the number to be interpreted. 
   229 Must be 0 or be between 2 and 36. If it is 0 the radix of the string is determined 
   230 by the initial characters of the string:
   231 */
   232 EXPORT_C unsigned long strtoul (const char *s, char **ptr, int base)
   233 	{
   234 	return _do_strtoX (s, ptr, base, 0);
   235 	}
   236 
   237 /**
   238 Convert string to long integer.
   239 @return The converted long int value from the input string.
   240 If an error occurs or no conversion can be made 0 is returned.
   241 @param s String representing an integer number. 
   242 @param ptr Address of a pointer. 
   243 This is filled by the function with the address where scan has ended. 
   244 @param base Numeral radix in which the number to be interpreted. 
   245 Must be 0 or be between 2 and 36. If it is 0 the radix of the string 
   246 is determined by the initial characters of the string
   247 */
   248 EXPORT_C long strtol (const char *s, char **ptr, int base)
   249 	{
   250 	return (long)_do_strtoX (s, ptr, base, 1);
   251 	}
   252 
   253 /**
   254 Convert string to integer.
   255 Parses string interpreting its content as a number and returns an int value.
   256 @return   The converted integer value of the input string.
   257 On overflow the result is undefined.
   258 If an error occurs 0 is returned.
   259 @param s String representing an integer number. 
   260 */
   261 EXPORT_C int atoi (const char *s)
   262 	{
   263 	return (int) _do_strtoX (s, NULL, 10, 1);
   264 	}