|
24 | 24 | * |
25 | 25 | */ |
26 | 26 |
|
27 | | -#include <popt.h> |
28 | | - |
29 | 27 | #include "lib/framework/frame.h" |
30 | 28 | #include "lib/netplay/netplay.h" |
31 | 29 |
|
|
43 | 41 | //! Let the end user into debug mode.... |
44 | 42 | BOOL bAllowDebugMode = false; |
45 | 43 |
|
| 44 | +////// |
| 45 | +// Our fine replacement for the popt abomination follows |
| 46 | + |
| 47 | +#define POPT_ARG_STRING true |
| 48 | +#define POPT_ARG_NONE false |
| 49 | +#define POPT_ERROR_BADOPT -1 |
| 50 | +#define POPT_ARGFLAG_DOC_HIDDEN 0 |
| 51 | + |
| 52 | +struct poptOption |
| 53 | +{ |
| 54 | + const char *string; |
| 55 | + char short_form; |
| 56 | + bool argument; |
| 57 | + void *nullptr; // unused |
| 58 | + int enumeration; |
| 59 | + const char *descrip; |
| 60 | + const char *argDescrip; |
| 61 | +}; |
| 62 | + |
| 63 | +typedef struct _poptContext |
| 64 | +{ |
| 65 | + int argc, current, size; |
| 66 | + const char **argv; |
| 67 | + const char *parameter; |
| 68 | + const char *bad; |
| 69 | + const struct poptOption *table; |
| 70 | +} *poptContext; |
| 71 | + |
| 72 | +static void poptPrintUsage(poptContext ctx, FILE *output, WZ_DECL_UNUSED int unused) |
| 73 | +{ |
| 74 | + // TODO ? |
| 75 | +} |
| 76 | + |
| 77 | +static void poptPrintHelp(poptContext ctx, FILE *output, WZ_DECL_UNUSED int unused) |
| 78 | +{ |
| 79 | + int i; |
| 80 | + |
| 81 | + fprintf(output, "Usage: %s [OPTION...]\n", ctx->argv[0]); |
| 82 | + for (i = 0; i < ctx->size; i++) |
| 83 | + { |
| 84 | + char txt[128]; |
| 85 | + |
| 86 | + if (ctx->table[i].short_form != '\0') |
| 87 | + { |
| 88 | + ssprintf(txt, " -%c, --%s", ctx->table[i].short_form, ctx->table[i].string); |
| 89 | + } |
| 90 | + else |
| 91 | + { |
| 92 | + ssprintf(txt, " --%s", ctx->table[i].string); |
| 93 | + } |
| 94 | + |
| 95 | + if (ctx->table[i].argument) |
| 96 | + { |
| 97 | + sstrcat(txt, "="); |
| 98 | + sstrcat(txt, ctx->table[i].argDescrip); |
| 99 | + } |
| 100 | + |
| 101 | + fprintf(output, "%-40s", txt); |
| 102 | + if (ctx->table[i].descrip) |
| 103 | + { |
| 104 | + fprintf(output, "%s", ctx->table[i].descrip); |
| 105 | + } |
| 106 | + fprintf(output, "\n"); |
| 107 | + } |
| 108 | +} |
| 109 | + |
| 110 | +static void poptFreeContext(WZ_DECL_UNUSED poptContext ctx) |
| 111 | +{ |
| 112 | + // Nothing! |
| 113 | +} |
| 114 | + |
| 115 | +static const char *poptBadOption(poptContext ctx, WZ_DECL_UNUSED int unused) |
| 116 | +{ |
| 117 | + return ctx->bad; |
| 118 | +} |
| 119 | + |
| 120 | +static const char *poptGetOptArg(poptContext ctx) |
| 121 | +{ |
| 122 | + return ctx->parameter; |
| 123 | +} |
| 124 | + |
| 125 | +static int poptGetNextOpt(poptContext ctx) |
| 126 | +{ |
| 127 | + static char match[PATH_MAX]; // static for bad function |
| 128 | + static char parameter[PATH_MAX]; // static for arg function |
| 129 | + char *pparam; |
| 130 | + int i; |
| 131 | + |
| 132 | + ctx->bad = NULL; |
| 133 | + ctx->parameter = NULL; |
| 134 | + parameter[0] = '\0'; |
| 135 | + match[0] = '\0'; |
| 136 | + |
| 137 | + if (ctx->current >= ctx->argc) // counts from 1 |
| 138 | + { |
| 139 | + return 0; |
| 140 | + } |
| 141 | + |
| 142 | + sstrcpy(match, ctx->argv[ctx->current]); |
| 143 | + ctx->current++; |
| 144 | + pparam = strrchr(match, '='); |
| 145 | + if (pparam) // option's got a parameter |
| 146 | + { |
| 147 | + *pparam++ = '\0'; // split option from parameter and increment past '=' |
| 148 | + if (pparam[0] == '"') // found scary quotes |
| 149 | + { |
| 150 | + pparam++; // skip start quote |
| 151 | + sstrcpy(parameter, pparam); // copy first parameter |
| 152 | + if (!strrchr(pparam, '"')) // if no end quote, then find it |
| 153 | + { |
| 154 | + while (!strrchr(parameter, '"') && ctx->current < ctx->argc) |
| 155 | + { |
| 156 | + sstrcat(parameter, " "); // insert space |
| 157 | + sstrcat(parameter, ctx->argv[ctx->current]); |
| 158 | + ctx->current++; // next part, please! |
| 159 | + } |
| 160 | + } |
| 161 | + if (strrchr(parameter, '"')) // its not an else for above! |
| 162 | + { |
| 163 | + *strrchr(parameter, '"') = '\0'; // remove end qoute |
| 164 | + } |
| 165 | + } |
| 166 | + else |
| 167 | + { |
| 168 | + sstrcpy(parameter, pparam); // copy parameter |
| 169 | + } |
| 170 | + } |
| 171 | + |
| 172 | + for (i = 0; i < ctx->size; i++) |
| 173 | + { |
| 174 | + char sshort[3]; |
| 175 | + char slong[64]; |
| 176 | + |
| 177 | + ssprintf(sshort, "-%c", ctx->table[i].short_form); |
| 178 | + ssprintf(slong, "--%s", ctx->table[i].string); |
| 179 | + if ((strcmp(sshort, match) == 0 && ctx->table[i].short_form != '\0') || strcmp(slong, match) == 0) |
| 180 | + { |
| 181 | + if (ctx->table[i].argument && pparam) |
| 182 | + { |
| 183 | + ctx->parameter = parameter; |
| 184 | + } |
| 185 | + return ctx->table[i].enumeration; |
| 186 | + } |
| 187 | + } |
| 188 | + ctx->bad = match; |
| 189 | + ctx->current++; |
| 190 | + return POPT_ERROR_BADOPT; |
| 191 | +} |
| 192 | + |
| 193 | +static poptContext poptGetContext(WZ_DECL_UNUSED void *unused, int argc, const char **argv, const struct poptOption *table, WZ_DECL_UNUSED int none) |
| 194 | +{ |
| 195 | + static struct _poptContext ctx; |
| 196 | + |
| 197 | + ctx.argc = argc; |
| 198 | + ctx.argv = argv; |
| 199 | + ctx.table = table; |
| 200 | + ctx.current = 1; |
| 201 | + ctx.parameter = NULL; |
| 202 | + |
| 203 | + for (ctx.size = 0; table[ctx.size].string; ctx.size++) ; // count table size |
| 204 | + |
| 205 | + return &ctx; |
| 206 | +} |
| 207 | + |
| 208 | + |
46 | 209 | typedef enum |
47 | 210 | { |
48 | 211 | // We don't want to use zero, so start at one (1) |
@@ -79,8 +242,8 @@ static const struct poptOption* getOptionsTable(void) |
79 | 242 | static const struct poptOption optionsTable[] = |
80 | 243 | { |
81 | 244 | { "cheat", '\0', POPT_ARG_NONE, NULL, CLI_CHEAT, N_("Run in cheat mode"), NULL }, |
82 | | - { "datadir", '\0', POPT_ARG_STRING, NULL, CLI_DATADIR, N_("Set default data directory"), N_("data directory") }, |
83 | 245 | { "configdir", '\0', POPT_ARG_STRING, NULL, CLI_CONFIGDIR, N_("Set configuration directory"), N_("configuration directory") }, |
| 246 | + { "datadir", '\0', POPT_ARG_STRING, NULL, CLI_DATADIR, N_("Set default data directory"), N_("data directory") }, |
84 | 247 | { "debug", '\0', POPT_ARG_STRING, NULL, CLI_DEBUG, N_("Show debug for given level"), N_("debug level") }, |
85 | 248 | { "debugfile", '\0', POPT_ARG_STRING, NULL, CLI_DEBUGFILE, N_("Log debug output to file"), N_("file") }, |
86 | 249 | { "flush-debug-stderr", '\0', POPT_ARG_NONE, NULL, CLI_FLUSHDEBUGSTDERR, N_("Flush all debug output written to stderr"), NULL }, |
|
0 commit comments