diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-05-29 10:36:59 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-05-29 10:36:59 +0300 |
commit | a2528b04a987bdbff4763edd2258622ad3141024 (patch) | |
tree | 18fafe3ac7c1208dd7e12574fc8cb0093301cd5a /tests | |
parent | 120727f7c5b36bddaa3ef232dd9b105148ac7433 (diff) | |
download | gdbm-a2528b04a987bdbff4763edd2258622ad3141024.tar.gz gdbm-a2528b04a987bdbff4763edd2258622ad3141024.tar.bz2 |
Minor changes
* src/gdbmtool.c: Reduce memory consuption in -random mode. Some
minor bugfixes as well.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/num2word.c | 125 |
1 files changed, 80 insertions, 45 deletions
diff --git a/tests/num2word.c b/tests/num2word.c index 1ac54a4..2a1878a 100644 --- a/tests/num2word.c +++ b/tests/num2word.c | |||
@@ -209,24 +209,46 @@ xstrtoul (char *arg, char **endp) | |||
209 | return num; | 209 | return num; |
210 | } | 210 | } |
211 | 211 | ||
212 | struct numrange | 212 | struct numrange /* Range of numbers */ |
213 | { | 213 | { |
214 | numeral_t start; | 214 | numeral_t start; /* Starting number */ |
215 | numeral_t count; | 215 | numeral_t count; /* Count of numbers in the range */ |
216 | }; | 216 | }; |
217 | 217 | ||
218 | struct numrange *range; | 218 | struct numrange *range; /* Array of ranges */ |
219 | size_t range_count; | 219 | size_t range_max; /* Number of elements in RANGE */ |
220 | size_t range_max; | 220 | size_t range_total; /* Total count of numbers (sum of range[i].count) */ |
221 | size_t range_total; | ||
222 | 221 | ||
223 | #define RANGE_INITIAL_ALLOC 16 | 222 | #define RANGE_INITIAL_ALLOC 16 /* Initial allocation for the range (entries) */ |
224 | 223 | ||
224 | /* List of available entries. | ||
225 | |||
226 | Unallocated entries in RANGE form a singly-linked list. Each unallocated | ||
227 | entry has COUNT set to 0, and START set to the index of the next | ||
228 | unallocated entry, or AVAIL_NIL, if that's the last free entry. | ||
229 | */ | ||
230 | #define AVAIL_NIL ((size_t)-1) /* Marks end of the list */ | ||
231 | size_t range_avail = AVAIL_NIL; /* Index of the first available entry */ | ||
232 | |||
233 | /* Return entry I to the list of available ones */ | ||
234 | static void | ||
235 | range_remove (size_t i) | ||
236 | { | ||
237 | range[i].count = 0; | ||
238 | range[i].start = range_avail; | ||
239 | range_avail = i; | ||
240 | } | ||
241 | |||
242 | /* Add interval [start, start + count) */ | ||
225 | static void | 243 | static void |
226 | range_add (numeral_t start, numeral_t count) | 244 | range_add (numeral_t start, numeral_t count) |
227 | { | 245 | { |
228 | if (range_count == range_max) | 246 | size_t i; |
247 | |||
248 | if (range_avail == AVAIL_NIL) | ||
229 | { | 249 | { |
250 | size_t n = range_max; | ||
251 | |||
230 | if (range_max == 0) | 252 | if (range_max == 0) |
231 | range_max = RANGE_INITIAL_ALLOC; | 253 | range_max = RANGE_INITIAL_ALLOC; |
232 | else | 254 | else |
@@ -234,39 +256,41 @@ range_add (numeral_t start, numeral_t count) | |||
234 | assert ((size_t)-1 / 3 * 2 / sizeof (range[0]) > range_max); | 256 | assert ((size_t)-1 / 3 * 2 / sizeof (range[0]) > range_max); |
235 | range_max += (range_max + 1) / 2; | 257 | range_max += (range_max + 1) / 2; |
236 | } | 258 | } |
259 | |||
237 | range = realloc (range, range_max * sizeof (range[0])); | 260 | range = realloc (range, range_max * sizeof (range[0])); |
238 | if (!range) | 261 | if (!range) |
239 | abort (); | 262 | abort (); |
263 | |||
264 | for (i = range_max; i > n; i--) | ||
265 | range_remove (i - 1); | ||
240 | } | 266 | } |
241 | range[range_count].start = start; | 267 | |
242 | range[range_count].count = count; | 268 | i = range_avail; |
243 | ++range_count; | 269 | range_avail = range[i].start; |
270 | |||
271 | range[i].start = start; | ||
272 | range[i].count = count; | ||
244 | range_total += count; | 273 | range_total += count; |
245 | } | 274 | } |
246 | 275 | ||
276 | /* Treating RANGE as a contiguous array of numbers, return the number in | ||
277 | position IDX and remove it from the array. */ | ||
247 | numeral_t | 278 | numeral_t |
248 | range_get (size_t idx) | 279 | range_get (size_t idx) |
249 | { | 280 | { |
250 | numeral_t n; | 281 | numeral_t n; |
251 | size_t i; | 282 | size_t i; |
252 | 283 | ||
253 | assert (range_count > 0); | 284 | for (i = 0; i < range_max; i++) |
254 | |||
255 | for (i = 0; i < range_count; i++) | ||
256 | { | 285 | { |
257 | if (idx < range[i].count) | 286 | if (idx < range[i].count) |
258 | break; | 287 | break; |
259 | idx -= range[i].count; | 288 | idx -= range[i].count; |
260 | } | 289 | } |
290 | assert (i < range_max); | ||
261 | n = range[i].start + idx; | 291 | n = range[i].start + idx; |
262 | if (range[i].count == 1) | 292 | if (range[i].count == 1) |
263 | { | 293 | range_remove (i); |
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) | 294 | else if (idx == 0) |
271 | { | 295 | { |
272 | range[i].start++; | 296 | range[i].start++; |
@@ -286,25 +310,33 @@ range_get (size_t idx) | |||
286 | return n; | 310 | return n; |
287 | } | 311 | } |
288 | 312 | ||
313 | void | ||
314 | usage (FILE *fp) | ||
315 | { | ||
316 | fprintf (fp, "usage: %s [-revert] [-random] RANGE [RANGE...]\n", progname); | ||
317 | fprintf (fp, "Lists english numerals in given ranges\n\n"); | ||
318 | fprintf (fp, "Each RANGE is one of:\n\n"); | ||
319 | fprintf (fp, " X:N N numerals starting from X; interval [X,X+N]\n"); | ||
320 | fprintf (fp, " X-Y numerals from X to Y; interval [X,Y]\n\n"); | ||
321 | fprintf (fp, "Options are:\n\n"); | ||
322 | fprintf (fp, " -random produce list in random order\n"); | ||
323 | fprintf (fp, " -revert revert output columns (numeral first)\n"); | ||
324 | fprintf (fp, " -help display this help summary\n"); | ||
325 | fprintf (fp, "\n"); | ||
326 | } | ||
327 | |||
289 | int | 328 | int |
290 | main (int argc, char **argv) | 329 | main (int argc, char **argv) |
291 | { | 330 | { |
292 | progname = argv[0]; | 331 | progname = *argv++; |
332 | --argc; | ||
293 | 333 | ||
294 | while (--argc) | 334 | for (; argc; argc--, argv++) |
295 | { | 335 | { |
296 | char *arg = *++argv; | 336 | char *arg = *argv; |
297 | if (strcmp (arg, "-h") == 0 || strcmp (arg, "-help") == 0) | 337 | if (strcmp (arg, "-h") == 0 || strcmp (arg, "-help") == 0) |
298 | { | 338 | { |
299 | printf ("usage: %s [-revert] [-random] RANGE [RANGE...]\n", progname); | 339 | usage (stdout); |
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); | 340 | exit (0); |
309 | } | 341 | } |
310 | else if (strcmp (arg, "-revert") == 0) | 342 | else if (strcmp (arg, "-revert") == 0) |
@@ -321,22 +353,18 @@ main (int argc, char **argv) | |||
321 | return 1; | 353 | return 1; |
322 | } | 354 | } |
323 | else | 355 | else |
324 | { | 356 | break; |
325 | argc++; | ||
326 | argv--; | ||
327 | break; | ||
328 | } | ||
329 | } | 357 | } |
330 | 358 | ||
331 | while (--argc) | 359 | for (; argc; argc--, argv++) |
332 | { | 360 | { |
333 | char *arg = *++argv; | 361 | char *arg = *argv; |
334 | numeral_t num, num2; | 362 | numeral_t num, num2; |
335 | char *p; | 363 | char *p; |
336 | 364 | ||
337 | num = xstrtoul (arg, &p); | 365 | num = xstrtoul (arg, &p); |
338 | if (*p == 0) | 366 | if (*p == 0) |
339 | print_number (num); | 367 | range_add (num, 1); |
340 | else if (*p == ':') | 368 | else if (*p == ':') |
341 | { | 369 | { |
342 | *p++ = 0; | 370 | *p++ = 0; |
@@ -367,6 +395,12 @@ main (int argc, char **argv) | |||
367 | } | 395 | } |
368 | } | 396 | } |
369 | 397 | ||
398 | if (range_total == 0) | ||
399 | { | ||
400 | usage (stderr); | ||
401 | exit (1); | ||
402 | } | ||
403 | |||
370 | if (random_option) | 404 | if (random_option) |
371 | { | 405 | { |
372 | srandom (time (NULL)); | 406 | srandom (time (NULL)); |
@@ -379,8 +413,9 @@ main (int argc, char **argv) | |||
379 | else | 413 | else |
380 | { | 414 | { |
381 | size_t i; | 415 | size_t i; |
382 | for (i = 0; i < range_count; i++) | 416 | for (i = 0; i < range_max; i++) |
383 | print_range (range[i].start, range[i].start + range[i].count - 1); | 417 | if (range[i].count) |
418 | print_range (range[i].start, range[i].start + range[i].count - 1); | ||
384 | } | 419 | } |
385 | exit (0); | 420 | exit (0); |
386 | } | 421 | } |