comparison th_args.c @ 81:69aed051f84d

Synced th-libs.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 20 Apr 2009 22:02:37 +0300
parents 323c98360d8b
children 9ad157feb99a
comparison
equal deleted inserted replaced
80:335b5a74c22e 81:69aed051f84d
126 126
127 /* Check if option requires an argument 127 /* Check if option requires an argument
128 */ 128 */
129 static BOOL th_args_check_arg(optarg_t *o, char *optArg) 129 static BOOL th_args_check_arg(optarg_t *o, char *optArg)
130 { 130 {
131 if ((o->optFlags & OPT_ARGMASK) == OPT_ARGREQ && optArg == NULL) { 131 if ((o->optFlags & OPT_ARGMASK) == OPT_ARGREQ && optArg == NULL) {
132 if (o->optShort != 0 && o->optLong != NULL) { 132 if (o->optShort != 0 && o->optLong != NULL) {
133 THERR("Option '-%c ARG' (--%s=ARG) requires an argument!\n", 133 THERR("Option '-%c ARG' (--%s=ARG) requires an argument!\n",
134 o->optShort, o->optLong); 134 o->optShort, o->optLong);
135 } else if (o->optShort != 0) { 135 } else if (o->optShort != 0) {
136 THERR("Option '-%c ARG' requires an argument!\n", o->optShort); 136 THERR("Option '-%c ARG' requires an argument!\n", o->optShort);
137 } else if (o->optLong != NULL) { 137 } else if (o->optLong != NULL) {
138 THERR("Option --%s=ARG requires an argument!\n", o->optLong); 138 THERR("Option --%s=ARG requires an argument!\n", o->optLong);
139 } 139 }
140 140
141 return FALSE; 141 return FALSE;
142 } else 142 } else
143 return TRUE; 143 return TRUE;
144 144
145 } 145 }
146 146
147 147
148 /* Handle short options 148 /* Handle short options
149 */ 149 */
150 static BOOL th_args_process_short(char *currArg, int *newArgIndex, 150 static BOOL th_args_process_short(char *currArg, int *newArgIndex,
151 BOOL *wasGiven, int argc, char *argv[], 151 BOOL *wasGiven, int argc, char *argv[],
152 optarg_t optList[], int optListN, 152 optarg_t optList[], int optListN,
153 BOOL (*handleOpt)(int, char *, char *)) 153 BOOL (*handleOpt)(int, char *, char *))
154 { 154 {
155 char *tmpArg = currArg, *optArg; 155 char *tmpArg = currArg, *optArg;
156 int optN; 156 int optN;
157 BOOL isFound; 157 BOOL isFound;
158 158
159 /* Short options can be combined: -a -b -c == -abc */ 159 /* Short options can be combined: -a -b -c == -abc */
160 while (*tmpArg) { 160 while (*tmpArg) {
161 161
162 for (optN = 0, isFound = FALSE; (optN < optListN) && !isFound; optN++) 162 for (optN = 0, isFound = FALSE; (optN < optListN) && !isFound; optN++)
163 if (*tmpArg == optList[optN].optShort) { 163 if (*tmpArg == optList[optN].optShort) {
164 /* Get possible option argument, if needed */ 164 /* Get possible option argument, if needed */
165 if ((optList[optN].optFlags & OPT_ARGMASK) != 0 && (++(*newArgIndex) < argc)) 165 if ((optList[optN].optFlags & OPT_ARGMASK) != 0 && (++(*newArgIndex) < argc))
166 optArg = argv[*newArgIndex]; 166 optArg = argv[*newArgIndex];
167 else 167 else
168 optArg = NULL; 168 optArg = NULL;
169 169
170 /* Check if option argument is required */ 170 /* Check if option argument is required */
171 if (!th_args_check_arg(&optList[optN], optArg)) 171 if (!th_args_check_arg(&optList[optN], optArg))
172 return FALSE; 172 return FALSE;
173 else { 173 else {
174 char tmpStr[2] = { 0, 0 }; 174 char tmpStr[2] = { 0, 0 };
175 175
176 /* Option was given succesfully, try to handle it */ 176 /* Option was given succesfully, try to handle it */
177 wasGiven[optN] = TRUE; 177 wasGiven[optN] = TRUE;
178 178
179 tmpStr[0] = *tmpArg; 179 tmpStr[0] = *tmpArg;
180 180
181 if (!handleOpt(optList[optN].optID, optArg, tmpStr)) 181 if (!handleOpt(optList[optN].optID, optArg, tmpStr))
182 return FALSE; 182 return FALSE;
183 } 183 }
184 184
185 isFound = TRUE; 185 isFound = TRUE;
186 } 186 }
187 187
188 if (!isFound) { 188 if (!isFound) {
189 THERR("Unknown short option '%c' in argument '-%s'\n", 189 THERR("Unknown short option '%c' in argument '-%s'\n",
190 *tmpArg, currArg); 190 *tmpArg, currArg);
191 return FALSE; 191 return FALSE;
192 } 192 }
193 193
194 tmpArg++; 194 tmpArg++;
195 } 195 }
196 196
197 return TRUE; 197 return TRUE;
198 } 198 }
199 199
200 200
201 /* Handle long options 201 /* Handle long options
202 */ 202 */
203 static BOOL th_args_process_long(char *currArg, int *newArgIndex, 203 static BOOL th_args_process_long(char *currArg, int *newArgIndex,
204 BOOL *wasGiven, int argc, char *argv[], 204 BOOL *wasGiven, int argc, char *argv[],
205 optarg_t optList[], int optListN, 205 optarg_t optList[], int optListN,
206 BOOL (*handleOpt)(int, char *, char *)) 206 BOOL (*handleOpt)(int, char *, char *))
207 { 207 {
208 int optN, optLen, i; 208 int optN, optLen, i;
209 char *optArg; 209 char *optArg;
210 210
211 (void) argc; (void) argv; (void) newArgIndex; 211 (void) argc; (void) argv; (void) newArgIndex;
212 212
213 /* Long option */ 213 /* Long option */
214 for (optN = -1, optLen = i = 0; (i < optListN) && (optN < 0); i++) 214 for (optN = -1, optLen = i = 0; (i < optListN) && (optN < 0); i++)
215 if (optList[i].optLong) { 215 if (optList[i].optLong) {
216 optLen = strlen(optList[i].optLong); 216 optLen = strlen(optList[i].optLong);
217 if (strncmp(currArg, optList[i].optLong, optLen) == 0) 217 if (strncmp(currArg, optList[i].optLong, optLen) == 0)
218 optN = i; 218 optN = i;
219 } 219 }
220 220
221 /* Get possible option argument, if needed */ 221 /* Get possible option argument, if needed */
222 if (optN >= 0) { 222 if (optN >= 0) {
223 if ((optList[optN].optFlags & OPT_ARGMASK) != 0) { 223 if ((optList[optN].optFlags & OPT_ARGMASK) != 0) {
224 if (currArg[optLen] == '=') 224 if (currArg[optLen] == '=')
225 optArg = &currArg[optLen + 1]; 225 optArg = &currArg[optLen + 1];
226 else 226 else
227 optArg = NULL; 227 optArg = NULL;
228 } else 228 } else
229 optArg = NULL; 229 optArg = NULL;
230 230
231 /* Check if option argument is required */ 231 /* Check if option argument is required */
232 if (!th_args_check_arg(&optList[optN], optArg)) 232 if (!th_args_check_arg(&optList[optN], optArg))
233 return FALSE; 233 return FALSE;
234 else { 234 else {
235 /* Option was given succesfully, try to handle it */ 235 /* Option was given succesfully, try to handle it */
236 wasGiven[optN] = TRUE; 236 wasGiven[optN] = TRUE;
237 if (!handleOpt(optList[optN].optID, optArg, currArg)) 237 if (!handleOpt(optList[optN].optID, optArg, currArg))
238 return FALSE; 238 return FALSE;
239 } 239 }
240 } else { 240 } else {
241 THERR("Unknown long option '--%s'\n", currArg); 241 THERR("Unknown long option '--%s'\n", currArg);
242 return FALSE; 242 return FALSE;
243 } 243 }
244 244
245 return TRUE; 245 return TRUE;
246 } 246 }
247 247
248 248
249 /* Process arguments, handling short and long options by 249 /* Process arguments, handling short and long options by
250 * calling the given callback functions. 250 * calling the given callback functions.
251 */ 251 */
252 BOOL th_args_process(int argc, char *argv[], 252 BOOL th_args_process(int argc, char *argv[],
253 optarg_t optList[], int optListN, 253 optarg_t optList[], int optListN,
254 BOOL (*handleOpt) (int, char *, char *), 254 BOOL (*handleOpt) (int, char *, char *),
255 BOOL (*handleNonOption) (char *), BOOL bailOut) 255 BOOL (*handleNonOption) (char *), BOOL bailOut)
256 { 256 {
257 BOOL endOptions, optionsOK; 257 BOOL endOptions, optionsOK;
258 int argIndex, newArgIndex, i; 258 int argIndex, newArgIndex, i;
259 char *currArg; 259 char *currArg;
260 BOOL *wasGiven; 260 BOOL *wasGiven;
261 261
262 /* Allocate wasGiven */ 262 /* Allocate wasGiven */
263 wasGiven = (BOOL *) th_calloc(optListN, sizeof(BOOL)); 263 wasGiven = (BOOL *) th_calloc(optListN, sizeof(BOOL));
264 if (!wasGiven) { 264 if (!wasGiven) {
265 THERR("FATAL ERROR! Could not allocate wasGiven in th_args_process()!\n"); 265 THERR("FATAL ERROR! Could not allocate wasGiven in th_args_process()!\n");
266 exit(128); 266 exit(128);
267 } 267 }
268 268
269 /* Parse arguments */ 269 /* Parse arguments */
270 argIndex = 1; 270 argIndex = 1;
271 optionsOK = TRUE; 271 optionsOK = TRUE;
272 endOptions = FALSE; 272 endOptions = FALSE;
273 while (argIndex < argc) { 273 while (argIndex < argc) {
274 currArg = argv[argIndex]; 274 currArg = argv[argIndex];
275 if ((currArg[0] == '-') && !endOptions) { 275 if ((currArg[0] == '-') && !endOptions) {
276 newArgIndex = argIndex; 276 newArgIndex = argIndex;
277 currArg++; 277 currArg++;
278 if (*currArg == '-') { 278 if (*currArg == '-') {
279 /* Check for "--", which ends the options-list */ 279 /* Check for "--", which ends the options-list */
280 currArg++; 280 currArg++;
281 if (*currArg == 0) { 281 if (*currArg == 0) {
282 endOptions = TRUE; 282 endOptions = TRUE;
283 continue; 283 continue;
284 } 284 }
285 285
286 /* Long options */ 286 /* Long options */
287 if (!th_args_process_long(currArg, &newArgIndex, 287 if (!th_args_process_long(currArg, &newArgIndex,
288 wasGiven, argc, argv, optList, optListN, 288 wasGiven, argc, argv, optList, optListN,
289 handleOpt)) 289 handleOpt))
290 optionsOK = FALSE; 290 optionsOK = FALSE;
291 } else { 291 } else {
292 /* Short options */ 292 /* Short options */
293 if (!th_args_process_short(currArg, &newArgIndex, 293 if (!th_args_process_short(currArg, &newArgIndex,
294 wasGiven, argc, argv, optList, optListN, 294 wasGiven, argc, argv, optList, optListN,
295 handleOpt)) 295 handleOpt))
296 optionsOK = FALSE; 296 optionsOK = FALSE;
297 } 297 }
298 298
299 argIndex = newArgIndex; 299 argIndex = newArgIndex;
300 } else { 300 } else {
301 /* Was not option argument */ 301 /* Was not option argument */
302 if (!handleNonOption || (handleNonOption && !handleNonOption(currArg))) { 302 if (handleNonOption == NULL || (handleNonOption != NULL && !handleNonOption(currArg))) {
303 THERR("Invalid argument '%s'\n", currArg); 303 THERR("Invalid argument '%s'\n", currArg);
304 optionsOK = FALSE; 304 optionsOK = FALSE;
305 } 305 }
306 } 306 }
307 307
308 /* Check if we bail out on invalid argument */ 308 /* Check if we bail out on invalid argument */
309 if (!optionsOK && bailOut) { 309 if (!optionsOK && bailOut) {
310 th_free(wasGiven); 310 th_free(wasGiven);
311 return FALSE; 311 return FALSE;
312 } 312 }
313 313
314 argIndex++; 314 argIndex++;
315 } 315 }
316 316
317 /* Check wasGiven by isRequired */ 317 /* Check wasGiven by isRequired */
318 for (i = 0; i < optListN; i++) 318 for (i = 0; i < optListN; i++)
319 if ((optList[i].optFlags & OPT_REQUIRED) != 0 && !wasGiven[i]) { 319 if ((optList[i].optFlags & OPT_REQUIRED) != 0 && !wasGiven[i]) {
320 THERR("Option -%s (--%s) is required.\n", 320 THERR("Option -%s (--%s) is required.\n",
321 optList[i].optShort, optList[i].optLong); 321 optList[i].optShort, optList[i].optLong);
322 322
323 optionsOK = FALSE; 323 optionsOK = FALSE;
324 if (bailOut) break; 324 if (bailOut) break;
325 } 325 }
326 326
327 th_free(wasGiven); 327 th_free(wasGiven);
328 return optionsOK; 328 return optionsOK;
329 } 329 }
330 330
331 331
332 /* Print help for commandline arguments/options 332 /* Print help for commandline arguments/options
333 */ 333 */
334 void th_args_help(FILE * outFile, 334 void th_args_help(FILE * outFile,
335 optarg_t optList[], int optListN, 335 optarg_t optList[], int optListN,
336 char * progName, char * progUsage) 336 char * progName, char * progUsage)
337 { 337 {
338 int i, nrequired; 338 int i, nrequired;
339 339
340 fprintf(outFile, 340 fprintf(outFile,
341 "\n%s v%s (%s)\n" 341 "\n%s v%s (%s)\n"
342 "%s\n" 342 "%s\n"
343 "%s\n" 343 "%s\n"
344 "Usage: %s %s\n", 344 "Usage: %s %s\n",
345 th_prog_name, th_prog_version, th_prog_fullname, 345 th_prog_name, th_prog_version, th_prog_fullname,
346 th_prog_author, th_prog_license, progName, progUsage); 346 th_prog_author, th_prog_license, progName, progUsage);
347 347
348 348
349 for (i = nrequired = 0; i < optListN; i++) { 349 for (i = nrequired = 0; i < optListN; i++) {
350 optarg_t *o = &optList[i]; 350 optarg_t *o = &optList[i];
351 351
352 /* Print short option */ 352 /* Print short option */
353 if (o->optShort != 0) 353 if (o->optShort != 0)
354 fprintf(outFile, " -%c, ", o->optShort); 354 fprintf(outFile, " -%c, ", o->optShort);
355 else 355 else
356 fprintf(outFile, " "); 356 fprintf(outFile, " ");
357 357
358 /* Print long option */ 358 /* Print long option */
359 if (o->optLong) { 359 if (o->optLong) {
360 char tmpStr[64], *p; 360 char tmpStr[64], *p;
361 361
362 if ((o->optFlags & OPT_ARGMASK) == OPT_ARGOPT) { 362 if ((o->optFlags & OPT_ARGMASK) == OPT_ARGOPT) {
363 snprintf(tmpStr, sizeof(tmpStr), "%s[=ARG]", optList[i].optLong); 363 snprintf(tmpStr, sizeof(tmpStr), "%s[=ARG]", optList[i].optLong);
364 p = tmpStr; 364 p = tmpStr;
365 } else if ((o->optFlags & OPT_ARGMASK) == OPT_ARGREQ) { 365 } else if ((o->optFlags & OPT_ARGMASK) == OPT_ARGREQ) {
366 snprintf(tmpStr, sizeof(tmpStr), "%s=ARG", optList[i].optLong); 366 snprintf(tmpStr, sizeof(tmpStr), "%s=ARG", optList[i].optLong);
367 p = tmpStr; 367 p = tmpStr;
368 } else 368 } else
369 p = o->optLong; 369 p = o->optLong;
370 370
371 fprintf(outFile, "--%-15s", p); 371 fprintf(outFile, "--%-15s", p);
372 } else 372 } else
373 fprintf(outFile, " "); 373 fprintf(outFile, " ");
374 374
375 fprintf(outFile, " %s.", optList[i].optDesc); 375 fprintf(outFile, " %s.", optList[i].optDesc);
376 376
377 if (o->optFlags & OPT_REQUIRED) { 377 if (o->optFlags & OPT_REQUIRED) {
378 fprintf(outFile, " [*]\n"); 378 fprintf(outFile, " [*]\n");
379 nrequired++; 379 nrequired++;
380 } else 380 } else
381 fprintf(outFile, "\n"); 381 fprintf(outFile, "\n");
382 } 382 }
383 383
384 if (nrequired > 0) 384 if (nrequired > 0)
385 fprintf(outFile, "(Options marked with [*] are required)\n"); 385 fprintf(outFile, "(Options marked with [*] are required)\n");
386 } 386 }
387 387