]>
Commit | Line | Data |
---|---|---|
28f540f4 RM |
1 | /* My bet is this was written by Chris Torek. |
2 | I reformatted and ansidecl-ized it, and tweaked it a little. */ | |
3 | ||
28f540f4 RM |
4 | #include <ctype.h> |
5 | #include <stdio.h> | |
6 | #include <errno.h> | |
7 | #include <stdlib.h> | |
a5a0310d | 8 | #include <string.h> |
762a2918 | 9 | #include <limits.h> |
28f540f4 RM |
10 | |
11 | struct ltest | |
12 | { | |
2c6fe0bd | 13 | const char *str; /* Convert this. */ |
28f540f4 RM |
14 | unsigned long int expect; /* To get this. */ |
15 | int base; /* Use this base. */ | |
16 | char left; /* With this left over. */ | |
17 | int err; /* And this in errno. */ | |
18 | }; | |
2c6fe0bd | 19 | static const struct ltest tests[] = |
28f540f4 | 20 | { |
1391f5d3 UD |
21 | /* First, signed numbers: */ |
22 | /* simple... */ | |
23 | {"123", 123, 0, 0, 0}, | |
24 | {"+123", 123, 0, 0, 0}, | |
25 | {" 123", 123, 0, 0, 0}, | |
26 | {" 123 ", 123, 0, ' ', 0}, | |
27 | {" -17", -17, 0, 0, 0}, | |
28f540f4 | 28 | |
1391f5d3 UD |
29 | /* implicit base... */ |
30 | {"0123", 0123, 0, 0, 0}, | |
31 | {"0123a", 0123, 0, 'a', 0}, | |
32 | {"01239", 0123, 0, '9', 0}, | |
33 | {"0x123", 0x123, 0, 0, 0}, | |
34 | {"-0x123", -0x123, 0, 0, 0}, | |
35 | {"0x0xc", 0, 0, 'x', 0}, | |
36 | {" +0x123fg", 0x123f, 0, 'g', 0}, | |
37 | ||
38 | /* explicit base... */ | |
39 | {"123", 0x123, 16, 0, 0}, | |
40 | {"0x123", 0x123, 16, 0, 0}, | |
41 | {"123", 0123, 8, 0, 0}, | |
42 | {"0123", 0123, 8, 0, 0}, | |
43 | {"0123", 123, 10, 0, 0}, | |
44 | {"0x123", 0, 10, 'x', 0}, | |
b20e47cb | 45 | |
1391f5d3 UD |
46 | /* case insensitivity... */ |
47 | {"abcd", 0xabcd, 16, 0, 0}, | |
48 | {"AbCd", 0xabcd, 16, 0, 0}, | |
49 | {"0xABCD", 0xabcd, 16, 0, 0}, | |
50 | {"0Xabcd", 0xabcd, 16, 0, 0}, | |
b20e47cb | 51 | |
1391f5d3 UD |
52 | /* odd bases... */ |
53 | {"0xyz", 33 * 35 + 34, 35, 'z', 0}, | |
54 | {"yz!", 34 * 36 + 35, 36, '!', 0}, | |
55 | {"-yz", -(34*36 + 35), 36, 0, 0}, | |
56 | {"GhI4", ((16*20 + 17)*20 + 18)*20 + 4, 20, 0, 0}, | |
b28ea43a | 57 | |
1391f5d3 UD |
58 | /* extremes... */ |
59 | #if LONG_MAX == 0x7fffffff | |
60 | {"2147483647", 2147483647, 0, 0, 0}, | |
61 | {"2147483648", 2147483647, 0, 0, ERANGE}, | |
62 | {"214748364888", 2147483647, 0, 0, ERANGE}, | |
63 | {"2147483650", 2147483647, 0, 0, ERANGE}, | |
64 | {"-2147483648", 0x80000000, 0, 0, 0}, | |
65 | {"-2147483649", 0x80000000, 0, 0, ERANGE}, | |
66 | {"0x1122334455z", 2147483647, 16, 'z', ERANGE}, | |
67 | #else | |
68 | {"9223372036854775807", 9223372036854775807, 0, 0, 0}, | |
69 | {"9223372036854775808", 9223372036854775807, 0, 0, ERANGE}, | |
70 | {"922337203685477580777", 9223372036854775807, 0, 0, ERANGE}, | |
71 | {"9223372036854775810", 9223372036854775807, 0, 0, ERANGE}, | |
72 | {"-2147483648", -2147483648, 0, 0, 0}, | |
73 | {"-9223372036854775808", -9223372036854775808, 0, 0, 0}, | |
74 | {"-9223372036854775809", -9223372036854775808, 0, 0, ERANGE}, | |
75 | {"0x112233445566778899z", 9223372036854775807, 16, 'z', ERANGE}, | |
b28ea43a | 76 | {"0xFFFFFFFFFFFF00FF" , 9223372036854775807, 0, 0, ERANGE}, |
1391f5d3 UD |
77 | #endif |
78 | {NULL, 0, 0, 0, 0}, | |
79 | ||
80 | /* Then unsigned. */ | |
81 | {" 0", 0, 0, 0, 0}, | |
82 | {"0xffffffffg", 0xffffffff, 0, 'g', 0}, | |
83 | #if LONG_MAX == 0x7fffffff | |
84 | {"-0xfedcba98", 0x01234568, 0, 0, 0}, | |
85 | {"0xf1f2f3f4f5", 0xffffffff, 0, 0, ERANGE}, | |
86 | {"-0x123456789", 0xffffffff, 0, 0, ERANGE}, | |
87 | #else | |
88 | {"0xffffffffffffffffg", 0xffffffffffffffff, 0, 'g', 0}, | |
89 | {"-0xfedcba987654321", 0xf0123456789abcdf, 0, 0, 0}, | |
90 | {"0xf1f2f3f4f5f6f7f8f9", 0xffffffffffffffff, 0, 0, ERANGE}, | |
91 | {"-0x123456789abcdef01", 0xffffffffffffffff, 0, 0, ERANGE}, | |
b20e47cb | 92 | #endif |
1391f5d3 | 93 | {NULL, 0, 0, 0, 0}, |
28f540f4 RM |
94 | }; |
95 | ||
bcaad6ee AJ |
96 | /* Prototypes for local functions. */ |
97 | static void expand (char *dst, int c); | |
28f540f4 RM |
98 | |
99 | int | |
bcaad6ee | 100 | main (void) |
28f540f4 | 101 | { |
2c6fe0bd | 102 | register const struct ltest *lt; |
28f540f4 RM |
103 | char *ep; |
104 | int status = 0; | |
f752bfe3 | 105 | int save_errno; |
28f540f4 RM |
106 | |
107 | for (lt = tests; lt->str != NULL; ++lt) | |
108 | { | |
109 | register long int l; | |
110 | ||
111 | errno = 0; | |
f752bfe3 UD |
112 | l = strtol (lt->str, &ep, lt->base); |
113 | save_errno = errno; | |
114 | printf ("strtol(\"%s\", , %d) test %u", | |
115 | lt->str, lt->base, (unsigned int) (lt - tests)); | |
116 | if (l == (long int) lt->expect && *ep == lt->left | |
117 | && save_errno == lt->err) | |
28f540f4 RM |
118 | puts("\tOK"); |
119 | else | |
120 | { | |
121 | puts("\tBAD"); | |
122 | if (l != (long int) lt->expect) | |
123 | printf(" returns %ld, expected %ld\n", | |
124 | l, (long int) lt->expect); | |
125 | if (lt->left != *ep) | |
126 | { | |
127 | char exp1[5], exp2[5]; | |
f752bfe3 UD |
128 | expand (exp1, *ep); |
129 | expand (exp2, lt->left); | |
130 | printf (" leaves '%s', expected '%s'\n", exp1, exp2); | |
28f540f4 | 131 | } |
5ae9d168 | 132 | if (save_errno != lt->err) |
f752bfe3 | 133 | printf (" errno %d (%s) instead of %d (%s)\n", |
5ae9d168 UD |
134 | save_errno, strerror (save_errno), |
135 | lt->err, strerror (lt->err)); | |
28f540f4 RM |
136 | status = 1; |
137 | } | |
138 | } | |
139 | ||
140 | for (++lt; lt->str != NULL; lt++) | |
141 | { | |
142 | register unsigned long int ul; | |
143 | ||
144 | errno = 0; | |
f752bfe3 | 145 | ul = strtoul (lt->str, &ep, lt->base); |
5ae9d168 | 146 | save_errno = errno; |
f752bfe3 UD |
147 | printf ("strtoul(\"%s\", , %d) test %u", |
148 | lt->str, lt->base, (unsigned int) (lt - tests)); | |
5ae9d168 | 149 | if (ul == lt->expect && *ep == lt->left && save_errno == lt->err) |
28f540f4 RM |
150 | puts("\tOK"); |
151 | else | |
152 | { | |
f752bfe3 | 153 | puts ("\tBAD"); |
28f540f4 | 154 | if (ul != lt->expect) |
f752bfe3 UD |
155 | printf (" returns %lu, expected %lu\n", |
156 | ul, lt->expect); | |
28f540f4 RM |
157 | if (lt->left != *ep) |
158 | { | |
159 | char exp1[5], exp2[5]; | |
f752bfe3 UD |
160 | expand (exp1, *ep); |
161 | expand (exp2, lt->left); | |
162 | printf (" leaves '%s', expected '%s'\n", exp1, exp2); | |
28f540f4 | 163 | } |
5ae9d168 | 164 | if (save_errno != lt->err) |
f752bfe3 | 165 | printf (" errno %d (%s) instead of %d (%s)\n", |
5ae9d168 UD |
166 | save_errno, strerror (save_errno), |
167 | lt->err, strerror (lt->err)); | |
28f540f4 RM |
168 | status = 1; |
169 | } | |
170 | } | |
171 | ||
f752bfe3 | 172 | exit (status ? EXIT_FAILURE : EXIT_SUCCESS); |
28f540f4 RM |
173 | } |
174 | ||
175 | static void | |
2c6fe0bd UD |
176 | expand (dst, c) |
177 | char *dst; | |
178 | int c; | |
28f540f4 | 179 | { |
f752bfe3 | 180 | if (isprint (c)) |
28f540f4 RM |
181 | { |
182 | dst[0] = c; | |
183 | dst[1] = '\0'; | |
184 | } | |
185 | else | |
f752bfe3 | 186 | (void) sprintf (dst, "%#.3o", (unsigned int) c); |
28f540f4 | 187 | } |