diff options
Diffstat (limited to 'android_popt.cpp')
-rw-r--r-- | android_popt.cpp | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/android_popt.cpp b/android_popt.cpp new file mode 100644 index 0000000..03d8751 --- /dev/null +++ b/android_popt.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <popt.h> + +// #define LOCAL_DEBUG + +/* + * popt has been deprecated for some time, and is replaced by GNOME's glib + * option parser. Instead of pulling in either of those dependencies, this + * stub implements just enough of popt to get things working. + */ + +poptContext poptGetContext(const char *, int argc, const char **argv, + const struct poptOption *options, unsigned int) { + // Convert into getopt format, sanity checking our limited + // capabilities along the way + int count = 0; + for (; options[count].longName; count++) { + } + + struct option *long_options = (struct option *) + calloc(count, sizeof(struct option)); + for (int i = 0; options[i].longName; i++) { + long_options[i].name = options[i].longName; + long_options[i].flag = 0; + + if (!options[i].val) { + fprintf(stderr, __FILE__ ": val required\n"); + abort(); + } + long_options[i].val = options[i].val; + + switch (options[i].argInfo) { + case POPT_ARG_NONE: + long_options[i].has_arg = no_argument; + break; + case POPT_ARG_STRING: + case POPT_ARG_INT: + case POPT_ARG_LONG: + if (!options[i].arg) { + fprintf(stderr, __FILE__ ": arg required\n"); + abort(); + } + long_options[i].has_arg = required_argument; + break; + default: + fprintf(stderr, __FILE__ ": unsupported argInfo\n"); + abort(); + } + } + + poptContext con = (poptContext) calloc(1, sizeof(struct _poptContext)); + con->argc = argc; + con->argv = argv; + con->options = options; + con->long_options = long_options; + return con; +} + +poptContext poptFreeContext(poptContext con) { + free(con->long_options); + free(con); + return 0; +} + +void poptPrintUsage(poptContext con, FILE *fp, int) { + fprintf(fp, "USAGE: %s %s\n", con->argv[0], con->otherHelp); + int i = 0; + for (; con->options[i].longName; i++) { + fprintf(fp, "\t--%s\t%s\n", con->options[i].longName, + con->options[i].descrip); + } + fprintf(fp, "\n"); +} + +int poptGetNextOpt(poptContext con) { + int i = -1; + int res = getopt_long(con->argc, (char *const *) con->argv, "", + con->long_options, &i); +#ifdef LOCAL_DEBUG + fprintf(stderr, "getopt_long()=%c\n", res); +#endif + if (res == 0 || res == '?') { + return -1; + } + + // Copy over found argument value + switch (con->options[i].argInfo) { + case POPT_ARG_STRING: + *((char**) con->options[i].arg) = strdup(optarg); + break; + case POPT_ARG_INT: + *((int*) con->options[i].arg) = atoi(optarg); + break; + case POPT_ARG_LONG: + *((long*) con->options[i].arg) = atol(optarg); + break; + } + + return res; +} |