From 3c1af3b9549abe3bfcdf72d92df371745dc2d93c Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Wed, 3 Mar 2021 00:58:42 -0500 Subject: [PATCH] Use the option generator script from dxcommon. This script simplifies maintenance of long option lists and the --help text a lot. --- Makefile.am | 12 +++- src/.gitignore | 1 + src/main.c | 167 ++++++++++++++++++++++++------------------------ src/options.opt | 70 ++++++++++++++++++++ 4 files changed, 163 insertions(+), 87 deletions(-) create mode 100644 src/options.opt diff --git a/Makefile.am b/Makefile.am index f7f54e6..a693ace 100644 --- a/Makefile.am +++ b/Makefile.am @@ -41,9 +41,9 @@ $(parser_rdeps_OBJECTS): src/parse.h noinst_HEADERS = src/main.h src/treefuncs.h src/out.h src/util.h src/checks.h gob2_SOURCES = src/main.c src/main.h src/treefuncs.c src/out.c src/util.c \ - src/checks.c src/parse.y src/lexer.c src/lexer.h + src/checks.c src/parse.y src/lexer.c src/lexer.h src/options.h gob2_LDADD = $(LIBGLIB_LIBS) libgnu.a -$(gob2_OBJECTS): src/treefuncs.h $(gnulib_headers) +$(gob2_OBJECTS): src/treefuncs.h src/options.h $(gnulib_headers) man_MANS = doc/gob2.1 EXTRA_DIST += doc/makehtml.pl @@ -77,6 +77,14 @@ endif $(abs_srcdir)/src/treefuncs.def; ) $(AM_V_at) mv -f $@.tmp $@ +OPTFILES = src/options.opt +.opt.h: + $(AM_V_GEN) $(AWK) -f $(DX_BASEDIR)/scripts/gen-options.awk $< >$@.tmp + $(AM_V_at) mv -f $@.tmp $@ +$(OPTFILES:.opt=.h): $(DX_BASEDIR)/scripts/gen-options.awk +MAINTAINERCLEANFILES += $(OPTFILES:.opt=.h) +EXTRA_DIST += $(DX_BASEDIR)/scripts/gen-options.awk $(OPTFILES) + .l.c: ; .l.stamp: if !HAVE_FLEX diff --git a/src/.gitignore b/src/.gitignore index 89b3329..12eb0d1 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,5 +1,6 @@ /lexer.[ch] /lexer.stamp +/options.h /parse.[ch] /treefuncs.[ch] /treefuncs.stamp diff --git a/src/main.c b/src/main.c index c994d5a..6436cde 100644 --- a/src/main.c +++ b/src/main.c @@ -42,41 +42,11 @@ #include "main.h" -enum { - SOPT_END = UCHAR_MAX, - LOPT_VERSION, - LOPT_NO_TOUCH, - LOPT_FILE_SEP, - LOPT_M4, - LOPT_M4_CLEAN, - LOPT_M4_DIR -}; +#include "options.h" -static const char sopts[] = "wnho:"; +static const char sopts[] = SOPT_STRING; static const struct option lopts[] = { - { "help", 0, NULL, 'h' }, - { "version", 0, NULL, LOPT_VERSION }, - { "exit-on-warn", 0, NULL, 'w' }, - { "no-exit-on-warn", 0, &exit_on_warn, FALSE }, - { "for-cpp", 0, &for_cpp, TRUE }, - { "no-extern-c", 0, &no_extern_c, TRUE }, - { "no-gnu", 0, &no_gnu, TRUE }, - { "no-touch", 0, NULL, LOPT_NO_TOUCH }, - { "no-touch-headers", 0, &no_touch_headers, TRUE }, - { "always-private-header", 0, &private_header, PRIVATE_HEADER_ALWAYS }, - { "ondemand-private-header", 0, &private_header, PRIVATE_HEADER_ONDEMAND }, - { "no-private-header", 0, &private_header, PRIVATE_HEADER_NEVER }, - { "always-private-struct", 0, &always_private_struct, TRUE }, - { "m4", 0, NULL, LOPT_M4 }, - { "m4-clean", 0, NULL, LOPT_M4_CLEAN }, - { "m4-dir", 0, NULL, LOPT_M4_DIR }, - { "no-write", 0, NULL, 'n' }, - { "no-lines", 0, &no_lines, TRUE }, - { "no-self-alias", 0, &no_self_alias, TRUE }, - { "no-kill-underscores", 0, NULL, 0 /* no-op */ }, - { "output-dir", 1, NULL, 'o' }, - { "file-sep", 2, NULL, LOPT_FILE_SEP }, - { "gtk3", 0, >k3_ok, TRUE }, + LOPTS_INITIALIZER, { 0 } }; @@ -4583,61 +4553,88 @@ static void print_usage(FILE *f) } } -static void -print_help(void) +/* + * Given a long option, return the corresponding short option character, + * or 0 if there is no such character. + */ +static char lopt_to_sopt(const char *sopts, const struct option *opt) +{ + int val = opt->val; + const char *c; + + if (val <= 0 || val > CHAR_MAX) + return 0; + + if (val == ':' || val == '+' || val == '-') + return 0; + + c = strchr(sopts, opt->val); + if (c) + return *c; + return 0; +} + +/* + * Print a string, with each line indented by i spaces. The first line + * will be indented by w fewer spaces (to account for the cursor being in + * some other column). + */ +static void print_block(const char *s, int i, int w) +{ + for (; *s; w = 0) { + const char *nl = strchr(s, '\n'); + int n = (nl ? nl-s : -1); + + printf("%*s%.*s\n", i-w, "", n, s); + if (!nl) + break; + + s = nl+1; + } +} + +static void print_help(void) { + const struct option *opt; + print_usage(stdout); - puts( -"This is \"GObject Builder\": a simple preprocessor to help with\n" -"implementing GObject types in C.\n" - ); - - puts("Options:"); - puts(" --help,-h,-? Display this help\n" - " --version Display version\n" - " --exit-on-warn,-w Exit with an error on warnings\n" - " --no-exit-on-warn Don't exit on warnings [default]\n" - " --for-cpp Create C++ files\n" - " --no-extern-c Never print extern \"C\" into the " - "header\n" - " --no-gnu Never use GNU extentions\n" - " --no-touch Don't touch output files unless they " - "really\n" - " changed (implies --no-touch-headers)\n" - " --no-touch-headers Don't touch headers unless they " - "really changed\n" - " --always-private-header Always create a private header " - "file,\n" - " even if it would be empty\n" - " --ondemand-private-header Create private header only when " - "needed\n" - " [default]\n" - " --no-private-header Don't create a private header, " - "put private\n" - " structure and protected " - "prototypes inside c file\n" - " --always-private-struct Always create a private pointer " - "in\n" - " the object structure\n" - " --m4 Preprocess source with m4. " - "Following args will\n" - " be passed to m4\n" - " --m4-dir Print directory that will be " - "searched for m4\n" - " files\n" - " --no-write,-n Don't write output files, just " - "check syntax\n" - " --no-lines Don't print '#line' to output\n" - " --no-self-alias Don't create self type and macro " - "aliases\n" - " --no-kill-underscores Ignored for compatibility\n" - " -o,--output-dir The directory where output " - "should be placed\n" - " --file-sep[=c] replace default \'-\' file " - "name separator\n\n" - " --gtk3 Use gtk+3\n" - ); + puts("This is \"GObject Builder\": a simple preprocessor to help with\n" + "implementing GObject types in C."); + + puts("\nOptions:"); + for (opt = lopts; opt->name; opt++) { + struct lopt_help help; + char sopt; + int w; + + /* Don't display obsolete options that don't do anything */ + if (!opt->flag && !opt->val) + continue; + + if (!lopt_get_help(opt, &help)) + continue; + + if ((sopt = lopt_to_sopt(sopts, opt))) { + w = printf(opt->has_arg == 0 ? " -%c, --%s" + : opt->has_arg == 1 ? " -%c, --%s=%s" + : " -%c, --%s[=%s]", + sopt, opt->name, help.arg); + } else { + w = printf(opt->has_arg == 0 ? " --%s" + : opt->has_arg == 1 ? " --%s=%s" + : " --%s[=%s]", + opt->name, help.arg); + } + + if (w < 0 || w > 18) { + putchar('\n'); + w = 0; + } + + print_block(help.desc, 20, w); + } + putchar('\n'); puts("End world hunger, donate to the World Food Programme: https://www.wfp.org/"); } diff --git a/src/options.opt b/src/options.opt new file mode 100644 index 0000000..cb2d5cb --- /dev/null +++ b/src/options.opt @@ -0,0 +1,70 @@ +-h, --help +Print this message and then exit. + +--version +Print a version message and then exit. + +-w, --exit-on-warn +Exit with an error on any warning. +--no-exit-on-warn (&exit_on_warn, FALSE) + +--for-cpp (&for_cpp, TRUE) +Generate C++ output. + +--no-extern-c (&no_extern_c, TRUE) +Omit C++ extern "C" declarations from headers. + +--no-gnu (&no_gnu, TRUE) +Do not use any GNU language extensions. + +--no-touch-headers (&no_touch_headers, TRUE) +Avoid modifying output header files if there would not be +any changes, so that modification times are preserved. + +--no-touch +Same as --no-touch-headers but applies to all output files. + +--always-private-struct (&always_private_struct, TRUE) +Create the _priv pointer in the object structure even if +there are no private members. + +--always-private-header (&private_header, PRIVATE_HEADER_ALWAYS) +Create a private header file even if it would be empty. + +--ondemand-private-header (&private_header, PRIVATE_HEADER_ONDEMAND) +Create a private header file only if required (default). + +--no-private-header (&private_header, PRIVATE_HEADER_NEVER) + +--m4 +Use M4 to produce input data. All non-option arguments +and subsequent arguments are passed to m4. + +--m4-clean +Same as --m4, except that no arguments other than those +specified on the command line are passed to m4. + +--m4-dir +Print the default m4 search directory and then exit. + +-n, --no-write +Do not actually create any output files. The input is +still parsed to check for syntax errors. + +--no-lines (&no_lines, TRUE) +Do not output any #line directives. + +--no-self-alias (&no_self_alias, TRUE) +Do not output the SELF macros or Self typedefs. + +--no-kill-underscores (0) + +-o, --output-dir=DIR +Output files will be placed relative to DIR. + +--file-sep[=CHAR] +Separate filename components with CHAR, as opposed to '-'. +If CHAR is omitted, no separator is used. + +--gtk3 (>k3_ok, TRUE) +Use GTK+3 interface names. -- 2.43.0