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