1 /*
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
14 #include <popt.h>
15
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
poptGetContext(const char * name,int argc,const char ** argv,const struct poptOption * options,unsigned int flags)24 poptContext 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
32 struct option *long_options = (struct option *)
33 calloc(count, sizeof(struct option));
34 for (int i = 0; options[i].longName; i++) {
35 long_options[i].name = options[i].longName;
36 long_options[i].flag = 0;
37
38 if (!options[i].val) {
39 fprintf(stderr, __FILE__ ": val required\n");
40 abort();
41 }
42 long_options[i].val = options[i].val;
43
44 switch (options[i].argInfo) {
45 case POPT_ARG_NONE:
46 long_options[i].has_arg = no_argument;
47 break;
48 case POPT_ARG_STRING:
49 case POPT_ARG_INT:
50 if (!options[i].arg) {
51 fprintf(stderr, __FILE__ ": arg required\n");
52 abort();
53 }
54 long_options[i].has_arg = required_argument;
55 break;
56 default:
57 fprintf(stderr, __FILE__ ": unsupported argInfo\n");
58 abort();
59 }
60 }
61
62 poptContext con = (poptContext) calloc(1, sizeof(struct _poptContext));
63 con->argc = argc;
64 con->argv = argv;
65 con->options = options;
66 con->long_options = long_options;
67 return con;
68 }
69
poptFreeContext(poptContext con)70 poptContext poptFreeContext(poptContext con) {
71 free(con->long_options);
72 free(con);
73 return 0;
74 }
75
poptResetContext(poptContext con)76 void poptResetContext(poptContext con) {
77 optind = 1;
78 }
79
poptSetOtherOptionHelp(poptContext con,const char * text)80 void poptSetOtherOptionHelp(poptContext con, const char *text) {
81 con->otherHelp = text;
82 }
83
poptPrintUsage(poptContext con,FILE * fp,int flags)84 void poptPrintUsage(poptContext con, FILE *fp, int flags) {
85 fprintf(fp, "USAGE: %s %s\n", con->argv[0], con->otherHelp);
86 int i = 0;
87 for (; con->options[i].longName; i++) {
88 fprintf(fp, "\t--%s\t%s\n", con->options[i].longName,
89 con->options[i].descrip);
90 }
91 fprintf(fp, "\n");
92 }
93
poptGetNextOpt(poptContext con)94 int poptGetNextOpt(poptContext con) {
95 int i = -1;
96 int res = getopt_long(con->argc, (char *const *) con->argv, "",
97 con->long_options, &i);
98 #ifdef LOCAL_DEBUG
99 fprintf(stderr, "getopt_long()=%c\n", res);
100 #endif
101 if (res <= 0 || res == '?' || i == -1) {
102 return -1;
103 }
104
105 // Copy over found argument value
106 switch (con->options[i].argInfo) {
107 case POPT_ARG_STRING:
108 *((char**) con->options[i].arg) = strdup(optarg);
109 break;
110 case POPT_ARG_INT:
111 *((int*) con->options[i].arg) = atoi(optarg);
112 break;
113 }
114
115 return res;
116 }
117
poptGetArg(poptContext con)118 const char *poptGetArg(poptContext con) {
119 const char *res = con->argv[optind++];
120 #ifdef LOCAL_DEBUG
121 fprintf(stderr, "poptGetArg()=%s\n", res);
122 #endif
123 return res;
124 }
125