From 083fc37b12e31687e592ab9948cfbb8b996ece0b Mon Sep 17 00:00:00 2001 From: Thomas Jensen Date: Sat, 1 Jun 2024 15:54:46 +0200 Subject: [PATCH] Consolidate undocumented options into -x command line option --- src/boxes.c | 2 +- src/boxes.in.h | 3 +- src/cmdline.c | 81 ++++++++++++++++++++++++++++++++++++++++--------- src/list.c | 2 +- src/parsecode.c | 2 +- src/query.c | 10 +----- src/query.h | 7 ----- 7 files changed, 72 insertions(+), 35 deletions(-) diff --git a/src/boxes.c b/src/boxes.c index 8a68dc7..e74d460 100644 --- a/src/boxes.c +++ b/src/boxes.c @@ -512,7 +512,7 @@ int main(int argc, char *argv[]) } /* If "-q" option was given, print results of tag query and exit. */ - if (opt.query != NULL && opt.query[0] != NULL && !query_is_undoc()) { + if (opt.query != NULL && opt.query[0] != NULL) { rc = query_by_tag(); exit(rc); } diff --git a/src/boxes.in.h b/src/boxes.in.h index a375756..98b9572 100644 --- a/src/boxes.in.h +++ b/src/boxes.in.h @@ -143,7 +143,6 @@ typedef struct { /* Command line options: */ char *eol; /** `-e`: line break to use. Never NULL, default to "\n". */ int eol_overridden; /** `-e`: 0: value in `eol` is the default; 1: value in `eol` specified via `-e` */ char *f; /** `-f`: config file path */ - int *debug; /** `-g`: activate debug logging for given debug log areas */ int help; /** `-h`: flags if help argument was specified */ char indentmode; /** `-i`: 'b', 't', 'n', or '\0' */ int killblank; /** `-k`: kill blank lines, -1 if not set */ @@ -158,6 +157,8 @@ typedef struct { /* Command line options: */ int tabstop; /** `-t`: tab stop distance */ char tabexp; /** `-t`: tab expansion mode (for leading tabs) */ int version_requested; /** `-v`: request to show version number */ + int *debug; /** `-x debug:`: activate debug logging for given debug log areas */ + int qundoc; /** `-x (undoc)`: flag if "(undoc)" was specified, put directly before "debug:" */ FILE *infile; FILE *outfile; } opt_t; diff --git a/src/cmdline.c b/src/cmdline.c index 9146f0b..14b8b2d 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -32,6 +32,7 @@ #endif #include "boxes.h" +#include "bxstring.h" #include "discovery.h" #include "logging.h" #include "query.h" @@ -58,6 +59,9 @@ extern int optind; /* for getopt() */ #define EOL_DEFAULT "\n" #endif +#define EXTRA_UNDOC "(undoc)" +#define EXTRA_DEBUG "debug" + /** @@ -92,7 +96,6 @@ void usage_long(FILE *st) strcmp(EOL_DEFAULT, "\r\n") == 0 ? "CRLF" : "LF"); fprintf(st, " -f, --config Configuration file [default: %s]\n", config_file != NULL ? bxs_to_output(config_file) : "none"); - /* fprintf(st, " -g, --debug Activate debug logging for specified log areas [default area: MAIN]"); // undocumented */ fprintf(st, " -h, --help Print usage information\n"); fprintf(st, " -i, --indent Indentation mode [default: box]\n"); fprintf(st, " -k Leading/trailing blank line retention on removal\n"); @@ -102,11 +105,14 @@ void usage_long(FILE *st) fprintf(st, " -m, --mend Mend (repair) box\n"); fprintf(st, " -n, --encoding Character encoding of input and output [default: %s]\n", locale_charset()); fprintf(st, " -p, --padding Padding [default: none]\n"); - fprintf(st, " -q, --tag-query Query the list of designs by tag\n"); /* with "(undoc)" as query, trigger undocumented behavior instead */ + fprintf(st, " -q, --tag-query Query the list of designs by tag\n"); fprintf(st, " -r, --remove Remove box\n"); fprintf(st, " -s, --size Box size (width w and/or height h)\n"); fprintf(st, " -t, --tabs Tab stop distance and expansion [default: %de]\n", DEF_TABSTOP); fprintf(st, " -v, --version Print version information\n"); + /* fprintf(st, " -x, --extra If starts with "debug:", activate debug logging for specified log + areas which follow in a comma-separated list [default area: MAIN]. If is "(undoc)", trigger + undocumented behavior of design detail lister."); // undocumented */ bxs_free(config_file); } @@ -494,7 +500,10 @@ static int debug_areas(opt_t *result, char *optarg) } } if (!valid) { - bx_fprintf(stderr, "%s: invalid debug area -- %s\n", PROJECT, trimmed); + bx_fprintf(stderr, "%s: invalid debug area -- %s. Valid values: ", PROJECT, trimmed); + for (size_t i = 1; i < NUM_LOG_AREAS + 2; i++) { + bx_fprintf(stderr, "%s%s", log_area_names[i], i < (NUM_LOG_AREAS + 2 - 1) ? ", " : "\n"); + } BFREE(trimmed); return 1; } @@ -553,6 +562,48 @@ static int tab_handling(opt_t *result, char *optarg) +/** + * Handle undocumented options (-x). + * @param result the options struct we are building + * @param optarg the argument to `-x` on the command line + * @returns 0 on success, anything else on error + */ +static int undocumented_options(opt_t *result, char *optarg) +{ + char *s = optarg; + + if (strncmp(s, EXTRA_UNDOC, strlen(EXTRA_UNDOC)) == 0) { + result->qundoc = 1; + s += strlen(EXTRA_UNDOC); + } + + if (strncasecmp(s, EXTRA_DEBUG, strlen(EXTRA_DEBUG)) == 0) { + s += strlen(EXTRA_DEBUG); + if (*s == ':') { + if (debug_areas(result, s + 1) != 0) { + return 1; + } + } + else if (*s == '\0') { + /* default to MAIN */ + debug_areas(result, NULL); + } + else { + bx_fprintf(stderr, "%s: invalid option -x %s\n", PROJECT, optarg); + return 2; + } + activate_debug_logging(result->debug); + } + + if (!result->qundoc && !is_debug_activated()) { + bx_fprintf(stderr, "%s: invalid option -x %s\n", PROJECT, optarg); + return 3; + } + return 0; +} + + + /** * Set *stdout* to binary mode, so that we can control the line terminator. This function only ever does anything on * Windows, because on Linux, we already do have control over line terminators. @@ -639,7 +690,7 @@ static void print_debug_info(opt_t *result) log_debug(__FILE__, MAIN, " - Design Definition W shape (-c): %s\n", result->cld ? result->cld : "n/a"); log_debug(__FILE__, MAIN, " - Color mode: %d\n", result->color); - log_debug(__FILE__, MAIN, " - Debug areas: "); + log_debug(__FILE__, MAIN, " - Debug areas (-x debug:...): "); int dbgfirst = 1; for (size_t i = 0; i < NUM_LOG_AREAS; i++) { if (result->debug[i]) { @@ -658,7 +709,7 @@ static void print_debug_info(opt_t *result) log_debug(__FILE__, MAIN, " - Padding (-p): l:%d t:%d r:%d b:%d\n", result->padding[BLEF], result->padding[BTOP], result->padding[BRIG], result->padding[BBOT]); - log_debug(__FILE__, MAIN, " - Tag Query / Special handling for Web UI (-q): "); + log_debug(__FILE__, MAIN, " - Tag Query (-q): "); if (result->query != NULL) { for (size_t qidx = 0; result->query[qidx] != NULL; ++qidx) { log_debug_cont(MAIN, "%s%s", qidx > 0 ? ", " : "", result->query[qidx]); @@ -668,6 +719,7 @@ static void print_debug_info(opt_t *result) } log_debug_cont(MAIN, "\n"); + log_debug(__FILE__, MAIN, " - qundoc (-x): %d\n", result->qundoc); log_debug(__FILE__, MAIN, " - Remove box (-r): %d\n", result->r); log_debug(__FILE__, MAIN, " - Requested box size (-s): %ldx%ld\n", result->reqwidth, result->reqheight); log_debug(__FILE__, MAIN, " - Tabstop distance (-t): %d\n", result->tabstop); @@ -703,7 +755,6 @@ opt_t *process_commandline(int argc, char *argv[]) { "create", required_argument, NULL, 'c' }, { "color", no_argument, NULL, OPT_COLOR }, { "no-color", no_argument, NULL, OPT_NO_COLOR }, - { "debug", optional_argument, NULL, 'g' }, { "design", required_argument, NULL, 'd' }, { "eol", required_argument, NULL, 'e' }, { "config", required_argument, NULL, 'f' }, @@ -720,9 +771,10 @@ opt_t *process_commandline(int argc, char *argv[]) { "size", required_argument, NULL, 's' }, { "tabs", required_argument, NULL, 't' }, { "version", no_argument, NULL, 'v' }, + { "extra", required_argument, NULL, 'x' }, { NULL, 0, NULL, 0 } }; - const char *short_options = "a:c:d:e:f:g::hi:k:lmn:p:q:rs:t:v"; + const char *short_options = "a:c:d:e:f:hi:k:lmn:p:q:rs:t:vx:"; int oc; /* option character */ do { @@ -770,14 +822,6 @@ opt_t *process_commandline(int argc, char *argv[]) result->f = strdup(optarg); /* input file */ break; - case 'g': - if (debug_areas(result, optarg) != 0) { - BFREE(result); - return NULL; - } - activate_debug_logging(result->debug); - break; - case 'h': result->help = 1; return result; @@ -863,6 +907,13 @@ opt_t *process_commandline(int argc, char *argv[]) result->version_requested = 1; /* print version number */ return result; + case 'x': + if (undocumented_options(result, optarg) != 0) { + BFREE(result); + return NULL; + } + break; + case ':': case '?': /* Missing argument or illegal option - do nothing else */ diff --git a/src/list.c b/src/list.c index 2ae3963..0dbe523 100644 --- a/src/list.c +++ b/src/list.c @@ -321,7 +321,7 @@ static void print_design_details(design_t *d) /* * Display all shapes */ - if (query_is_undoc()) { + if (opt.qundoc) { fprintf(opt.outfile, "Sample:%s%s%s", opt.eol, bxs_to_output(d->sample), opt.eol); } else { diff --git a/src/parsecode.c b/src/parsecode.c index ee20ded..efac4f7 100644 --- a/src/parsecode.c +++ b/src/parsecode.c @@ -314,7 +314,7 @@ static int full_parse_required() { int result = 0; if (!opt.design_choice_by_user) { - result = opt.r || opt.l || (opt.query != NULL && !query_is_undoc()); + result = opt.r || opt.l || (opt.query != NULL && !opt.qundoc); } #ifdef DEBUG fprintf(stderr, " Parser: full_parse_required() -> %s\n", result ? "true" : "false"); diff --git a/src/query.c b/src/query.c index 8dc2c64..0cdcfd2 100644 --- a/src/query.c +++ b/src/query.c @@ -30,13 +30,12 @@ #define QUERY_ALL "(all)" -#define QUERY_UNDOC "(undoc)" static int validate_tag(char *tag) { - if (strcmp(tag, QUERY_ALL) == 0 || strcmp(tag, QUERY_UNDOC) == 0) { + if (strcmp(tag, QUERY_ALL) == 0) { return 1; } return tag_is_valid(tag); @@ -117,13 +116,6 @@ char **parse_query(char *optarg) -int query_is_undoc() -{ - return opt.query != NULL && strcmp(opt.query[0], QUERY_UNDOC) == 0 && opt.query[1] == NULL; -} - - - static int filter_by_tag(char **tags) { #ifdef DEBUG diff --git a/src/query.h b/src/query.h index 1169311..b419a03 100644 --- a/src/query.h +++ b/src/query.h @@ -29,13 +29,6 @@ char **parse_query(char *optarg); -/** - * Check if -q "(undoc)" was specified. - * @returns flag - */ -int query_is_undoc(); - - /** * Perform the tag query based on the global design list and the query from the global `opt` struct. * @returns 0 if successful; anything else on error (then the program should exit)