Mercurial > hg > th-libs
view th_args.c @ 327:b0f9f806c8c9
Implement NCOUNT() macro for getting array element counts (sizeof(arr) / sizeof(arr[0]))
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 23 Feb 2016 12:43:38 +0200 |
parents | 503f0cb98775 |
children | f4e182720870 |
line wrap: on
line source
/* * Simple commandline argument processing * Programmed and designed by Matti 'ccr' Hamalainen * (C) Copyright 2002-2015 Tecnic Software productions (TNSP) * * Please read file 'COPYING' for information on license and distribution. */ #ifndef TH_EXTERNAL #include "th_util.h" #include "th_args.h" #include "th_string.h" #endif /* Parse long and short options */ static BOOL th_args_process_opt( char *currArg, int *argIndex, int argc, char *argv[], const th_optarg_t opts[], int numOpts, BOOL (*handleOptionCB)(int, char *, char *), BOOL doProcess, BOOL isLong) { const th_optarg_t *opt = NULL; char *optArg = NULL; int optIndex; for (optIndex = 0; optIndex < numOpts; optIndex++) { const th_optarg_t *node = &opts[optIndex]; if (isLong && node->optLong != NULL) { if (strcmp(currArg, node->optLong) == 0) { opt = node; optArg = NULL; break; } size_t len = strlen(node->optLong); if (strncmp(currArg, node->optLong, len) == 0 && currArg[len] == '=') { opt = node; optArg = (&currArg[len+1] != 0) ? &currArg[len+1] : NULL; break; } } else if (!isLong && node->optShort != 0) { if (*currArg == node->optShort) { opt = node; optArg = (currArg[1] != 0) ? &currArg[1] : NULL; } } } if (opt != NULL) { // Check for the possible option argument if ((opt->flags & OPT_ARGMASK) == OPT_ARGREQ && optArg == NULL) { if (*argIndex < argc) { (*argIndex)++; optArg = argv[*argIndex]; } if (optArg == NULL) { THERR("Option '%s%s' requires an argument.\n", isLong ? "--" : "-", currArg); return FALSE; } } // Option was given succesfully, try to process it if (doProcess && !handleOptionCB(opt->id, optArg, currArg)) return FALSE; } else { THERR("Unknown %s option '%s%s'\n", isLong ? "long" : "short", isLong ? "--" : "-", currArg); return FALSE; } return TRUE; } /* Process arguments, handling short and long options by * calling the given callback functions. */ BOOL th_args_process(int argc, char *argv[], const th_optarg_t *opts, const int numOpts, BOOL(*handleOptionCB) (int, char *, char *), BOOL(*handleOther) (char *), const int flags) { int argIndex, handleFlags = flags & OPTH_ONLY_MASK; BOOL optionsOK = TRUE, endOfOptions = FALSE; for (argIndex = 1; argIndex < argc; argIndex++) { char *str = argv[argIndex]; if (*str == '-' && !endOfOptions) { // Should we process options? BOOL doProcess = (handleFlags & OPTH_ONLY_OPTS) || handleFlags == 0; BOOL isLong; str++; if (*str == '-') { // Check for "--", which ends the options-list str++; if (*str == 0) { endOfOptions = TRUE; continue; } // We have a long option isLong = TRUE; } else isLong = FALSE; if (!th_args_process_opt(str, &argIndex, argc, argv, opts, numOpts, handleOptionCB, doProcess, isLong)) optionsOK = FALSE; } else if (handleFlags == OPTH_ONLY_OTHER || handleFlags == 0) { // Was not option argument if (handleOther == NULL || (handleOther != NULL && !handleOther(str))) { THERR("Invalid argument '%s'\n", str); optionsOK = FALSE; } } // Check if we bail out on invalid argument if (!optionsOK && (flags & OPTH_BAILOUT)) return FALSE; } return optionsOK; } /* Print help for commandline arguments/options */ void th_args_help(FILE *fh, const th_optarg_t *opts, const int numOpts, const int flags) { int index; (void) flags; // Print out option list for (index = 0; index < numOpts; index++) { const th_optarg_t *opt = &opts[index]; char tmpStr[128]; // Print short option if (opt->optShort != 0) { snprintf(tmpStr, sizeof(tmpStr), "-%c,", opt->optShort); } else tmpStr[0] = 0; fprintf(fh, " %-5s", tmpStr); // Print long option if (opt->optLong != NULL) { snprintf(tmpStr, sizeof(tmpStr), "--%s%s", opt->optLong, (opt->flags & OPT_ARGREQ) ? "=ARG" : ""); } else tmpStr[0] = 0; fprintf(fh, "%-20s", tmpStr); th_print_wrap(fh, opt->desc, 26, 26, th_term_width() - 2); } }