summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2018-11-27 13:05:18 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2018-12-07 18:27:03 (GMT)
commit9097d5294cf62c4cb7cd5e352e1d0c42d3c04d81 (patch) (side-by-side diff)
tree4e40c0af4dae891f38cfc466edcc7e0a3331b267
parent1202780fd92ff9fc2854bfa2d0ab0c39169eabd5 (diff)
downloadgrecs-9097d5294cf62c4cb7cd5e352e1d0c42d3c04d81.tar.gz
grecs-9097d5294cf62c4cb7cd5e352e1d0c42d3c04d81.tar.bz2
Revise getopt.m4
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--build-aux/getopt.m4240
1 files changed, 177 insertions, 63 deletions
diff --git a/build-aux/getopt.m4 b/build-aux/getopt.m4
index 93d81df..85e930e 100644
--- a/build-aux/getopt.m4
+++ b/build-aux/getopt.m4
@@ -1,5 +1,5 @@
dnl This file is part of grecs
-dnl Copyright (C) 2007-2016 Sergey Poznyakoff
+dnl Copyright (C) 2007-2018 Sergey Poznyakoff
dnl
dnl Grecs is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
@@ -17,6 +17,27 @@ divert(-1)
changequote([<,>])
changecom(/*,*/)
+dnl Diversion channels
+define([<__DIV_OPTKEYS__>],1)dnl option keys
+define([<__DIV_OPTDECL__>],2)dnl struct option declarations
+define([<__DIV_HELPDECL__>],3)dnl grecs_opthelp declarations
+define([<__DIV_SWITCH__>],4)dnl switch statement body
+define([<__DIV_STATIC__>],5)dnl module static data
+
+dnl Special macros that can be set during expansion
+pushdef([<__GETOPT_DEFINED__>])
+pushdef([<__OPTIONS_END_DEFINED__>])
+pushdef([<__GETOPT_LASTOPT_LABEL__>])
+
+define([<__GETOPT_LONG_TAG>])
+define([<__GETOPT_SHORT_TAG>])
+
+define([<WITH_DIVERSION>],[<ifelse([<$#>],0,[<[<$0>]>],[<dnl
+pushdef([<__GETOPT_DIVERSION__>],divnum)dnl
+divert([<$1>])$2dnl
+divert(__GETOPT_DIVERSION__)dnl
+popdef([<__GETOPT_DIVERSION__>])>])>])
+
dnl _getopt_mangle_option(NAME)
dnl ---------------------------
dnl Convert NAME to a valid m4 identifier, by replacing invalid characters
@@ -33,7 +54,7 @@ define([<_getopt_set_option>],
[<_getopt_mangle_option(\1),[<\2>]>]))>])>])
dnl _getopt_get_option(NAME[,DEFAULT])
-dnl ------------------------------
+dnl ----------------------------------
define([<_getopt_get_option>],
[<_getopt_if_option_set($1,[<indir(_getopt_mangle_option($1))>],[<$2>])>])
@@ -44,7 +65,7 @@ define([<_getopt_if_option_set>],
[<ifdef(_getopt_mangle_option([<$1>]),[<$2>],[<$3>])>])
dnl _getopt_if_option_null(NAME,IF-NULL,IF-NOT-NULL)
-dnl ---------------------------------------------
+dnl ------------------------------------------------
dnl Check if option NAME is set.
define([<_getopt_if_option_null>],
[<ifelse(indir(_getopt_mangle_option([<$1>])),,[<$2>],[<$3>])>])
@@ -61,7 +82,7 @@ define([<_getopt_option_switch>],
[<_getopt_option_switch(shift(shift($@)))>])>])>])
dnl _getopt_if_option_val(NAME,val,IF-TRUE,IF-FALSE)
-dnl ---------------------------------------------
+dnl ------------------------------------------------
dnl Check if option NAME is set.
define([<_getopt_if_option_val>],
[<ifelse(_getopt_get_option([<$1>]),[<$2>],[<$3>],[<$4>])>])
@@ -89,34 +110,39 @@ define([<_getopt_set_options>],
_getopt_set_options(shift($@))>])>])
dnl __getopt_format_authors(name[,name...])
-dnl ------------------------------
+dnl ---------------------------------------
define([<__getopt_format_authors>],dnl
[<ifelse([<$1>],,NULL,[<"$1",
__getopt_format_authors(shift($@))>])>])
dnl __getopt_upcase(ARGS...)
+dnl ------------------------
dnl Concatenate and convert ARGS to upper case.
dnl
define([<__getopt_upcase>], [<translit([<$*>], [<a-z>], [<A-Z>])>])
dnl __getopt_concat(ARGS...)
+dnl ------------------------
dnl Concatenate arguments, inserting ", " between each pair of them.
dnl
define([<__getopt_concat>],[<ifelse([<$#>],1,[<$1>],[<$1, __getopt_concat(shift($@))>])>])
dnl __getopt_flushleft(ARGS...)
+dnl ---------------------------
dnl Concatenate ARGS and remove any leading whitespace
dnl
define([<__getopt_flushleft>],
[<patsubst([<__getopt_concat($*)>], [<^[ ]+>])>])
dnl __getopt_chop(ARGS...)
+dnl ----------------------
dnl Concatenate ARGS and remove any trailing whitespace
dnl
define([<__getopt_chop>],
[<patsubst([<$*>], [<[ ]+$>])>])
dnl __getopt_escape(ARGS...)
+dnl ------------------------
dnl Concatenate ARGS and escape any occurrences of double-quotes with
dnl backslashes.
dnl
@@ -124,6 +150,7 @@ define([<__getopt_escape>],
[<patsubst([<__getopt_concat($*)>],[<[\"]>],[<\\\&>])>])
dnl __getopt_prep(ARG)
+dnl ------------------
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.
@@ -133,46 +160,56 @@ define([<__getopt_prep>],
+[ ]*>],[< >])))>])
dnl __GETOPT_SHORT_OPTS
+dnl -------------------
dnl Accumulator for the 3rd argument of getopt_long
dnl
define([<__GETOPT_SHORT_OPTS>],[<_getopt_if_option_set([<nopermute>],+)>])
dnl GROUP(STRING)
+dnl -------------
dnl Begin a named group of options
dnl
-define([<GROUP>],[<dnl
-divert(3)
+define([<GROUP>],[<ifelse([<$#>],0,[<[<$0>]>],[<dnl
+WITH_DIVERSION(__DIV_HELPDECL__,[<dnl
{ NULL, NULL, 0, N_("__getopt_prep([<$1>])") },
-divert(-1)>])
+>])>])>])
# __getopt_quote(args) - convert args to single-quoted string
-define([<__getopt_quote>], [<ifelse([<$#>], [<0>], [<>], [<[<$*>]>])>])
-define([<__getopt_dquote>], [<[<$@>]>])
+define([<__getopt_quote>], [<ifelse([<$*>], [<>], [<>], [<[<$*>]>])>])
+define([<__getopt_dquote>], [<ifelse([<$*>], [<>], [<>], [<[<$@>]>])>])
+
+# __getopt_ifempty(LIST, IF-TRUE [, IF-FALSE])
+# --------------------------------------------
+# Expands to IF-TRUE if LIST is not empty, otherwise to IF-FALSE.
+#
+define([<__getopt_ifempty>], [<ifelse([<$1>],[<>],[<$2>],[<$3>])>])
define([<__GATHER_OPTIONS>],[<
pushdef([<__GETOPT_KEY>],ifelse([<$2>],,[<OPTION_>]__getopt_upcase(patsubst($1,-,_)),'$2'))
ifelse([<$2>],,[<
-divert(1)
+WITH_DIVERSION(__DIV_OPTKEYS__,[<dnl
__GETOPT_KEY,
-divert(-1)
->])
+>])>])
define([<__GETOPT_SELECTOR>],ifdef([<__GETOPT_SELECTOR>],__GETOPT_SELECTOR) case __GETOPT_KEY:)
ifelse([<$1>],,,[<
-divert(2)
+WITH_DIVERSION(__DIV_OPTDECL__,[<dnl
{ "$1", __GETOPT_ARGTYPE, 0, __GETOPT_KEY },
-divert(-1)>])
+>])>])
dnl
define([<__GETOPT_SHORT_OPTS>],__getopt_dquote(__GETOPT_SHORT_OPTS[<>]dnl
ifelse([<$2>],,,[<$2>]ifelse(__GETOPT_ARGTYPE,[<no_argument>],,__GETOPT_ARGTYPE,[<required_argument>],:,__GETOPT_ARGTYPE,[<optional_argument>],::))))
dnl
ifelse([<$1>],,,dnl
-[<define([<__GETOPT_LONG_TAG>],ifelse(__GETOPT_LONG_TAG,,[<--$1>],[<__GETOPT_LONG_TAG; --$1>]))>])
+[<define([<__GETOPT_LONG_TAG>],
+__getopt_ifempty(__getopt_quote(__GETOPT_LONG_TAG),__getopt_dquote(__getopt_dquote(--$1)),[<__getopt_quote(__getopt_dquote(__GETOPT_LONG_TAG), __getopt_dquote([< --$1>]))>]))>])
ifelse([<$2>],,,dnl
-[<define([<__GETOPT_SHORT_TAG>],ifelse(__GETOPT_SHORT_TAG,,[<-$2>],[<__GETOPT_SHORT_TAG; -$2>]))>])
+[<define([<__GETOPT_SHORT_TAG>],
+__getopt_ifempty(__getopt_quote(__GETOPT_SHORT_TAG),__getopt_dquote(__getopt_dquote(-$2)),[<__getopt_quote(__getopt_dquote(__GETOPT_SHORT_TAG), __getopt_dquote([< -$2>]))>]))>])
popdef([<__GETOPT_KEY>])
>])
dnl OPTION(long-opt, short-opt, [arg], [descr])
+dnl -------------------------------------------
dnl Introduce a command line option. Arguments:
dnl long-opt Long option.
dnl short-opt Short option (a single char)
@@ -189,7 +226,7 @@ dnl
dnl If descr is not given the option will not appear in the --help and
dnl --usage outputs.
dnl
-define([<OPTION>],[<
+define([<OPTION>],[<ifelse([<$#>],0,[<[<$0>]>],[<
pushdef([<__GETOPT_LONG_TAG>])
pushdef([<__GETOPT_SHORT_TAG>])
pushdef([<__GETOPT_SELECTOR>])
@@ -200,43 +237,47 @@ pushdef([<__GETOPT_ARGTYPE>],[<ifelse([<$3>],,[<no_argument>],dnl
patsubst([<$3>],[<\[.*\]>]),,[<optional_argument>],dnl
[<required_argument>])>])
__GATHER_OPTIONS($@)
->])
+define([<BEGIN>],[<__GETOPT_API_BEGIN>])
+>])>])
dnl ALIAS(long-opt, short-opt)
+dnl --------------------------
dnl Declare aliases for the previous OPTION statement.
dnl long-opt Long option.
dnl short-opt Short option (a single char)
dnl (At least one of long-opt or short-opt must be present)
dnl An OPTION statement may be followed by any number of ALIAS statements.
dnl
-define([<ALIAS>],[<
+define([<ALIAS>],[<ifelse([<$#>],0,[<[<$0>]>],[<
__GATHER_OPTIONS($1,$2)
->])
+>])>])
dnl BEGIN
+dnl -----
dnl Start an action associated with the declared option. Must follow OPTION
dnl statement, with optional ALIAS statements in between.
dnl
-define([<BEGIN>],[<
+define([<__GETOPT_API_BEGIN>],[<
+undefine([<BEGIN>])
+define([<END>],[<__GETOPT_API_END>])
+define([<LASTOPT>],[<__GETOPT_API_LASTOPT>])
ifelse(__GETOPT_HIDDEN,1,,[<
-divert(3)
+WITH_DIVERSION(__DIV_HELPDECL__,[<dnl
{
#ifdef HAVE_GETOPT_LONG
- "translit(dnl
-ifelse(__GETOPT_SHORT_TAG,,__GETOPT_LONG_TAG,[<__GETOPT_SHORT_TAG[<>]ifelse(__GETOPT_LONG_TAG,,,; __GETOPT_LONG_TAG)>]),
- [<;>],[<,>])",
+ "__getopt_ifempty(__getopt_quote(__GETOPT_SHORT_TAG),__getopt_quote(__GETOPT_LONG_TAG),[<__getopt_quote(__GETOPT_SHORT_TAG)__getopt_ifempty(__getopt_quote(__GETOPT_LONG_TAG),,[<, __getopt_quote(__GETOPT_LONG_TAG)>])>])",
#else
- "translit(__GETOPT_SHORT_TAG, [<;>],[<,>])",
+ "__GETOPT_SHORT_TAG",
#endif
ifelse(__GETOPT_ARGNAME,,[<NULL, 0>],
[<ifelse(__GETOPT_ARGTYPE,[<optional_argument>],
[<N_(>]"[<patsubst(__GETOPT_ARGNAME,[<\[\(.*\)\]>],[<\1>])>][<"), 1>],[<N_("__GETOPT_ARGNAME"), 0>])>]), N_("__GETOPT_DOCSTRING") },
-divert(-1)>])
+>])>])
popdef([<__GETOPT_ARGTYPE>])
popdef([<__GETOPT_ARGNAME>])
popdef([<__GETOPT_DOCSTRING>])
popdef([<__GETOPT_HIDDEN>])
-divert(4)dnl
+divert(__DIV_SWITCH__)dnl
popdef([<__GETOPT_LONG_TAG>])dnl
popdef([<__GETOPT_SHORT_TAG>])dnl
__GETOPT_SELECTOR
@@ -244,31 +285,43 @@ popdef([<__GETOPT_SHORT_TAG>])dnl
>])
dnl END
+dnl ---
dnl Finish the associated action
dnl
-define([<END>],[<
+define([<__GETOPT_API_END>],[<
break;
}
divert(-1)
+undefine([<END>])
+undefine([<ALIAS>])
+undefine([<LASTOPT>])
popdef([<__GETOPT_SELECTOR>])>])
dnl OPTNODE(name, value)
-define([<OPTNODE>],[<do {
+dnl --------------------
+define([<OPTNODE>],[<ifelse([<$#>],0,[<[<$0>]>],[<dnl
+WITH_DIVERSION(__DIV_STATIC__,[<
+static struct grecs_node *cmdline_tree;
+>]);
+do {
struct grecs_node *node = grecs_node_from_path($1, $2);
if (!cmdline_tree)
cmdline_tree = node;
else
grecs_node_bind(cmdline_tree, node, 0);
} while(0)
->])
+>])>])
dnl LASTOPT()
-dnl Stop option processing (as if "--" has been encountered
-define([<LASTOPT>],[<dnl
-define([<__GETOPT_LASTOPT>],[<lastoptlab:>])dnl
+dnl ---------
+dnl Stop option processing (as if "--" has been encountered)
+define([<__GETOPT_API_LASTOPT>],[<dnl
+pushdef([<__GETOPT_LASTOPT_LABEL__>],[<lastoptlab:
+popdef([<__GETOPT_LASTOPT_LABEL__>])>])dnl
goto lastoptlab>])
dnl GETOPT(argc, argv, [long_index], [onerr])
+dnl -----------------------------------------
dnl Emit option parsing code. Arguments:
dnl
dnl argc Name of the 1st argument to getopt_long.
@@ -277,7 +330,8 @@ dnl long_index 5th argument to getopt_long. If not given,
dnl NULL will be passed.
dnl onerr Action to take if parsing fails.
dnl
-define([<GETOPT>],[<
+define([<GETOPT>],[<ifelse([<$#>],0,[<[<$0>]>],[<dnl
+pushdef([<__GETOPT_DEFINED__>],1)
{
int c;
@@ -294,35 +348,40 @@ define([<GETOPT>],[<
default:
ifelse([<$4>],,,[<$4;>])dnl
exit(EX_USAGE);
- undivert(4)
+ undivert(__DIV_SWITCH__)
}
}
-__GETOPT_LASTOPT
+__GETOPT_LASTOPT_LABEL__()dnl
ifelse([<$3>],,[<
if (optind < argc) {
fprintf(stderr, "%s: unexpected arguments\n", $2[0]);
exit(EX_USAGE);
}
>],[<$3 = optind;>])
+ifelse(__GETOPT_CMDLINE_TREE_NEEDED__,1,[<
if (cmdline_tree)
{
struct grecs_node *rn = grecs_node_create(grecs_node_root, NULL);
rn->down = cmdline_tree;
cmdline_tree = rn;
}
+>])dnl
}
->])
+>])>])
define([<_getopt_sc_array>],
[<ifelse([<$1>],,,[<[<"$1", >]_getopt_sc_array(shift($@))>])>])
-define([<STDFUNC>],[<
-divert(5)
+define([<STDFUNC>],[<ifelse([<$#>],0,[<[<$0>]>],[<
+WITH_DIVERSION(__DIV_STATIC__,[<
ifelse([<$3>],,,[<
static char *subcommands[] = {
_getopt_sc_array($3)
NULL
};>])
+#ifndef PACKAGE_URL
+# define PACKAGE_URL NULL
+#endif
static struct grecs_proginfo proginfo = {
$2, /* progname */
ifelse([<$3>],,NULL,subcommands), /* subcommands */
@@ -344,33 +403,59 @@ _getopt_if_option_set([<copyright_holder>],dnl
PACKAGE_URL, /* url */
NULL /* epilogue */
};
-static struct grecs_node *cmdline_tree;
_getopt_if_option_set([<program_version>],dnl
[<const char *_getopt_if_option_null(program_version,program_version,[<_getopt_get_option(program_version)>]) = $2 " (" PACKAGE_NAME ") " PACKAGE_VERSION;
->])
-divert(-1)
->])
-
-define([<OPTIONS_BEGIN>],
- [<divert(-1)
- define([<__GETOPT_LASTOPT>])
+>])>])>])>])
+
+dnl OPTIONS_BEGIN(PROGNAME, DOCSTR, [ARGDOC], [OPTS...])
+dnl ----------------------------------------------------
+dnl Begins option definition section. Arguments:
+dnl PROGNAME - canonical program name,
+dnl DOCSTR - usage string to be displayed in --help output.
+dnl ARGDOC - docstring for arguments
+dnl
+dnl Optional arguments (OPTS):
+dnl nostdincl - don't emit C include statements for standard include files
+dnl nopermute - don't permute arguments, i.e. don't accept intermixed
+dnl optional and positional arguments
+dnl
+dnl gnu - emit code for --help (-h), --version (-V) and --usage
+dnl options.
+dnl Options bellow modify the effect of the 'gnu' option:
+dnl
+dnl nousage - disable support for the --usage option
+dnl noversion - disable support for the --version option
+dnl
+dnl copyright_year=Y
+dnl Year, or range, or list of years to display in
+dnl the copyright statement. Default is 2012 (why?)
+dnl copyright_holder=NAME
+dnl Copyright holder name. Default is 'Free Software Foundation,
+dnl inc.'
+dnl program_version=V
+dnl Version string. Defaults to PACKAGE_VERSION autoconf define.
+dnl
+define([<OPTIONS_BEGIN>],[<ifelse([<$#>],0,[<[<$0>]>],
+ [<divert(-1)
_getopt_set_options(shift(shift(shift($@))))
+ pushdef([<__GETOPT_EXPECT_ARGS__>],ifelse(__getopt_quote($3),,0,1))
_getopt_if_option_set([<gnu>],
[<STDFUNC([<$1 " (" PACKAGE_NAME ") " PACKAGE_VERSION>],
- [<$1>], [<>], [<$2>], [<$3>])>])
->])
+ [<$1>], [<>], [<$2>], [<$3>])>])>])>])
+
-define([<OPTIONS_COMMAND_BEGIN>],
+define([<OPTIONS_COMMAND_BEGIN>],[<ifelse([<$#>],0,[<[<$0>]>],
[<divert(-1)
- define([<__GETOPT_LASTOPT>])
_getopt_set_options(shift(shift(shift(shift($@)))))
+ pushdef([<__GETOPT_EXPECT_ARGS__>],ifelse(__getopt_quote($3),,0,1))
_getopt_if_option_set([<gnu>],
[<STDFUNC([<$1 " (" PACKAGE_NAME ") " PACKAGE_VERSION>],
[<$1>], [<$2>], [<$3>], [<$4>])>])
->])
+>])>])
define([<OPTIONS_END>],[<
+pushdef([<__OPTIONS_END_DEFINED__>],1)
_getopt_if_option_set([<gnu>],[<
GROUP([<Other options>])
OPTION([<help>],h,,[<Give this help list>])
@@ -387,40 +472,69 @@ _getopt_if_option_set([<nousage>],,[<
_getopt_if_option_set([<noversion>],,[<
OPTION([<version>],V,,[<Print program version>])
BEGIN
- /* Give version */
+ /* Give version */
grecs_print_version(&proginfo, stdout);
exit(0);
END>])>])
-divert
-_getopt_if_option_set([<nostdincl>],,[<
-#ifdef HAVE_CONFIG_H
+divert(0)dnl
+_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 <stdlib.h>
+>])dnl
#include <grecs.h>
#include <grecs/opt.h>
+#ifndef [<EX_USAGE>]
+# define [<EX_USAGE>] 64
+#endif
/* Option codes */
enum {
_OPTION_INIT=255,
- undivert(1)
+undivert(__DIV_OPTKEYS__)dnl
MAX_OPTION
};
#ifdef HAVE_GETOPT_LONG
static struct option long_options[] = {
- undivert(2)
+undivert(__DIV_OPTDECL__)dnl
{0, 0, 0, 0}
};
#endif
+_getopt_if_option_set([<gnu>],[<
static struct grecs_opthelp opthelp[] = {
- undivert(3)
+undivert(__DIV_HELPDECL__)dnl
};
-undivert(5)
+>],[<WITH_DIVERSION(-1,[<undivert(__DIV_HELPDECL__)>])>])dnl
+undivert(__DIV_STATIC__)
>])
+m4wrap([<ifelse(__OPTIONS_END_DEFINED__,1,,[<OPTIONS_END()>])dnl
+ifelse(__GETOPT_DEFINED__,1,,[<divert(0)dnl
+ifelse(__GETOPT_EXPECT_ARGS__,1,[<
+int
+parse_options(int argc, char **argv, int *idx)
+{
+ GETOPT(argc, argv, *idx)
+ return 0;
+}
+>],[<
+int
+parse_options(int argc, char **argv)
+{
+ GETOPT(argc, argv)
+ return 0;
+}
+>])
+divert(-1)
+popdef([<__GETOPT_DEFINED__>])
+popdef([<__GETOPT_EXPECT_ARGS__>])
+popdef([<__OPTIONS_END_DEFINED__>])
+popdef([<__GETOPT_LASTOPT_LABEL__>])>])>])
+
divert(0)dnl
/* -*- buffer-read-only: t -*- vi: set ro:
THIS FILE IS GENERATED AUTOMATICALLY. PLEASE DO NOT EDIT.

Return to:

Send suggestions and report system problems to the System administrator.