]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/LibC/StdLib/strtoimax.c
Change the PciBusDxe driver to install the PCI enumeration complete GUID in the PCI...
[mirror_edk2.git] / StdLib / LibC / StdLib / strtoimax.c
CommitLineData
2aa62f2b 1/* $NetBSD: strtoimax.c,v 1.4 2005/11/29 03:12:00 christos Exp $ */\r
2\r
3/*-\r
4 * Copyright (c) 1992, 1993\r
5 * The Regents of the University of California. All rights reserved.\r
6 *\r
7 * Redistribution and use in source and binary forms, with or without\r
8 * modification, are permitted provided that the following conditions\r
9 * are met:\r
10 * 1. Redistributions of source code must retain the above copyright\r
11 * notice, this list of conditions and the following disclaimer.\r
12 * 2. Redistributions in binary form must reproduce the above copyright\r
13 * notice, this list of conditions and the following disclaimer in the\r
14 * documentation and/or other materials provided with the distribution.\r
15 * 3. Neither the name of the University nor the names of its contributors\r
16 * may be used to endorse or promote products derived from this software\r
17 * without specific prior written permission.\r
18 *\r
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\r
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\r
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
29 * SUCH DAMAGE.\r
30 */\r
31#include <LibConfig.h>\r
32#include <sys/EfiCdefs.h>\r
33#if defined(LIBC_SCCS) && !defined(lint)\r
34#if 0\r
35static char sccsid[] = "from: @(#)strtoq.c 8.1 (Berkeley) 6/4/93";\r
36#else\r
37__RCSID("$NetBSD: strtoimax.c,v 1.4 2005/11/29 03:12:00 christos Exp $");\r
38#endif\r
39#endif /* LIBC_SCCS and not lint */\r
40\r
41#include "namespace.h"\r
42\r
43#include <assert.h>\r
44#include <ctype.h>\r
45#include <errno.h>\r
46#include <inttypes.h>\r
47#include <stddef.h>\r
48\r
49#ifdef __weak_alias\r
50__weak_alias(strtoimax, _strtoimax)\r
51#endif\r
52\r
53/*\r
54 * Convert a string to an intmax_t.\r
55 *\r
56 * Ignores `locale' stuff. Assumes that the upper and lower case\r
57 * alphabets and digits are each contiguous.\r
58 */\r
59intmax_t\r
60_strtoimax(const char *nptr, char **endptr, int base)\r
61{\r
62 const char *s;\r
63 intmax_t acc, cutoff;\r
64 int c;\r
65 int neg, any, cutlim;\r
66\r
67 _DIAGASSERT(nptr != NULL);\r
68 /* endptr may be NULL */\r
69\r
70#ifdef __GNUC__\r
71 /* This outrageous construct just to shut up a GCC warning. */\r
72 (void) &acc; (void) &cutoff;\r
73#endif\r
74\r
75 /*\r
76 * Skip white space and pick up leading +/- sign if any.\r
77 * If base is 0, allow 0x for hex and 0 for octal, else\r
78 * assume decimal; if base is already 16, allow 0x.\r
79 */\r
80 s = nptr;\r
81 do {\r
82 c = (unsigned char) *s++;\r
83 } while (isspace(c));\r
84 if (c == '-') {\r
85 neg = 1;\r
86 c = *s++;\r
87 } else {\r
88 neg = 0;\r
89 if (c == '+')\r
90 c = *s++;\r
91 }\r
92 if ((base == 0 || base == 16) &&\r
93 c == '0' && (*s == 'x' || *s == 'X')) {\r
94 c = s[1];\r
95 s += 2;\r
96 base = 16;\r
97 }\r
98 if (base == 0)\r
99 base = c == '0' ? 8 : 10;\r
100\r
101 /*\r
102 * Compute the cutoff value between legal numbers and illegal\r
103 * numbers. That is the largest legal value, divided by the\r
104 * base. An input number that is greater than this value, if\r
105 * followed by a legal input character, is too big. One that\r
106 * is equal to this value may be valid or not; the limit\r
107 * between valid and invalid numbers is then based on the last\r
108 * digit. For instance, if the range for intmax_t is\r
109 * [-9223372036854775808..9223372036854775807] and the input base\r
110 * is 10, cutoff will be set to 922337203685477580 and cutlim to\r
111 * either 7 (neg==0) or 8 (neg==1), meaning that if we have\r
112 * accumulated a value > 922337203685477580, or equal but the\r
113 * next digit is > 7 (or 8), the number is too big, and we will\r
114 * return a range error.\r
115 *\r
116 * Set any if any `digits' consumed; make it negative to indicate\r
117 * overflow.\r
118 */\r
119 cutoff = neg ? INTMAX_MIN : INTMAX_MAX;\r
120 cutlim = (int)(cutoff % base);\r
121 cutoff /= base;\r
122 if (neg) {\r
123 if (cutlim > 0) {\r
124 cutlim -= base;\r
125 cutoff += 1;\r
126 }\r
127 cutlim = -cutlim;\r
128 }\r
129 for (acc = 0, any = 0;; c = (unsigned char) *s++) {\r
130 if (isdigit(c))\r
131 c -= '0';\r
132 else if (isalpha(c))\r
133 c -= isupper(c) ? 'A' - 10 : 'a' - 10;\r
134 else\r
135 break;\r
136 if (c >= base)\r
137 break;\r
138 if (any < 0)\r
139 continue;\r
140 if (neg) {\r
141 if (acc < cutoff || (acc == cutoff && c > cutlim)) {\r
142 any = -1;\r
143 acc = INTMAX_MIN;\r
144 errno = ERANGE;\r
145 } else {\r
146 any = 1;\r
147 acc *= base;\r
148 acc -= c;\r
149 }\r
150 } else {\r
151 if (acc > cutoff || (acc == cutoff && c > cutlim)) {\r
152 any = -1;\r
153 acc = INTMAX_MAX;\r
154 errno = ERANGE;\r
155 } else {\r
156 any = 1;\r
157 acc *= base;\r
158 acc += c;\r
159 }\r
160 }\r
161 }\r
162 if (endptr != 0)\r
163 *endptr = (char *)(any ? s - 1 : nptr);\r
164 //*endptr = __UNCONST(any ? s - 1 : nptr);\r
165 return (acc);\r
166}\r