]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/language/c/libc/stdlib/v2_0/src/strtoll.cxx
TX51 pre-release
[karo-tx-redboot.git] / packages / language / c / libc / stdlib / v2_0 / src / strtoll.cxx
1 //===========================================================================
2 //
3 //      strtoll.cxx
4 //
5 //      String to long long int conversion function
6 //
7 //===========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 // -------------------------------------------
36 //####ECOSGPLCOPYRIGHTEND####
37 //===========================================================================
38 //#####DESCRIPTIONBEGIN####
39 //
40 // Author(s):    jlarmour
41 // Contributors: Fredrik Hederstierna, converted file from long to long long.
42 // Date:         2000-04-30, 2004-02-19
43 // Purpose:     
44 // Description: 
45 // Usage:       
46 //
47 //####DESCRIPTIONEND####
48 //
49 //===========================================================================
50 //
51 // This code is based on original code with the following copyright:
52 //
53 /*-
54  * Copyright (c) 1990 The Regents of the University of California.
55  * All rights reserved.
56  *
57  * Redistribution and use in source and binary forms, with or without
58  * modification, are permitted provided that the following conditions
59  * are met:
60  * 1. Redistributions of source code must retain the above copyright
61  *    notice, this list of conditions and the following disclaimer.
62  * 2. Redistributions in binary form must reproduce the above copyright
63  *    notice, this list of conditions and the following disclaimer in the
64  *    documentation and/or other materials provided with the distribution.
65  * 3. Neither the name of the University nor the names of its contributors
66  *    may be used to endorse or promote products derived from this software
67  *    without specific prior written permission.
68  *
69  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
70  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
71  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
72  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
73  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
74  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
75  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
76  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
77  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
78  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
79  * SUCH DAMAGE.
80  */
81
82
83 // CONFIGURATION
84
85 #include <pkgconf/libc_stdlib.h>   // Configuration header
86
87 // INCLUDES
88
89 #include <cyg/infra/cyg_type.h>    // Common type definitions and support
90 #include <cyg/infra/cyg_trac.h>    // Tracing support
91 #include <cyg/infra/cyg_ass.h>     // Assertion support
92 #include <limits.h>                // Definition of LONG_LONG_MIN and LONG_LONG_MAX
93 #include <ctype.h>                 // Definition of many ctype functions
94 #include <errno.h>                 // Error code definitions
95 #include <stdlib.h>                // Header for all stdlib functions
96                                    // (like this one)
97
98
99 // FUNCTIONS
100
101 //
102 // Convert a string to a long long integer.
103 //
104 // Ignores `locale' stuff.  Assumes that the upper and lower case
105 // alphabets and digits are each contiguous.
106 //
107
108 long long
109 strtoll( const char *nptr, char **endptr, int base )
110 {
111     const char *s = nptr;
112     unsigned long long acc;
113     int c;
114     unsigned long long cutoff;
115     int neg = 0, any, cutlim;
116
117     CYG_REPORT_FUNCNAMETYPE( "strtoll", "returning long long %lld" );
118     CYG_REPORT_FUNCARG3( "nptr=%08x, endptr=%08x, base=%d",
119                          nptr, endptr, base );
120     CYG_CHECK_DATA_PTR( nptr, "nptr is not a valid pointer!" );
121
122     if (endptr != NULL)
123         CYG_CHECK_DATA_PTR( endptr, "endptr is not a valid pointer!" );
124     
125     //
126     // Skip white space and pick up leading +/- sign if any.
127     // If base is 0, allow 0x for hex and 0 for octal, else
128     // assume decimal; if base is already 16, allow 0x.
129     //
130     
131     do {
132         c = *s++;
133     } while (isspace(c));
134     if (c == '-') {
135         neg = 1;
136         c = *s++;
137     } else if (c == '+')
138         c = *s++;
139     if ((base == 0 || base == 16) &&
140         c == '0' && (*s == 'x' || *s == 'X')) {
141         c = s[1];
142         s += 2;
143         base = 16;
144     }
145     if (base == 0)
146         base = c == '0' ? 8 : 10;
147     
148     //
149     // Compute the cutoff value between legal numbers and illegal
150     // numbers.  That is the largest legal value, divided by the
151     // base.  An input number that is greater than this value, if
152     // followed by a legal input character, is too big.  One that
153     // is equal to this value may be valid or not; the limit
154     // between valid and invalid numbers is then based on the last
155     // digit.  For instance, if the range for long longs is
156     // [-2147483648..2147483647] and the input base is 10,
157     // cutoff will be set to 214748364 and cutlim to either
158     // 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
159     // a value > 214748364, or equal but the next digit is > 7 (or 8),
160     // the number is too big, and we will return a range error.
161     //
162     // Set any if any `digits' consumed; make it negative to indicate
163     // overflow.
164     //
165     
166     cutoff = neg ? -(unsigned long long)LONG_LONG_MIN : LONG_LONG_MAX;
167     cutlim = cutoff % (unsigned long long)base;
168     cutoff /= (unsigned long long)base;
169     for (acc = 0, any = 0;; c = *s++) {
170         if (isdigit(c))
171             c -= '0';
172         else if (isalpha(c))
173             c -= isupper(c) ? 'A' - 10 : 'a' - 10;
174         else
175             break;
176         if (c >= base)
177             break;
178         if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
179             any = -1;
180         else {
181             any = 1;
182             acc *= base;
183             acc += c;
184         }
185     }
186     if (any < 0) {
187         acc = neg ? LONG_LONG_MIN : LONG_LONG_MAX;
188         errno = ERANGE;
189     } else if (neg)
190         acc = -acc;
191     if (endptr != 0)
192         *endptr = (char *) (any ? s - 1 : nptr);
193
194     CYG_REPORT_RETVAL ( acc );
195
196     return acc;
197 } // strtoll()
198
199 // EOF strtoll.cxx