• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     // getopt_long expects the last element to be null
33     // so allocate count + 1
34     struct option *long_options = (struct option *)
35             calloc(count + 1, sizeof(struct option));
36     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 
poptFreeContext(poptContext con)72 poptContext poptFreeContext(poptContext con) {
73     free(con->long_options);
74     free(con);
75     return 0;
76 }
77 
poptResetContext(poptContext con)78 void poptResetContext(poptContext con) {
79     optind = 1;
80 }
81 
poptSetOtherOptionHelp(poptContext con,const char * text)82 void poptSetOtherOptionHelp(poptContext con, const char *text) {
83     con->otherHelp = text;
84 }
85 
poptPrintUsage(poptContext con,FILE * fp,int flags)86 void 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 
poptGetNextOpt(poptContext con)96 int 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
103     if (res <= 0 || res == '?' || i == -1) {
104         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 
poptGetArg(poptContext con)120 const 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 }
127