os/ossrv/genericopenlibs/cstdlib/LSTDLIB/STRTOL.C
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/genericopenlibs/cstdlib/LSTDLIB/STRTOL.C	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,264 @@
     1.4 +/*
     1.5 +FUNCTION
     1.6 +   <<strtol>>---string to long
     1.7 +   <<strtoul>>---string to unsigned long
     1.8 +
     1.9 +INDEX
    1.10 +	strtol
    1.11 +INDEX
    1.12 +	_strtol_r
    1.13 +
    1.14 +ANSI_SYNOPSIS
    1.15 +	#include <stdlib.h>
    1.16 +        long strtol(const char *<[s]>, char **<[ptr]>,int <[base]>);
    1.17 +        unsigned long strtoul(const char *<[s]>, char **<[ptr]>,
    1.18 +                              int <[base]>);
    1.19 +
    1.20 +DESCRIPTION
    1.21 +The function <<strtol>> converts the string <<*<[s]>>> to
    1.22 +a <<long>>. First, it breaks down the string into three parts:
    1.23 +leading whitespace, which is ignored; a subject string consisting
    1.24 +of characters resembling an integer in the radix specified by <[base]>;
    1.25 +and a trailing portion consisting of zero or more unparseable characters,
    1.26 +and always including the terminating null character. Then, it attempts
    1.27 +to convert the subject string into a <<long>> and returns the
    1.28 +result.
    1.29 +
    1.30 +If the value of <[base]> is 0, the subject string is expected to look
    1.31 +like a normal C integer constant: an optional sign, a possible `<<0x>>'
    1.32 +indicating a hexadecimal base, and a number. If <[base]> is between
    1.33 +2 and 36, the expected form of the subject is a sequence of letters
    1.34 +and digits representing an integer in the radix specified by <[base]>,
    1.35 +with an optional plus or minus sign. The letters <<a>>--<<z>> (or,
    1.36 +equivalently, <<A>>--<<Z>>) are used to signify values from 10 to 35;
    1.37 +only letters whose ascribed values are less than <[base]> are
    1.38 +permitted. If <[base]> is 16, a leading <<0x>> is permitted.
    1.39 +
    1.40 +The subject sequence is the longest initial sequence of the input
    1.41 +string that has the expected form, starting with the first
    1.42 +non-whitespace character.  If the string is empty or consists entirely
    1.43 +of whitespace, or if the first non-whitespace character is not a
    1.44 +permissible letter or digit, the subject string is empty.
    1.45 +
    1.46 +If the subject string is acceptable, and the value of <[base]> is zero,
    1.47 +<<strtol>> attempts to determine the radix from the input string. A
    1.48 +string with a leading <<0x>> is treated as a hexadecimal value; a string with
    1.49 +a leading 0 and no <<x>> is treated as octal; all other strings are
    1.50 +treated as decimal. If <[base]> is between 2 and 36, it is used as the
    1.51 +conversion radix, as described above. If the subject string begins with
    1.52 +a minus sign, the value is negated. Finally, a pointer to the first
    1.53 +character past the converted subject string is stored in <[ptr]>, if
    1.54 +<[ptr]> is not <<NULL>>.
    1.55 +
    1.56 +If the subject string is empty (or not in acceptable form), no conversion
    1.57 +is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
    1.58 +not <<NULL>>).
    1.59 +
    1.60 +The alternate function <<_strtol_r>> is a reentrant version.  The
    1.61 +extra argument <[reent]> is a pointer to a reentrancy structure.
    1.62 +
    1.63 +The function <<strtoul>> is similar but does not permit an optional sign
    1.64 +and returns an <<unsigned long>>.
    1.65 +
    1.66 +RETURNS
    1.67 +<<strtol>> returns the converted value, if any. If no conversion was
    1.68 +made, 0 is returned.
    1.69 +
    1.70 +<<strtol>> returns <<LONG_MAX>> or <<LONG_MIN>> if the magnitude of
    1.71 +the converted value is too large, and sets <<errno>> to <<ERANGE>>.
    1.72 +
    1.73 +<<strtoul>> returns <<ULONG_MAX>> if the magnitude of the converted
    1.74 +value is too large, and sets <<errno>> to <<ERANGE>>.
    1.75 +
    1.76 +PORTABILITY
    1.77 +<<strtol>> and <<strtoul>> are both ANSI.
    1.78 +
    1.79 +No supporting OS subroutines are required.
    1.80 + */
    1.81 +
    1.82 +/*-
    1.83 + * Copyright (c) 1990 The Regents of the University of California.
    1.84 + * All rights reserved.
    1.85 + *
    1.86 + * Redistribution and use in source and binary forms, with or without
    1.87 + * modification, are permitted provided that the following conditions
    1.88 + * are met:
    1.89 + * 1. Redistributions of source code must retain the above copyright
    1.90 + *    notice, this list of conditions and the following disclaimer.
    1.91 + * 2. Redistributions in binary form must reproduce the above copyright
    1.92 + *    notice, this list of conditions and the following disclaimer in the
    1.93 + *    documentation and/or other materials provided with the distribution.
    1.94 + * 3. All advertising materials mentioning features or use of this software
    1.95 + *    must display the following acknowledgement:
    1.96 + *	This product includes software developed by the University of
    1.97 + *	California, Berkeley and its contributors.
    1.98 + * 4. Neither the name of the University nor the names of its contributors
    1.99 + *    may be used to endorse or promote products derived from this software
   1.100 + *    without specific prior written permission.
   1.101 + *
   1.102 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   1.103 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   1.104 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   1.105 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   1.106 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   1.107 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   1.108 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   1.109 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   1.110 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   1.111 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   1.112 + * SUCH DAMAGE.
   1.113 + */
   1.114 +
   1.115 +
   1.116 +#include <_ansi.h>
   1.117 +#include <limits.h>
   1.118 +#include <ctype.h>
   1.119 +#include <errno.h>
   1.120 +#include <stdlib.h>
   1.121 +#include <reent.h>
   1.122 +
   1.123 +/*
   1.124 + * Convert a string to a long integer.
   1.125 + *
   1.126 + * Ignores `locale' stuff.  Assumes that the upper and lower case
   1.127 + * alphabets and digits are each contiguous.
   1.128 + */
   1.129 +static unsigned long _do_strtoX (const char *nptr, char **endptr, int base, int issigned)
   1.130 +{
   1.131 +	register const char *s = nptr;
   1.132 +	register unsigned long acc;
   1.133 +	register int c;
   1.134 +	register unsigned long cutoff;
   1.135 +	register int neg = 0, any, cutlim;
   1.136 +	register const unsigned long long_min = (unsigned long)LONG_MIN;
   1.137 +
   1.138 +	/*
   1.139 +	 * Skip white space and pick up leading +/- sign if any.
   1.140 +	 * If base is 0, allow 0x for hex and 0 for octal, else
   1.141 +	 * assume decimal; if base is already 16, allow 0x.
   1.142 +	 */
   1.143 +	do {
   1.144 +		c = *s++;
   1.145 +	} while (isspace(c));
   1.146 +	
   1.147 +	if ((c == '-')||(c == '+')) {
   1.148 +	    issigned = 1;
   1.149 +	}
   1.150 +	
   1.151 +	if (issigned) {
   1.152 +		if (c == '-') {
   1.153 +			neg = 1;
   1.154 +			c = *s++;
   1.155 +		} else if (c == '+')
   1.156 +			c = *s++;
   1.157 +	}
   1.158 +	if ((base == 0 || base == 16) &&
   1.159 +	    c == '0' && (*s == 'x' || *s == 'X')) {
   1.160 +		c = s[1];
   1.161 +		s += 2;
   1.162 +		base = 16;
   1.163 +	}
   1.164 +	if (base == 0)
   1.165 +		base = c == '0' ? 8 : 10;
   1.166 +
   1.167 +	/*
   1.168 +	 * Compute the cutoff value between legal numbers and illegal
   1.169 +	 * numbers.  That is the largest legal value, divided by the
   1.170 +	 * base.  An input number that is greater than this value, if
   1.171 +	 * followed by a legal input character, is too big.  One that
   1.172 +	 * is equal to this value may be valid or not; the limit
   1.173 +	 * between valid and invalid numbers is then based on the last
   1.174 +	 * digit.  For instance, if the range for longs is
   1.175 +	 * [-2147483648..2147483647] and the input base is 10,
   1.176 +	 * cutoff will be set to 214748364 and cutlim to either
   1.177 +	 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
   1.178 +	 * a value > 214748364, or equal but the next digit is > 7 (or 8),
   1.179 +	 * the number is too big, and we will return a range error.
   1.180 +	 *
   1.181 +	 * Set any if any `digits' consumed; make it negative to indicate
   1.182 +	 * overflow.
   1.183 +	 */
   1.184 +	if (issigned)
   1.185 +		cutoff = neg ? long_min : LONG_MAX;
   1.186 +	else
   1.187 +		cutoff = ULONG_MAX;
   1.188 +	cutlim = cutoff % (unsigned long)base;
   1.189 +	cutoff = cutoff / (unsigned long)base;
   1.190 +	for (acc = 0, any = 0;; c = *s++) {
   1.191 +		if (isdigit(c))
   1.192 +			c -= '0';
   1.193 +		else if (isalpha(c))
   1.194 +			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
   1.195 +		else
   1.196 +			break;
   1.197 +		if (c >= base)
   1.198 +			break;
   1.199 +		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
   1.200 +			any = -1;
   1.201 +		else {
   1.202 +			any = 1;
   1.203 +			acc *= base;
   1.204 +			acc += c;
   1.205 +		}
   1.206 +	}
   1.207 +	if (any < 0) {
   1.208 +		if (issigned)
   1.209 +			acc = neg ? LONG_MIN : LONG_MAX;
   1.210 +		else
   1.211 +			acc = ULONG_MAX;
   1.212 +		errno = ERANGE;
   1.213 +	} else if (neg)
   1.214 +		acc = (unsigned long)(-(long)acc);
   1.215 +	if (endptr != 0)
   1.216 +		*endptr = (char *) (any ? s - 1 : nptr);
   1.217 +	return (acc);
   1.218 +}
   1.219 +
   1.220 +/**
   1.221 +Convert string to unsigned long integer.
   1.222 +Parses string interpreting its content as an integer value 
   1.223 +until a character that can not be interpreted is found,
   1.224 +and returns an unsigned long value.
   1.225 +@return The converted unsigned long value from the input string.
   1.226 +If an error occurs or no conversion can be made 0 is returned.
   1.227 +@param s String representing an integer number. 
   1.228 +@param ptr Address of a pointer.
   1.229 +This is filled by the function with the address where scan has ended. 
   1.230 +Serves to determine where there is the first non-numerical character in the string. 
   1.231 +@param base Numeral radix in which the number to be interpreted. 
   1.232 +Must be 0 or be between 2 and 36. If it is 0 the radix of the string is determined 
   1.233 +by the initial characters of the string:
   1.234 +*/
   1.235 +EXPORT_C unsigned long strtoul (const char *s, char **ptr, int base)
   1.236 +	{
   1.237 +	return _do_strtoX (s, ptr, base, 0);
   1.238 +	}
   1.239 +
   1.240 +/**
   1.241 +Convert string to long integer.
   1.242 +@return The converted long int value from the input string.
   1.243 +If an error occurs or no conversion can be made 0 is returned.
   1.244 +@param s String representing an integer number. 
   1.245 +@param ptr Address of a pointer. 
   1.246 +This is filled by the function with the address where scan has ended. 
   1.247 +@param base Numeral radix in which the number to be interpreted. 
   1.248 +Must be 0 or be between 2 and 36. If it is 0 the radix of the string 
   1.249 +is determined by the initial characters of the string
   1.250 +*/
   1.251 +EXPORT_C long strtol (const char *s, char **ptr, int base)
   1.252 +	{
   1.253 +	return (long)_do_strtoX (s, ptr, base, 1);
   1.254 +	}
   1.255 +
   1.256 +/**
   1.257 +Convert string to integer.
   1.258 +Parses string interpreting its content as a number and returns an int value.
   1.259 +@return   The converted integer value of the input string.
   1.260 +On overflow the result is undefined.
   1.261 +If an error occurs 0 is returned.
   1.262 +@param s String representing an integer number. 
   1.263 +*/
   1.264 +EXPORT_C int atoi (const char *s)
   1.265 +	{
   1.266 +	return (int) _do_strtoX (s, NULL, 10, 1);
   1.267 +	}