aboutsummaryrefslogtreecommitdiff
path: root/android_popt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'android_popt.cpp')
-rw-r--r--android_popt.cpp112
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;
+}