Mercurial > hg > dmlib
view src/dmargs.c @ 2208:90ec1ec89c56
Revamp the palette handling in lib64gfx somewhat, add helper functions to
lib64util for handling external palette file options and add support for
specifying one of the "internal" palettes or external (.act) palette file to
gfxconv and 64vw.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 14 Jun 2019 05:01:12 +0300 |
parents | bcdea45a14cb |
children | c801995cbb13 |
line wrap: on
line source
/* * Simple commandline argument processing * Programmed and designed by Matti 'ccr' Hamalainen * (C) Copyright 2002-2018 Tecnic Software productions (TNSP) * * Please read file 'COPYING' for information on license and distribution. */ /// @file /// @brief Simple commandline argument processing functions #include "dmargs.h" /** * Parse and optionally handle the given long or short option argument. * @param currArg current argument string * @param argIndex pointer to index of current argument in argv[] * @param argc number of arguments * @param argv argument string array * @param opts options list array * @param nopts number of elements in options list array * @param handle_option function pointer to callback that handles option arguments * @param doProcess if TRUE, actually handle the argument, aka call the handle_option() function. if FALSE, only validity of options are checked. * @param isLong TRUE if the option is a --long-format one */ static BOOL dmArgsProcessOpt( char *currArg, int *argIndex, int argc, char *argv[], const DMOptArg opts[], int nopts, BOOL (*handle_option)(int id, char *, char *), BOOL doProcess, BOOL isLong) { const DMOptArg *opt = NULL; char *optArg = NULL; int optIndex; for (optIndex = 0; optIndex < nopts; optIndex++) { const DMOptArg *node = &opts[optIndex]; if (isLong && node->o_long != NULL) { if (strcmp(currArg, node->o_long) == 0) { opt = node; optArg = NULL; break; } size_t len = strlen(node->o_long); if (strncmp(currArg, node->o_long, len) == 0 && currArg[len] == '=') { opt = node; optArg = (&currArg[len+1] != 0) ? &currArg[len+1] : NULL; break; } } else if (!isLong && node->o_short != 0) { if (*currArg == node->o_short) { 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) { dmErrorMsg("Option '%s%s' requires an argument.\n", isLong ? "--" : "-", currArg); return FALSE; } } // Option was given succesfully, try to process it if (doProcess && !handle_option(opt->id, optArg, currArg)) return FALSE; } else { dmErrorMsg("Unknown %s option '%s%s'\n", isLong ? "long" : "short", isLong ? "--" : "-", currArg); return FALSE; } return TRUE; } /** * Process given array of commandline arguments, handling short * and long options by calling the respective callback functions. * * @param argc number of arguments * @param argv argument list * @param opts supported option list array * @param nopts number of elements in the option list array * @param handle_option callback function * @param handle_other callback function * @param flags processing flags * @return return TRUE if all is well */ BOOL dmArgsProcess(int argc, char *argv[], const DMOptArg *opts, const int nopts, BOOL(*handle_option)(int id, char *, char *), BOOL(*handle_other)(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 (!dmArgsProcessOpt(str, &argIndex, argc, argv, opts, nopts, handle_option, doProcess, isLong)) optionsOK = FALSE; } else if (handleFlags == OPTH_ONLY_OTHER || handleFlags == 0) { // Was not option argument if (handle_other == NULL || (handle_other != NULL && !handle_other(str))) { dmErrorMsg("Invalid argument '%s'\n", str); optionsOK = FALSE; } } // Check if we bail out on invalid argument if (!optionsOK && (flags & OPTH_BAILOUT)) return FALSE; } return optionsOK; } static void dmPad(FILE *outFile, int count) { while (count--) fputc(' ', outFile); } static void dmPrintWrap(FILE *fh, const char *str, int spad, int rpad, int width) { size_t pos = 0; BOOL first = TRUE; while (str[pos]) { // Pre-pad line int linelen = first ? spad : rpad; dmPad(fh, first ? 0 : rpad); first = FALSE; // Skip whitespace at line start while (isspace(str[pos]) || str[pos] == '\n') pos++; // Handle each word while (str[pos] && str[pos] != '\n') { size_t next; int wlen; for (wlen = 0, next = pos; str[next] && !isspace(str[next]) && str[next] != '\n'; next++, wlen++); // fprintf(stdout, "X '%c', %d .. linelen=%d/%d, wlen=%d\n", str[pos], pos, linelen, width, wlen); if (linelen + wlen < width) { for (;pos < next; pos++, linelen++) fputc(str[pos], fh); if (str[next] == '\n' || str[next] == 0) { fprintf(fh, "\n"); break; } else { fputc(str[pos], fh); pos++; linelen++; } } else { fprintf(fh, "\n"); break; } } } } /** * Print help for commandline arguments/options * @param fh stdio file handle to output to * @param opts options list array * @param nopts number of elements in options list array * @param flags flags (currently unused) */ void dmArgsPrintHelp(FILE *fh, const DMOptArg *opts, const int nopts, const int flags) { int index; (void) flags; // Print out option list for (index = 0; index < nopts; index++) { const DMOptArg *opt = &opts[index]; char tmpStr[128]; // Print short option if (opt->o_short != 0) { snprintf(tmpStr, sizeof(tmpStr), "-%c,", opt->o_short); } else tmpStr[0] = 0; fprintf(fh, " %-5s", tmpStr); // Print long option if (opt->o_long != NULL) { snprintf(tmpStr, sizeof(tmpStr), "--%s%s", opt->o_long, (opt->flags & OPT_ARGREQ) ? "=ARG" : ""); } else tmpStr[0] = 0; fprintf(fh, "%-18s", tmpStr); dmPrintWrap(fh, opt->desc, 24, 24, 79); } }