diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-05-28 23:08:43 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-05-28 23:08:43 +0300 |
commit | 120727f7c5b36bddaa3ef232dd9b105148ac7433 (patch) | |
tree | 737ccf80008c823f37b760f6a26bbb96e1ff0528 /tests | |
parent | 4011b4ce9a4c4fa505843381d43a1157cf0c782e (diff) | |
download | gdbm-120727f7c5b36bddaa3ef232dd9b105148ac7433.tar.gz gdbm-120727f7c5b36bddaa3ef232dd9b105148ac7433.tar.bz2 |
Improve num2word
* tests/num2word.c: New options: -revert and -random
Diffstat (limited to 'tests')
-rw-r--r-- | tests/num2word.c | 171 |
1 files changed, 151 insertions, 20 deletions
diff --git a/tests/num2word.c b/tests/num2word.c index c9d5bc4..1ac54a4 100644 --- a/tests/num2word.c +++ b/tests/num2word.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <string.h> | 20 | #include <string.h> |
21 | #include <unistd.h> | 21 | #include <unistd.h> |
22 | #include <errno.h> | 22 | #include <errno.h> |
23 | #include <time.h> | ||
24 | #include <assert.h> | ||
23 | 25 | ||
24 | const char *progname; | 26 | const char *progname; |
25 | 27 | ||
@@ -68,10 +70,14 @@ const char *short_scale[] = { | |||
68 | }; | 70 | }; |
69 | size_t short_scale_max = sizeof (short_scale) / sizeof (short_scale[0]); | 71 | size_t short_scale_max = sizeof (short_scale) / sizeof (short_scale[0]); |
70 | 72 | ||
73 | typedef unsigned long numeral_t; | ||
74 | |||
71 | char buffer[1024]; | 75 | char buffer[1024]; |
72 | size_t bufsize = sizeof(buffer); | 76 | size_t bufsize = sizeof(buffer); |
73 | size_t bufoff; | 77 | size_t bufoff; |
74 | int delim = 0; | 78 | int delim = 0; |
79 | int revert_option = 0; | ||
80 | int random_option = 0; | ||
75 | 81 | ||
76 | void | 82 | void |
77 | copy (const char *str, int dch) | 83 | copy (const char *str, int dch) |
@@ -87,7 +93,7 @@ copy (const char *str, int dch) | |||
87 | } | 93 | } |
88 | 94 | ||
89 | void | 95 | void |
90 | format_100 (unsigned long num) | 96 | format_100 (numeral_t num) |
91 | { | 97 | { |
92 | if (num == 0) | 98 | if (num == 0) |
93 | ; | 99 | ; |
@@ -97,7 +103,7 @@ format_100 (unsigned long num) | |||
97 | copy (nstr[1][num-10], delim); | 103 | copy (nstr[1][num-10], delim); |
98 | else | 104 | else |
99 | { | 105 | { |
100 | unsigned long tens = num / 10; | 106 | numeral_t tens = num / 10; |
101 | num %= 10; | 107 | num %= 10; |
102 | if (num) | 108 | if (num) |
103 | { | 109 | { |
@@ -111,7 +117,7 @@ format_100 (unsigned long num) | |||
111 | } | 117 | } |
112 | 118 | ||
113 | void | 119 | void |
114 | format_1000 (unsigned long num, int more) | 120 | format_1000 (numeral_t num, int more) |
115 | { | 121 | { |
116 | size_t n = num % 100; | 122 | size_t n = num % 100; |
117 | num /= 100; | 123 | num /= 100; |
@@ -128,7 +134,7 @@ format_1000 (unsigned long num, int more) | |||
128 | 134 | ||
129 | 135 | ||
130 | void | 136 | void |
131 | format_number (unsigned long num) | 137 | format_number (numeral_t num) |
132 | { | 138 | { |
133 | int s = 0; | 139 | int s = 0; |
134 | size_t off; | 140 | size_t off; |
@@ -140,7 +146,7 @@ format_number (unsigned long num) | |||
140 | 146 | ||
141 | do | 147 | do |
142 | { | 148 | { |
143 | unsigned long n = num % 1000; | 149 | numeral_t n = num % 1000; |
144 | 150 | ||
145 | num /= 1000; | 151 | num /= 1000; |
146 | 152 | ||
@@ -161,23 +167,26 @@ format_number (unsigned long num) | |||
161 | 167 | ||
162 | 168 | ||
163 | void | 169 | void |
164 | print_number (unsigned long num) | 170 | print_number (numeral_t num) |
165 | { | 171 | { |
166 | format_number (num); | 172 | format_number (num); |
167 | printf ("%lu\t%s\n", num, buffer + bufoff); | 173 | if (revert_option) |
174 | printf ("%s\t%lu\n", buffer + bufoff, num); | ||
175 | else | ||
176 | printf ("%lu\t%s\n", num, buffer + bufoff); | ||
168 | } | 177 | } |
169 | 178 | ||
170 | void | 179 | void |
171 | print_range (unsigned long num, unsigned long to) | 180 | print_range (numeral_t num, numeral_t to) |
172 | { | 181 | { |
173 | for (; num <= to; num++) | 182 | for (; num <= to; num++) |
174 | print_number (num); | 183 | print_number (num); |
175 | } | 184 | } |
176 | 185 | ||
177 | unsigned long | 186 | numeral_t |
178 | xstrtoul (char *arg, char **endp) | 187 | xstrtoul (char *arg, char **endp) |
179 | { | 188 | { |
180 | unsigned long num; | 189 | numeral_t num; |
181 | char *p; | 190 | char *p; |
182 | 191 | ||
183 | errno = 0; | 192 | errno = 0; |
@@ -199,23 +208,130 @@ xstrtoul (char *arg, char **endp) | |||
199 | 208 | ||
200 | return num; | 209 | return num; |
201 | } | 210 | } |
211 | |||
212 | struct numrange | ||
213 | { | ||
214 | numeral_t start; | ||
215 | numeral_t count; | ||
216 | }; | ||
217 | |||
218 | struct numrange *range; | ||
219 | size_t range_count; | ||
220 | size_t range_max; | ||
221 | size_t range_total; | ||
222 | |||
223 | #define RANGE_INITIAL_ALLOC 16 | ||
224 | |||
225 | static void | ||
226 | range_add (numeral_t start, numeral_t count) | ||
227 | { | ||
228 | if (range_count == range_max) | ||
229 | { | ||
230 | if (range_max == 0) | ||
231 | range_max = RANGE_INITIAL_ALLOC; | ||
232 | else | ||
233 | { | ||
234 | assert ((size_t)-1 / 3 * 2 / sizeof (range[0]) > range_max); | ||
235 | range_max += (range_max + 1) / 2; | ||
236 | } | ||
237 | range = realloc (range, range_max * sizeof (range[0])); | ||
238 | if (!range) | ||
239 | abort (); | ||
240 | } | ||
241 | range[range_count].start = start; | ||
242 | range[range_count].count = count; | ||
243 | ++range_count; | ||
244 | range_total += count; | ||
245 | } | ||
246 | |||
247 | numeral_t | ||
248 | range_get (size_t idx) | ||
249 | { | ||
250 | numeral_t n; | ||
251 | size_t i; | ||
252 | |||
253 | assert (range_count > 0); | ||
254 | |||
255 | for (i = 0; i < range_count; i++) | ||
256 | { | ||
257 | if (idx < range[i].count) | ||
258 | break; | ||
259 | idx -= range[i].count; | ||
260 | } | ||
261 | n = range[i].start + idx; | ||
262 | if (range[i].count == 1) | ||
263 | { | ||
264 | /* Remove range */ | ||
265 | if (i + 1 < range_count) | ||
266 | memmove (range + i, range + i + 1, | ||
267 | (range_count - i - 1) * sizeof (range[0])); | ||
268 | range_count--; | ||
269 | } | ||
270 | else if (idx == 0) | ||
271 | { | ||
272 | range[i].start++; | ||
273 | range[i].count--; | ||
274 | } | ||
275 | else | ||
276 | { | ||
277 | /* Split range */ | ||
278 | if (range[i].count > idx - 1) | ||
279 | { | ||
280 | range_total -= range[i].count - idx - 1; | ||
281 | range_add (range[i].start + idx + 1, range[i].count - idx - 1); | ||
282 | } | ||
283 | range[i].count = idx; | ||
284 | } | ||
285 | range_total--; | ||
286 | return n; | ||
287 | } | ||
202 | 288 | ||
203 | int | 289 | int |
204 | main (int argc, char **argv) | 290 | main (int argc, char **argv) |
205 | { | 291 | { |
206 | progname = argv[0]; | 292 | progname = argv[0]; |
207 | 293 | ||
208 | if (argc == 1 || strcmp (argv[1], "-h") == 0) | 294 | while (--argc) |
209 | { | 295 | { |
210 | printf ("usage: %s NUM [NUM...]\n", progname); | 296 | char *arg = *++argv; |
211 | printf ("where NUM is a decimal number, NUM:COUNT or NUM-NUM\n"); | 297 | if (strcmp (arg, "-h") == 0 || strcmp (arg, "-help") == 0) |
212 | exit (0); | 298 | { |
299 | printf ("usage: %s [-revert] [-random] RANGE [RANGE...]\n", progname); | ||
300 | printf ("Lists english numerals in given ranges\n\n"); | ||
301 | printf ("Each RANGE is one of:\n\n"); | ||
302 | printf (" X:N N numerals starting from X; interval [X,X+N]\n"); | ||
303 | printf (" X-Y numerals from X to Y; interval [X,Y]\n\n"); | ||
304 | printf ("Options are:\n\n"); | ||
305 | printf (" -revert revert output columns (numeral first)\n"); | ||
306 | printf (" -random produce list in random order\n"); | ||
307 | printf ("\n"); | ||
308 | exit (0); | ||
309 | } | ||
310 | else if (strcmp (arg, "-revert") == 0) | ||
311 | { | ||
312 | revert_option = 1; | ||
313 | } | ||
314 | else if (strcmp (arg, "-random") == 0) | ||
315 | { | ||
316 | random_option = 1; | ||
317 | } | ||
318 | else if (arg[0] == '-') | ||
319 |