Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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