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 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 70 poptContext poptFreeContext(poptContext con) { 71 free(con->long_options); 72 free(con); 73 return 0; 74 } 75 76 void poptResetContext(poptContext con) { 77 optind = 1; 78 } 79 80 void poptSetOtherOptionHelp(poptContext con, const char *text) { 81 con->otherHelp = text; 82 } 83 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 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 == '?') { 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 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