]> git.draconx.ca Git - gob-dx.git/commitdiff
Use the option generator script from dxcommon.
authorNick Bowler <nbowler@draconx.ca>
Wed, 3 Mar 2021 05:58:42 +0000 (00:58 -0500)
committerNick Bowler <nbowler@draconx.ca>
Wed, 3 Mar 2021 06:28:40 +0000 (01:28 -0500)
This script simplifies maintenance of long option lists and
the --help text a lot.

Makefile.am
src/.gitignore
src/main.c
src/options.opt [new file with mode: 0644]

index f7f54e69216fd5296d09aeef577822d2a2365a39..a693aced024113b7c0985bc112cf3775fb448dbb 100644 (file)
@@ -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
index 89b3329377c16a2420b8f1d2ead869f337ba6141..12eb0d18c984efcacb3973c54c1e066b551f20a2 100644 (file)
@@ -1,5 +1,6 @@
 /lexer.[ch]
 /lexer.stamp
+/options.h
 /parse.[ch]
 /treefuncs.[ch]
 /treefuncs.stamp
index c994d5ae3b0119326e3f32b52300a7fb997b71c8..6436cde678fdb97f8702808e2aabaa93b836317d 100644 (file)
 
 #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, &gtk3_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 (file)
index 0000000..cb2d5cb
--- /dev/null
@@ -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 (&gtk3_ok, TRUE)
+Use GTK+3 interface names.