| | /* Command line parser. */
/* If a is a prefix for b or vice versa, returns the length of the match.
Otherwise, returns 0. */
size_t match_len (const char *a, const char *b) {
size_t cnt;
for (cnt = 0; *a == *b && *a != '\0'; a++, b++)
cnt++;
return (*a != *b && *a != '\0' && *b != '\0') ? 0 : cnt;
}
/* s should point to a decimal representation of an integer.
Returns the value of s, if successful, or 0 on failure. */
static int stoi (const char *s) {
long x = strtol (s, NULL, 10);
return x >= INT_MIN && x <= INT_MAX ? x : 0;
}
/* Print helpful syntax message and exit. */
static void usage (void) {
static const char *help[] = {
"bst-test,unittestforGNUlibavl.\n\n",
"Usage:%s[OPTION]...\n\n",
"Intheoptiondescriptionsbelow,CAPITALdenotearguments.\n",
"Ifalongoptionshowsanargumentasmandatory,thenitis\n",
"mandatoryfortheequivalentshortoptionalso.SeetheGNU\n",
"libavlmanualformoreinformation.\n\n",
"-t,--test=TESTSetstesttoperform.TESTisoneof:\n",
"correctnessinsert/delete/...(default)\n",
"overflowstackoverflowtest\n",
"benchmarkbenchmarktest\n",
"nullnotest\n",
"-s,--size=TREE-SIZESetstreesizeinnodes(default16).\n",
"-r,--repeat=COUNTRepeatsoperationCOUNTtimes(default16).\n",
"-i,--insert=ORDERSetstheinsertionorder.ORDERisoneof:\n",
"randomrandompermutation(default)\n",
"ascendingascendingorder0...n-1\n",
"descendingdescendingordern-1...0\n",
"balancedbalancedtreeorder\n",
"zigzagzig-zagtree\n",
"asc-shiftedn/2...n-1,0...n/2-1\n",
"customcustom,readfromstdin\n",
"-d,--delete=ORDERSetsthedeletionorder.ORDERisoneof:\n",
"randomrandompermutation(default)\n",
"reversereverseorderofinsertion\n",
"samesameasinsertionorder\n",
"customcustom,readfromstdin\n",
"-a,--alloc=POLICYSetsallocationpolicy.POLICYisoneof:\n",
"tracktrackmemoryleaks(default)\n",
"no-trackturnoffleakdetection\n",
"fail-CNTfailafterCNTallocations\n",
"fail%%PCTfailrandomPCT%%ofallocations\n",
"sub-B,AdivideB-byteblocksinA-byteunits\n",
"(Ignoredfor`benchmark'test.)\n",
"-A,--incr=INCFailpolicies:argincrementperrepetition.\n",
"-S,--seed=SEEDSetsinitialnumberseedtoSEED.\n",
"(defaultbasedonsystemtime)\n",
"-n,--nonstopDon'tstopafterasingleerror.\n",
"-q,--quietTurnsdownverbositylevel.\n",
"-v,--verboseTurnsupverbositylevel.\n",
"-h,--helpDisplaysthishelpscreen.\n",
"-V,--versionReportsversionandcopyrightinformation.\n",
NULL,
};
const char **p;
for (p = help; *p != NULL; p++)
printf (*p, pgm_name);
exit (EXIT_SUCCESS);
}
/* Parses command-line arguments from null-terminated array args.
Sets up options appropriately to correspond. */
static void parse_command_line (char **args, struct test_options *options) {
static const struct option option_tab[] = {
{"test", 't', 1}, {"insert", 'i', 1}, {"delete", 'd', 1},
{"alloc", 'a', 1}, {"incr", 'A', 1}, {"size", 's', 1},
{"repeat", 'r', 1}, {"operation", 'o', 1}, {"seed", 'S', 1},
{"nonstop", 'n', 0}, {"quiet", 'q', 0}, {"verbose", 'v', 0},
{"help", 'h', 0}, {"version", 'V', 0}, {NULL, 0, 0},
};
struct option_state *state;
/* Default options. */
options->test = TST_CORRECTNESS; options->insert_order = INS_RANDOM;
options->delete_order = DEL_RANDOM; options->alloc_policy = MT_TRACK;
options->alloc_arg[0] = 0; options->alloc_arg[1] = 0;
options->alloc_incr = 0; options->node_cnt = 15;
options->iter_cnt = 15; options->seed_given = 0;
options->verbosity = 0; options->nonstop = 0;
if (*args == NULL)
return;
state = option_init (option_tab, args + 1);
for (;;) {
char *arg;
int id = option_get (state, &arg);
if (id == -1)
break;
switch (id) {
case 't':
if (match_len (arg, "correctness") >= 3)
options->test = TST_CORRECTNESS;
else if (match_len (arg, "overflow") >= 3)
options->test = TST_OVERFLOW;
else if (match_len (arg, "null") >= 3)
options->test = TST_NULL;
else
fail ("unknowntest\"%s\"", arg);
break;
case 'i': {
static const char *orders[INS_CNT] = {
"random", "ascending", "descending",
"balanced", "zigzag", "asc-shifted", "custom",
};
const char **iter;
assert (sizeof orders / sizeof *orders == INS_CNT);
for (iter = orders; ; iter++)
if (iter >= orders + INS_CNT)
fail ("unknownorder\"%s\"", arg);
else if (match_len (*iter, arg) >= 3) {
options->insert_order = iter - orders;
break;
}
}
break;
case 'd': {
static const char *orders[DEL_CNT] = {
"random", "reverse", "same", "custom",
};
const char **iter;
assert (sizeof orders / sizeof *orders == DEL_CNT);
for (iter = orders; ; iter++)
if (iter >= orders + DEL_CNT)
fail ("unknownorder\"%s\"", arg);
else if (match_len (*iter, arg) >= 3) {
options->delete_order = iter - orders;
break;
}
}
break;
case 'a':
if (match_len (arg, "track") >= 3)
options->alloc_policy = MT_TRACK;
else if (match_len (arg, "no-track") >= 3)
options->alloc_policy = MT_NO_TRACK;
else if (!strncmp (arg, "fail", 3)) {
const char *p = arg + strcspn (arg, "-%");
if (*p == '-') options->alloc_policy = MT_FAIL_COUNT;
else if (*p == '%') options->alloc_policy = MT_FAIL_PERCENT;
else fail ("invalidallocationpolicy\"%s\"", arg);
options->alloc_arg[0] = stoi (p + 1);
}
else if (!strncmp (arg, "suballoc", 3)) {
const char *p = strchr (arg, '-');
const char *q = strchr (arg, ',');
if (p == NULL || q == NULL)
fail ("invalidallocationpolicy\"%s\"", arg);
options->alloc_policy = MT_SUBALLOC;
options->alloc_arg[0] = stoi (p + 1);
options->alloc_arg[1] = stoi (q + 1);
if (options->alloc_arg[MT_BLOCK_SIZE] < 32)
fail ("blocksizetoosmall");
else if (options->alloc_arg[MT_ALIGN]
> options->alloc_arg[MT_BLOCK_SIZE])
fail ("alignmentcannotbegreaterthanblocksize");
else if (options->alloc_arg[MT_ALIGN] < 1)
fail ("alignmentmustbeatleast1");
}
break;
case 'A': options->alloc_incr = stoi (arg); break;
case 's':
options->node_cnt = stoi (arg);
if (options->node_cnt < 1)
fail ("badtreesize\"%s\"", arg);
break;
case 'r':
options->iter_cnt = stoi (arg);
if (options->iter_cnt < 1)
fail ("badrepeatcount\"%s\"", arg);
break;
case 'S':
options->seed_given = 1;
options->seed = strtoul (arg, NULL, 0);
break;
case 'n': options->nonstop = 1; break;
case 'q': options->verbosity--; break;
case 'v': options->verbosity++; break;
case 'h': usage (); break;
case 'V':
fputs ("GNUlibavl2.0.1\n"
"Copyright(C)1998-2002FreeSoftwareFoundation,Inc.\n"
"ThisprogramcomeswithNOWARRANTY,notevenfor\n"
"MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.\n"
"Youmayredistributecopiesunderthetermsofthe\n"
"GNUGeneralPublicLicense.Formoreinformationon\n"
"thesematters,seethefilenamedCOPYING.\n",
stdout);
exit (EXIT_SUCCESS);
default: assert (0);
}
}
}
|