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