aboutsummaryrefslogtreecommitdiff
path: root/build-aux/getopt.m4
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2012-09-26 14:18:20 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2012-09-26 14:18:20 +0300
commit7bc88d60ab7398631be3f85750965e812ba7ceb0 (patch)
treef1e8c86da6d78dd44a780702c2959d304b55a7d3 /build-aux/getopt.m4
parent934c30d3ec1b443feee7dbc711b998202d40f77c (diff)
downloadgrecs-7bc88d60ab7398631be3f85750965e812ba7ceb0.tar.gz
grecs-7bc88d60ab7398631be3f85750965e812ba7ceb0.tar.bz2
Improve getopt interface.
* build-aux/getopt.m4: Move function declarations to the library. Introduce new options: nopermute, nousage, noversion. * src/grecsopt.h: New file. * src/opthelp.c: New file. * src/Make-shared.am: Add new files. * src/Make-static.am: Likewise. * src/Make.am: Likewise.
Diffstat (limited to 'build-aux/getopt.m4')
-rw-r--r--build-aux/getopt.m4544
1 files changed, 49 insertions, 495 deletions
diff --git a/build-aux/getopt.m4 b/build-aux/getopt.m4
index 878504d..4dd0a5a 100644
--- a/build-aux/getopt.m4
+++ b/build-aux/getopt.m4
@@ -94,7 +94,7 @@ dnl
define([<upcase>], [<translit([<$*>], [<a-z>], [<A-Z>])>])
dnl concat(ARGS...)
-dnl Concatenate arguments, inserting ", " between each of pair of them.
+dnl Concatenate arguments, inserting ", " between each pair of them.
dnl
define([<concat>],[<ifelse([<$#>],1,[<$1>],[<$1, concat(shift($@))>])>])
@@ -118,8 +118,8 @@ define([<escape>],
[<patsubst([<concat($*)>],[<[\"]>],[<\\\&>])>])
dnl prep(ARG)
-dnl Prepare ARG for including in C strings: replace newlines with any amount
-dnl of preceding and following whitespace by a single space character, remove
+dnl Prepare ARG for including in C strings: replace newlines and any
+dnl preceding and following whitespace by a single space character, remove
dnl leading whitespace, and escape double-quotes.
dnl
define([<prep>],
@@ -129,7 +129,7 @@ define([<prep>],
dnl SHORT_OPTS
dnl Accumulator for the 3rd argument of getopt_long
dnl
-define([<SHORT_OPTS>],[<>])
+define([<SHORT_OPTS>],[<_getopt_if_option_set([<nopermute>],+)>])
dnl GROUP(STRING)
dnl Begin a named group of options
@@ -263,6 +263,8 @@ define([<GETOPT>],[<
{
int c;
+ optind = 0;
+ opterr = 0;
#ifdef HAVE_GETOPT_LONG
while ((c = getopt_long($1, $2, "SHORT_OPTS",
long_options, NULL)) != EOF)
@@ -294,486 +296,31 @@ define([<GETOPT>],[<
>])
define([<STDFUNC>],[<
-divert(0)
-void print_help(void);
-void print_usage(void);
divert(5)
-const char *program_version = [<$1>];
-static char doc[] = ifelse([<$3>],,"",N_("$3"));
-static char args_doc[] = ifelse([<$4>],,"",N_("$4"));
-const char *program_bug_address = "<" PACKAGE_BUGREPORT ">";
-struct grecs_node *cmdline_tree;
-#define DESCRCOLUMN 30
-#define RMARGIN 79
-#define GROUPCOLUMN 2
-#define USAGECOLUMN 13
-
-static void
-indent (size_t start, size_t col)
-{
- for (; start < col; start++)
- putchar (' ');
-}
-
-static void
-print_option_descr (const char *descr, size_t lmargin, size_t rmargin)
-{
- while (*descr)
- {
- size_t s = 0;
- size_t i;
- size_t width = rmargin - lmargin;
-
- for (i = 0; ; i++)
- {
- if (descr[i] == 0 || descr[i] == ' ' || descr[i] == '\t')
- {
- if (i > width)
- break;
- s = i;
- if (descr[i] == 0)
- break;
- }
- }
- printf ("%*.*s\n", s, s, descr);
- descr += s;
- if (*descr)
- {
- indent (0, lmargin);
- descr++;
- }
- }
-}
-
-#define NOPTHELP (sizeof (opthelp) / sizeof (opthelp[0]))
-
-static int
-optcmp (const void *a, const void *b)
-{
- struct opthelp const *ap = (struct opthelp const *)a;
- struct opthelp const *bp = (struct opthelp const *)b;
- const char *opta, *optb;
- size_t alen, blen;
-
- for (opta = ap->opt; *opta == '-'; opta++)
- ;
- alen = strcspn (opta, ",");
-
- for (optb = bp->opt; *optb == '-'; optb++)
- ;
- blen = strcspn (optb, ",");
-
- if (alen > blen)
- blen = alen;
-
- return strncmp (opta, optb, blen);
-}
-
-static void
-sort_options (int start, int count)
-{
- qsort (opthelp + start, count, sizeof (opthelp[0]), optcmp);
-}
-
-static int
-sort_group (int start)
-{
- int i;
-
- for (i = start; i < NOPTHELP && opthelp[i].opt; i++)
- ;
- sort_options (start, i - start);
- return i + 1;
-}
-
-static void
-sort_opthelp (void)
-{
- int start;
-
- for (start = 0; start < NOPTHELP; )
- {
- if (!opthelp[start].opt)
- start = sort_group (start + 1);
- else
- start = sort_group (start);
- }
-}
-
-void (*print_help_hook) (FILE *stream);
-
-void
-print_help (void)
-{
- unsigned i;
- int argsused = 0;
-
- printf ("%s %s [%s]... %s\n", _("Usage:"), [<$2>], _("[<OPTION>]"),
- args_doc[0] ? gettext (args_doc) : args_doc);
- if (doc[0])
- print_option_descr(gettext (doc), 0, RMARGIN);
- putchar ('\n');
-
- sort_opthelp ();
- for (i = 0; i < NOPTHELP; i++)
- {
- unsigned n;
- if (opthelp[i].opt)
- {
- n = printf (" %s", opthelp[i].opt);
- if (opthelp[i].arg)
- {
- char *cb, *ce;
- argsused = 1;
- if (strlen (opthelp[i].opt) == 2)
- {
- if (!opthelp[i].is_optional)
- {
- putchar (' ');
- n++;
- }
- }
- else
- {
- putchar ('=');
- n++;
- }
- if (opthelp[i].is_optional)
- {
- cb = "[";
- ce = "]";
- }
- else
- cb = ce = "";
- n += printf ("%s%s%s", cb, gettext (opthelp[i].arg), ce);
- }
- if (n >= DESCRCOLUMN)
- {
- putchar ('\n');
- n = 0;
- }
- indent (n, DESCRCOLUMN);
- print_option_descr (gettext (opthelp[i].descr), DESCRCOLUMN, RMARGIN);
- }
- else
- {
- if (i)
- putchar ('\n');
- indent (0, GROUPCOLUMN);
- print_option_descr (gettext (opthelp[i].descr),
- GROUPCOLUMN, RMARGIN);
- putchar ('\n');
- }
- }
-
- putchar ('\n');
-dnl **************************************************************************
-dnl This string cannot be split over serveal lines, because this would trigger
-dnl a bug in GNU M4 (version 1.4.9 and 1.4.10), which would insert #line
-dnl directives between the lines.
-dnl **************************************************************************
- if (argsused)
- {
- print_option_descr (_("Mandatory or optional arguments to long options are also mandatory or optional for any corresponding short options."), 0, RMARGIN);
- putchar ('\n');
- }
-
- if (print_help_hook)
- print_help_hook (stdout);
-
- /* TRANSLATORS: The placeholder indicates the bug-reporting address
- for this package. Please add _another line_ saying
- "Report translation bugs to <...>\n" with the address for translation
- bugs (typically your translation team's web or email address). */
- printf (_("Report bugs to %s.\n"), program_bug_address);
-
-#ifdef PACKAGE_URL
- printf (_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
-_getopt_if_option_set([<gnupackage>],[<#else
- printf (_("%s home page: <http://www.gnu.org/software/%s/>\n"),
- PACKAGE_NAME, PACKAGE);
-#endif
- fputs (_("General help using GNU software: <http://www.gnu.org/gethelp/>\n"),
- stdout);>],
-[<#endif>])
-}
-
-static int
-cmpidx_short (const void *a, const void *b)
-{
- unsigned const *ai = (unsigned const *)a;
- unsigned const *bi = (unsigned const *)b;
-
- return opthelp[*ai].opt[1] - opthelp[*bi].opt[1];
-}
-
-#ifdef HAVE_GETOPT_LONG
-static int
-cmpidx_long (const void *a, const void *b)
-{
- unsigned const *ai = (unsigned const *)a;
- unsigned const *bi = (unsigned const *)b;
- struct opthelp const *ap = opthelp + *ai;
- struct opthelp const *bp = opthelp + *bi;
- char const *opta, *optb;
- size_t lena, lenb;
-
- if (ap->opt[1] == '-')
- opta = ap->opt;
- else
- opta = ap->opt + 4;
- lena = strcspn (opta, ",");
-
- if (bp->opt[1] == '-')
- optb = bp->opt;
- else
- optb = bp->opt + 4;
- lenb = strcspn (optb, ",");
- return strncmp (opta, optb, lena > lenb ? lenb : lena);
-}
-#endif
-
-void
-print_usage (void)
-{
- unsigned i;
- unsigned n;
- char buf[RMARGIN+1];
- unsigned *idxbuf;
- unsigned nidx;
-
-#define FLUSH dnl
- do dnl
- { dnl
- buf[n] = 0; dnl
- printf ("%s\n", buf); dnl
- n = USAGECOLUMN; dnl
- memset (buf, ' ', n); dnl
- } dnl
- while (0)
-#define ADDC(c) dnl
- do { if (n == RMARGIN) FLUSH; buf[n++] = c; } while (0)
-
- idxbuf = calloc (NOPTHELP, sizeof (idxbuf[0]));
- if (!idxbuf)
- {
- fprintf (stderr, "not enough memory");
- abort ();
- }
-
- n = snprintf (buf, sizeof buf, "%s %s ", _("Usage:"), [<$2>]);
-
- /* Print a list of short options without arguments. */
- for (i = nidx = 0; i < NOPTHELP; i++)
- if (opthelp[i].opt && opthelp[i].descr && opthelp[i].opt[1] != '-'
- && opthelp[i].arg == NULL)
- idxbuf[nidx++] = i;
-
- if (nidx)
- {
- qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_short);
-
- ADDC ('[');
- ADDC ('-');
- for (i = 0; i < nidx; i++)
- {
- ADDC (opthelp[idxbuf[i]].opt[1]);
- }
- ADDC (']');
- }
-
- /* Print a list of short options with arguments. */
- for (i = nidx = 0; i < NOPTHELP; i++)
- {
- if (opthelp[i].opt && opthelp[i].descr && opthelp[i].opt[1] != '-'
- && opthelp[i].arg)
- idxbuf[nidx++] = i;
- }
-
- if (nidx)
- {
- qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_short);
-
- for (i = 0; i < nidx; i++)
- {
- struct opthelp *opt = opthelp + idxbuf[i];
- size_t len = 5 + strlen (opt->arg)
- + (opt->is_optional ? 2 : 1);
-
- if (n + len > RMARGIN) FLUSH;
- buf[n++] = ' ';
- buf[n++] = '[';
- buf[n++] = '-';
- buf[n++] = opt->opt[1];
- if (opt->is_optional)
- {
- buf[n++] = '[';
- strcpy (&buf[n], opt->arg);
- n += strlen (opt->arg);
- buf[n++] = ']';
- }
- else
- {
- buf[n++] = ' ';
- strcpy (&buf[n], opt->arg);
- n += strlen (opt->arg);
- }
- buf[n++] = ']';
- }
- }
-
-#ifdef HAVE_GETOPT_LONG
- /* Print a list of long options */
- for (i = nidx = 0; i < NOPTHELP; i++)
- {
- if (opthelp[i].opt && opthelp[i].descr
- && (opthelp[i].opt[1] == '-' || opthelp[i].opt[2] == ','))
- idxbuf[nidx++] = i;
- }
-
- if (nidx)
- {
- qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_long);
-
- for (i = 0; i < nidx; i++)
- {
- struct opthelp *opt = opthelp + idxbuf[i];
- size_t len;
- const char *longopt;
-
- if (opt->opt[1] == '-')
- longopt = opt->opt;
- else if (opt->opt[2] == ',')
- longopt = opt->opt + 4;
- else
- continue;
-
- len = 3 + strlen (longopt)
- + (opt->arg ? 1 + strlen (opt->arg)
- + (opt->is_optional ? 2 : 0) : 0);
- if (n + len > RMARGIN) FLUSH;
- buf[n++] = ' ';
- buf[n++] = '[';
- strcpy (&buf[n], longopt);
- n += strlen (longopt);
- if (opt->arg)
- {
- buf[n++] = '=';
- if (opt->is_optional)
- {
- buf[n++] = '[';
- strcpy (&buf[n], opt->arg);
- n += strlen (opt->arg);
- buf[n++] = ']';
- }
- else
- {
- strcpy (&buf[n], opt->arg);
- n += strlen (opt->arg);
- }
- }
- buf[n++] = ']';
- }
- }
-#endif
- FLUSH;
- free (idxbuf);
-}
-
-const char version_etc_copyright[] =
- /* Do *not* mark this string for translation. First %s is a copyright
- symbol suitable for this locale, and second %s are the copyright
- years. */
- "Copyright %s %s %s";
-
-void
-print_version_only(const char *program_version, FILE *stream)
-{
- fprintf (stream, "%s\n", program_version);
- /* TRANSLATORS: Translate "(C)" to the copyright symbol
- (C-in-a-circle), if this symbol is available in the user's
- locale. Otherwise, do not translate "(C)"; leave it as-is. */
- fprintf (stream, version_etc_copyright, _("(C)"),
- "_getopt_get_option(copyright_year, 2010)",
- "_getopt_get_option(copyright_holder)");
- fputc ('\n', stream);
-}
-
-_getopt_if_option_set([<authors>],[<
-char *program_author[] = {
-format_authors(_getopt_get_option(authors))
-};>])
-
-void (*print_version_hook)(FILE *stream);
-
-void
-print_version(const char *program_version, FILE *stream)
-{
- _getopt_if_option_set([<authors>],[<int i;
- unsigned width;
- const char *written_by = _("Written by ");
- /* TRANSLATORS: This string is used as a delimiter between authors' names
- as in:
-
- Written by Winnie the Pooh, Piglet ...
- */
- const char *middle_delim = _(", ");
- /* TRANSLATORS: This string acts as a delimiter before the last author's
- names, e.g.:
-
- Written by Winnie the Pooh, Piglet and Christopher Robin.
- */
- const char *final_delim = _(" and ");
-
->])
- print_version_only(program_version, stream);
-
-dnl **************************************************************************
-dnl This string cannot be split over serveal lines, because this would trigger
-dnl a bug in GNU M4 (version 1.4.9 and 1.4.10), which would insert #line
-dnl directives between the lines.
-dnl **************************************************************************
- fputs (_("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.\n\n"),
- stream);
- if (print_version_hook)
- print_version_hook (stream);
-_getopt_if_option_set([<authors>],[<
- width = strlen (written_by);
- fputs (written_by, stream);
- for (i = 0; ; )
- {
- char *author = program_author[i++];
- size_t len = strlen (author);
- const char *delim = NULL;
-
- if (program_author[i])
- {
- delim = program_author[i+1] ? middle_delim : final_delim;
- len += strlen (delim);
- }
- else
- len++;
- if (width + len > RMARGIN)
- {
- fputc ('\n', stream);
- width = 0;
- }
- fputs (author, stream);
- width += len;
- if (delim)
- fputs (delim, stream);
- else
- break;
- }
- fputc ('.', stream);
- fputc ('\n', stream);
->])
-}
+static struct grecs_proginfo proginfo = {
+ $2, /* progname */
+ ifelse([<$3>],,"",N_("$3")), /* docstring */
+ ifelse([<$4>],,"",N_("$4")), /* args_doc */
+ opthelp, /* opthelp */
+ sizeof(opthelp)/sizeof(opthelp[0]), /* optcount */
+ NULL, /* print_help_hook */
+ NULL, /* print_version_hook */
+ PACKAGE_NAME, /* package */
+ PACKAGE_VERSION, /* version */
+ NULL, /* license */
+_getopt_if_option_set([<copyright_year>],dnl
+ "[<_getopt_get_option(copyright_year)>]",NULL),/* copyright_year */
+_getopt_if_option_set([<copyright_holder>],dnl
+ "[<_getopt_get_option(copyright_holder)>]",NULL), /* copyright_holder */
+ NULL, /* *authors */
+ "<" PACKAGE_BUGREPORT ">", /* bug_address */
+ PACKAGE_URL, /* url */
+ NULL /* epilogue */
+};
+static struct grecs_node *cmdline_tree;
divert(-1)
-popdef([<ADDC>])
-popdef([<FLUSH>])
>])
define([<OPTIONS_BEGIN>],
@@ -789,22 +336,34 @@ _getopt_if_option_set([<gnu>],[<
GROUP([<Other options>])
OPTION([<help>],h,,[<Give this help list>])
BEGIN
- print_help ();
- exit (0);
+ grecs_print_help(&proginfo);
+ exit(0);
END
- OPTION([<usage>],,,[<Give a short usage message>])
+_getopt_if_option_set([<nousage>],,[<
+ OPTION([<usage>],,,[<Give a short usage message>])
BEGIN
- print_usage ();
- exit (0);
- END
+ grecs_print_usage(&proginfo);
+ exit(0);
+ END>])
+_getopt_if_option_set([<noversion>],,[<
OPTION([<version>],V,,[<Print program version>])
BEGIN
/* Give version */
- print_version(program_version, stdout);
- exit (0);
- END>])
+ grecs_print_version(&proginfo, stdout);
+ exit(0);
+ END>])>])
divert
+_getopt_if_option_set([<nostdincl>],,[<
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#ifdef HAVE_GETOPT_H
+# include <getopt.h>
+#endif
+#include <unistd.h>
+>])
#include <grecs.h>
+#include <grecsopt.h>
/* Option codes */
enum {
_OPTION_INIT=255,
@@ -817,12 +376,7 @@ static struct option long_options[] = {
{0, 0, 0, 0}
};
#endif
-static struct opthelp {
- const char *opt;
- const char *arg;
- int is_optional;
- const char *descr;
-} opthelp[] = {
+static struct grecs_opthelp opthelp[] = {
undivert(3)
};
undivert(5)

Return to:

Send suggestions and report system problems to the System administrator.