static int parse_params(int argc, char **argv, struct params *params) { struct getlongopt *parser; /* option parser */ int id; /* id of parsed option */ const char *arg; /* argument of parsed option */ enum getlongopt_ret ret; /* return value from option parser */ struct getlongopt_opt opts[] = { {"input", '\0', GETLONGOPT_ARG_REQUIRED, 'i'}, {"verbose", 'v', GETLONGOPT_ARG_NONE, 'v'} }; if ((parser = getlongopt_new(argc - 1, (const char **) &argv[1], opts, sizeof(opts) / sizeof(*opts)))) { /* succeeded, do nothing */ } else { fprintf(stderr, "failed to initialise options parser\n"); return 0; } while ((ret = getlongopt(parser, &id, &arg)) == GETLONGOPT_OK) { switch (id) { case 'i': /* ignore */ break; case 'v': /* verbose */ params->verbose = 1; break; default: assert(0); } } getlongopt_delete(parser); return 1; }
static struct args *parse_args(unsigned int argc, char **argv, FILE *output) { struct args *args; int err = 0, quiet = 0, id; long int num; /* temporary space for numeric conversion */ char *tmp; /* temporary space */ unsigned int ind; const char *arg; struct getlongopt *parser; enum getlongopt_ret ret = GETLONGOPT_OK; struct getlongopt_opt opts[] = { {"file", 'f', GETLONGOPT_ARG_REQUIRED, OPT_FILE}, {"file-list", 'F', GETLONGOPT_ARG_REQUIRED, OPT_FILELIST}, {"number-results", 'n', GETLONGOPT_ARG_REQUIRED, OPT_NUMRESULTS}, {"runid", 'r', GETLONGOPT_ARG_REQUIRED, OPT_RUNID}, {"print-queries", '\0', GETLONGOPT_ARG_NONE, OPT_PRINTQUERIES}, {"timing", '\0', GETLONGOPT_ARG_NONE, OPT_TIMING}, {"okapi", 'o', GETLONGOPT_ARG_NONE, OPT_OKAPI}, {"dirichlet", '\0', GETLONGOPT_ARG_REQUIRED, OPT_DIRICHLET}, {"hawkapi", '\0', GETLONGOPT_ARG_REQUIRED, OPT_HAWKAPI}, {"k1", '1', GETLONGOPT_ARG_REQUIRED, OPT_K1}, {"k3", '3', GETLONGOPT_ARG_REQUIRED, OPT_K3}, {"b", 'b', GETLONGOPT_ARG_REQUIRED, OPT_B}, {"pivoted-cosine", 'p', GETLONGOPT_ARG_REQUIRED, OPT_PIVOTED_COSINE}, {"cosine", 'c', GETLONGOPT_ARG_NONE, OPT_COSINE}, {"anh-impact", '\0', GETLONGOPT_ARG_NONE, OPT_ANH_IMPACT}, {"title", 't', GETLONGOPT_ARG_NONE, OPT_TITLE}, {"description", 'd', GETLONGOPT_ARG_NONE, OPT_DESCRIPTION}, {"narrative", 'a', GETLONGOPT_ARG_NONE, OPT_NARRATIVE}, {"qrels", 'q', GETLONGOPT_ARG_REQUIRED, OPT_QRELS}, {"accumulator-limit", 'A', GETLONGOPT_ARG_REQUIRED, OPT_ACCUMULATOR_LIMIT}, {"ignore-version", '\0', GETLONGOPT_ARG_NONE, OPT_IGNORE_VERSION}, {"help", 'h', GETLONGOPT_ARG_NONE, OPT_HELP}, {"version", 'v', GETLONGOPT_ARG_NONE, OPT_VERSION}, {"memory", 'm', GETLONGOPT_ARG_REQUIRED, OPT_MEMORY}, {"parse-buffer", 'm', GETLONGOPT_ARG_REQUIRED, OPT_PARSEBUF}, {"tablesize", 'm', GETLONGOPT_ARG_REQUIRED, OPT_TABLESIZE}, {"big-and-fast", 'm', GETLONGOPT_ARG_NONE, OPT_BIG_AND_FAST}, {"phrase", '\0', GETLONGOPT_ARG_OPTIONAL, OPT_PHRASE}, {"term-cutoff", '\0', GETLONGOPT_ARG_REQUIRED, OPT_CUTOFF}, {"dummy", '\0', GETLONGOPT_ARG_NONE, OPT_DUMMY}, {"non-stop", '\0', GETLONGOPT_ARG_NONE, OPT_NONSTOP}, {"query-stop", '\0', GETLONGOPT_ARG_OPTIONAL, OPT_STOP}, {NULL, 'V', GETLONGOPT_ARG_NONE, OPT_VERSION} }; if ((args = malloc(sizeof(*args))) && (parser = getlongopt_new(argc - 1, (const char **) &argv[1], opts, sizeof(opts) / sizeof(*opts)))) { /* succeeded, do nothing */ } else { if (args) { free(args); } fprintf(output, "failed to initialise option parsing\n"); return NULL; } args->stoplist = NULL; args->topic_files = 0; args->topic_file = NULL; args->run_id = NULL; args->idx = NULL; args->numresults = 0; args->numaccumulators = 0; args->sopts = INDEX_SEARCH_NOOPT; args->lopts = INDEX_LOAD_NOOPT; args->title = 0; args->descr = 0; args->narr = 0; args->qrels = NULL; args->sopt.u.okapi_k3.k1 = 1.2F; args->sopt.u.okapi_k3.k3 = 1e10; args->sopt.u.okapi_k3.b = 0.75; args->lopt.docmap_cache = DOCMAP_CACHE_TRECNO; args->print_queries = args->timing = 0; args->memory = MEMORY_DEFAULT; args->phrase = 0; args->cutoff = 0; args->dummy = 0; args->cont = 0; /* parse arguments */ while (!err && ((ret = getlongopt(parser, &id, &arg)) == GETLONGOPT_OK)) { switch (id) { case OPT_RUNID: /* set run_id */ if (!args->run_id) { if (!(args->run_id = str_dup(arg))) { fprintf(output, "couldn't set run_id '%s': %s\n", arg, strerror(errno)); err = quiet = 1; } } else if (args->run_id) { fprintf(output, "run_id already set to '%s'\n", args->run_id); err = 1; quiet = 0; } break; case OPT_STOP: if (args->stoplist) { err = 1; fprintf(output, "query stoplist specified multiple times\n"); quiet = 0; } else if (!arg || (args->stoplist = str_dup(arg))) { args->lopts |= INDEX_LOAD_QSTOP; args->lopt.qstop_file = args->stoplist; } else { err = quiet = 1; fprintf(output, "can't copy query stoplist name\n"); } break; case OPT_MEMORY: /* set memory */ args->memory = atoi(arg); break; case OPT_PARSEBUF: errno = 0; num = strtol(arg, &tmp, 10); if (!errno && (num > 0) && (num <= UINT_MAX) && !*tmp) { args->lopts |= INDEX_LOAD_PARSEBUF; args->lopt.parsebuf = num; } else { fprintf(output, "error converting parsebuf value '%s'\n", arg); err = 1; } break; case OPT_TABLESIZE: errno = 0; num = strtol(arg, &tmp, 10); if (!errno && (num > 0) && (num <= UINT_MAX) && !*tmp) { args->lopts |= INDEX_LOAD_TABLESIZE; args->lopt.tablesize = num; } else { fprintf(output, "error converting tablesize value '%s'\n", arg); err = 1; } break; case OPT_BIG_AND_FAST: /* use big memory options */ if (args->memory == MEMORY_DEFAULT) { args->memory = BIG_MEMORY_DEFAULT; } if (!(args->lopts & INDEX_NEW_PARSEBUF)) { args->lopts |= INDEX_LOAD_PARSEBUF; args->lopt.parsebuf = BIG_PARSE_BUFFER; } if (!(args->lopts & INDEX_NEW_TABLESIZE)) { args->lopts |= INDEX_LOAD_TABLESIZE; args->lopt.tablesize = BIG_TABLESIZE; } break; case OPT_QRELS: /* they want it evaluated against some qrels */ if (!args->qrels) { if ((args->qrels = treceval_qrels_new(arg))) { /* succeeded, do nothing */ } else { fprintf(output, "failed to load qrels from '%s'\n", arg); err = 1; } } else { fprintf(output, "qrels specified multiple times\n"); err = 1; } break; case OPT_IGNORE_VERSION: args->lopts |= INDEX_LOAD_IGNORE_VERSION; break; case OPT_ACCUMULATOR_LIMIT: /* set number of accumulators to use. */ errno = 0; num = strtol(arg, &tmp, 10); if (!errno && !*tmp) { args->sopt.accumulator_limit = num; args->sopts |= INDEX_SEARCH_ACCUMULATOR_LIMIT; } else { fprintf(output, "error converting accumulator limit value '%s'\n", arg); err = 1; } break; case OPT_NONSTOP: args->cont = 1; break; case OPT_DUMMY: args->dummy = 1; break; case OPT_CUTOFF: args->cutoff = atoi(arg); break; case OPT_PHRASE: /* they want to run it as a phrase, optionally sloppy */ args->phrase = 1; if (arg) { char *end; long int tmpnum = strtol(arg, &end, 0); if (!*end && (tmpnum <= UINT_MAX)) { args->sloppiness = tmpnum; } else { fprintf(output, "couldn't convert '%s' to number\n", arg); } } else { args->sloppiness = 0; } break; case OPT_NUMRESULTS: /* set number of results per topic */ if (!args->numresults) { char *end; long int tmpnum = strtol(arg, &end, 0); if (!*end && (tmpnum <= UINT_MAX)) { args->numresults = tmpnum; } else { fprintf(output, "couldn't convert '%s' to number\n", arg); } } else { fprintf(output, "number of results is already set to %u\n", args->numresults); err = 1; } break; case OPT_FILE: /* add topic file */ if (!(add_topic_file(args, arg))) { fprintf(output, "couldn't add file '%s': %s\n", arg, strerror(errno)); err = quiet = 1; } break; case OPT_FILELIST: /* add topic file file */ if (!(add_topic_file_file(args, arg))) { fprintf(output, "couldn't add list '%s': %s\n", arg, strerror(errno)); err = quiet = 1; } break; case OPT_HELP: /* they want help */ err = 1; output = stdout; break; case OPT_VERSION: /* they want version info */ printf("version %s\n", PACKAGE_VERSION); err = quiet = 1; output = stdout; break; case OPT_ANH_IMPACT: args->sopts |= INDEX_SEARCH_ANH_IMPACT_RANK; break; case OPT_HAWKAPI: /* they want to use hawkapi */ args->sopts |= INDEX_SEARCH_HAWKAPI_RANK; if (!sscanf(arg, "%f", &args->sopt.u.hawkapi.alpha)) { fprintf(stderr, "failed to read alpha parameter\n"); err = 1; } break; case OPT_DIRICHLET: /* they want to use dirichlet */ args->sopts |= INDEX_SEARCH_DIRICHLET_RANK; if (!sscanf(arg, "%f", &args->sopt.u.dirichlet.mu)) { fprintf(stderr, "failed to read mu parameter\n"); err = 1; } break; case OPT_OKAPI: /* they want to use okapi */ args->sopts |= INDEX_SEARCH_OKAPI_RANK; break; case OPT_K1: /* set okapi k1 parameter */ if (sscanf(arg, "%f", &args->sopt.u.okapi_k3.k1)) { /* do nothing */ } else { fprintf(output, "can't read k1 value '%s'\n", arg); err = 1; } break; case OPT_K3: /* set okapi k3 parameter */ if (sscanf(arg, "%f", &args->sopt.u.okapi_k3.k3)) { /* do nothing */ } else { fprintf(output, "can't read k3 value '%s'\n", arg); err = 1; } break; case OPT_B: /* set okapi b parameter */ if (sscanf(arg, "%f", &args->sopt.u.okapi_k3.b)) { /* do nothing */ } else { fprintf(output, "can't read b value '%s'\n", arg); err = 1; } break; case OPT_TIMING: /* print queries */ args->timing = 1; break; case OPT_PRINTQUERIES: /* print queries */ args->print_queries = 1; break; case OPT_TITLE: /* use title in query */ args->title = 1; break; case OPT_DESCRIPTION: /* use description in query */ args->descr = 1; break; case OPT_NARRATIVE: /* use narrative in query */ args->narr = 1; break; case OPT_PIVOTED_COSINE: /* they want to use pivoted cosine */ if (sscanf(arg, "%f", &args->sopt.u.pcosine.pivot)) { args->sopts |= INDEX_SEARCH_PCOSINE_RANK; /* arrange for weights to be loaded into memory */ args->lopts |= INDEX_LOAD_DOCMAP_CACHE; args->lopt.docmap_cache |= DOCMAP_CACHE_WEIGHT; if (args->sopt.u.pcosine.pivot < 0.0) { fprintf(output, "cosine pivot can't be negative\n"); err = 1; } } else { fprintf(output, "can't read pivot value '%s'\n", arg); err = 1; } break; case OPT_COSINE: /* they want to use the cosine metric */ args->sopts |= INDEX_SEARCH_COSINE_RANK; /* arrange for weights to be loaded into memory */ args->lopts |= INDEX_LOAD_DOCMAP_CACHE; args->lopt.docmap_cache |= DOCMAP_CACHE_WEIGHT; break; default: /* shouldn't happen */ assert(0); } } ind = getlongopt_optind(parser) + 1; getlongopt_delete(parser); if (err || ret == GETLONGOPT_END) { /* succeeded, do nothing */ } else { if (ret == GETLONGOPT_UNKNOWN) { fprintf(stderr, "unknown option '%s'\n", argv[ind]); } else if (ret == GETLONGOPT_MISSING_ARG) { fprintf(stderr, "missing argument to option '%s'\n", argv[ind]); } else { fprintf(stderr, "unexpected error parsing options (around '%s')\n", argv[ind]); } free(args); return NULL; } /* remaining arguments should be index */ while (!err && (ind < (unsigned int) argc)) { if (!args->idx) { if (!(args->idx = load_index(argv[ind], args->memory, args->lopts, &args->lopt))) { fprintf(output, "couldn't load index from '%s': %s\n", argv[ind], strerror(errno)); err = quiet = 1; } } else { fprintf(output, "index already loaded\n"); err = 1; quiet = 0; } ind++; } /* set run_id if they haven't */ if (!err && !args->run_id && !(args->run_id = str_dup(PACKAGE))) { fprintf(output, "couldn't set default run_id: %s\n", strerror(errno)); err = quiet = 1; } /* set number of results if they haven't */ if (!err && !args->numresults) { args->numresults = 1000; } /* set number of accumulators if they haven't */ if (!err && !args->numaccumulators) { args->numaccumulators = ACCUMULATOR_LIMIT; } /* check that they've given a topic file */ if (!err && !args->topic_files) { fprintf(output, "no topic files given\n"); err = 1; } /* check that they've given an index */ if (!err && !args->idx) { fprintf(output, "no index given\n"); err = 1; } if (!(args->title || args->descr || args->narr)) { /* title only run is default */ args->title = 1; } if (err) { if (!quiet) { fprintf(output, "\n"); print_usage(output, *argv); } free_args(args); return NULL; } else { return args; } }
int args_parse(args_parse_state *state, int argc, char **argv, args_option *opts) { char *arg; const char *optarg; args_option *opt; int retval; if(state->idx == 0) state->idx++; if(state->idx >= argc) return -1; state->arg = arg = argv[state->idx]; if(state->no_more_options || strlen(arg) <= 1 || arg[0] != '-') { state->idx++; return '_'; } if(strcmp(arg, "--") == 0) { state->idx++; state->no_more_options = 1; return args_parse(state, argc, argv, opts); } if(strncmp(arg, "--", 2) == 0) { state->idx++; optarg = NULL; opt = getlongopt(opts, arg + 2, &optarg); if(opt == NULL) return '?'; if(opt->arg_name == NULL) return opt->code; else { if(optarg != NULL) state->arg = (char *)optarg; else { if(state->idx >= argc) return ':'; state->arg = argv[state->idx]; state->idx++; } return opt->code; } } state->off++; snprintf(state->short_arg, 3, "-%c", arg[state->off]); state->arg = state->short_arg; opt = getshortopt(opts, arg[state->off]); if(opt == NULL) { retval = '?'; goto ret; } if(opt->arg_name == NULL) { retval = opt->code; goto ret; } if(state->idx + 1 == argc || state->off + 1 != strlen(arg)) { retval = ':'; goto ret; } state->idx++; state->arg = argv[state->idx]; retval = opt->code; ret: if(state->off + 1 == strlen(arg)) { state->off = 0; state->idx++; } return retval; }