blob: 98b7f9969d279cba63bbde63359fe654d9866633 [file] [log] [blame]
Jeff Sharkey873988a2015-02-21 13:30:14 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
Greg Hartman08372d72015-02-23 20:04:52 -080014#include <popt.h>
Jeff Sharkey873988a2015-02-21 13:30:14 -080015
16// #define LOCAL_DEBUG
17
18/*
19 * popt has been deprecated for some time, and is replaced by GNOME's glib
20 * option parser. Instead of pulling in either of those dependencies, this
21 * stub implements just enough of popt to get things working.
22 */
23
24poptContext poptGetContext(const char *name, int argc, const char **argv,
25 const struct poptOption *options, unsigned int flags) {
26 // Convert into getopt format, sanity checking our limited
27 // capabilities along the way
28 int count = 0;
29 for (; options[count].longName; count++) {
30 }
31
bohu74041442019-02-26 15:34:08 -080032 // getopt_long expects the last element to be null
33 // so allocate count + 1
Jeff Sharkey873988a2015-02-21 13:30:14 -080034 struct option *long_options = (struct option *)
bohu74041442019-02-26 15:34:08 -080035 calloc(count + 1, sizeof(struct option));
Jeff Sharkey873988a2015-02-21 13:30:14 -080036 for (int i = 0; options[i].longName; i++) {
37 long_options[i].name = options[i].longName;
38 long_options[i].flag = 0;
39
40 if (!options[i].val) {
41 fprintf(stderr, __FILE__ ": val required\n");
42 abort();
43 }
44 long_options[i].val = options[i].val;
45
46 switch (options[i].argInfo) {
47 case POPT_ARG_NONE:
48 long_options[i].has_arg = no_argument;
49 break;
50 case POPT_ARG_STRING:
51 case POPT_ARG_INT:
52 if (!options[i].arg) {
53 fprintf(stderr, __FILE__ ": arg required\n");
54 abort();
55 }
56 long_options[i].has_arg = required_argument;
57 break;
58 default:
59 fprintf(stderr, __FILE__ ": unsupported argInfo\n");
60 abort();
61 }
62 }
63
64 poptContext con = (poptContext) calloc(1, sizeof(struct _poptContext));
65 con->argc = argc;
66 con->argv = argv;
67 con->options = options;
68 con->long_options = long_options;
69 return con;
70}
71
72poptContext poptFreeContext(poptContext con) {
73 free(con->long_options);
74 free(con);
75 return 0;
76}
77
78void poptResetContext(poptContext con) {
79 optind = 1;
80}
81
82void poptSetOtherOptionHelp(poptContext con, const char *text) {
83 con->otherHelp = text;
84}
85
86void poptPrintUsage(poptContext con, FILE *fp, int flags) {
87 fprintf(fp, "USAGE: %s %s\n", con->argv[0], con->otherHelp);
88 int i = 0;
89 for (; con->options[i].longName; i++) {
90 fprintf(fp, "\t--%s\t%s\n", con->options[i].longName,
91 con->options[i].descrip);
92 }
93 fprintf(fp, "\n");
94}
95
96int poptGetNextOpt(poptContext con) {
97 int i = -1;
98 int res = getopt_long(con->argc, (char *const *) con->argv, "",
99 con->long_options, &i);
100#ifdef LOCAL_DEBUG
101 fprintf(stderr, "getopt_long()=%c\n", res);
102#endif
bohu69e46b92017-08-01 11:40:14 -0700103 if (res <= 0 || res == '?' || i == -1) {
Jeff Sharkey873988a2015-02-21 13:30:14 -0800104 return -1;
105 }
106
107 // Copy over found argument value
108 switch (con->options[i].argInfo) {
109 case POPT_ARG_STRING:
110 *((char**) con->options[i].arg) = strdup(optarg);
111 break;
112 case POPT_ARG_INT:
113 *((int*) con->options[i].arg) = atoi(optarg);
114 break;
115 }
116
117 return res;
118}
119
120const char *poptGetArg(poptContext con) {
121 const char *res = con->argv[optind++];
122#ifdef LOCAL_DEBUG
123 fprintf(stderr, "poptGetArg()=%s\n", res);
124#endif
125 return res;
126}