#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
+#include <unistd.h>
#if defined __OpenBSD__
#include <unistd.h>
guint help_enabled : 1;
guint ignore_unknown : 1;
guint strv_mode : 1;
+ guint strict_posix : 1;
GOptionGroup *main_group;
context = g_new0 (GOptionContext, 1);
context->parameter_string = g_strdup (parameter_string);
+ {
+ const char *argv[] = { "./a", "a", "-a", NULL };
+ /* Check to see if getopt will parse the "-a" or not. If it finds
+ * no arguments then we are in strict POSIX mode.
+ */
+ optind = 1;
+ context->strict_posix = getopt (3, (char **) argv, "a") != 'a';
+ }
context->help_enabled = TRUE;
context->ignore_unknown = FALSE;
}
/**
+ * g_option_context_set_strict_posix:
+ * @context: a #GoptionContext
+ *
+ * Sets strict POSIX mode.
+ *
+ * In strict POSIX mode, the first non-argument parameter encountered
+ * (eg: filename) terminates argument processing. Remaining arguments
+ * are treated as non-options and are not attempted to be parsed.
+ *
+ * If strict POSIX mode is disabled then parsing is done in the GNU way
+ * where option arguments can be freely mixed with non-options.
+ *
+ * As an example, consider "ls foo -l". With GNU style parsing, this
+ * will list "foo" in long mode. In strict POSIX style, this will list
+ * the files named "foo" and "-l".
+ *
+ * The default is system-dependent. In particular, on some systems, it
+ * may be modified by the POSIXLY_CORRECT environment variable.
+ *
+ * It may be useful to force strict POSIX mode when creating "verb
+ * style" command line tools. For example, the "gsettings" command line
+ * tool supports the global option "--schemadir" as well as many
+ * subcommands ("get", "set", etc.) which each have their own set of
+ * arguments. Using strict POSIX mode will allow parsing the global
+ * options up to the verb name while leaving the remaining options to be
+ * parsed by the relevant subcommand (which can be determined by
+ * examining the verb name, which should be present in argv[1] after
+ * parsing).
+ *
+ * Since: 2.44
+ **/
+void
+g_option_context_set_strict_posix (GOptionContext *context,
+ gboolean strict_posix)
+{
+ g_return_if_fail (context != NULL);
+
+ context->strict_posix = strict_posix;
+}
+
+/**
+ * g_option_context_get_strict_posix:
+ * @context: a #GoptionContext
+ *
+ * Returns whether strict POSIX code is enabled.
+ *
+ * See g_option_context_set_strict_posix() for more information.
+ *
+ * Since: 2.44
+ **/
+gboolean
+g_option_context_get_strict_posix (GOptionContext *context)
+{
+ g_return_val_if_fail (context != NULL, FALSE);
+
+ return context->strict_posix;
+}
+
+/**
* g_option_context_add_group:
* @context: a #GOptionContext
* @group: the group to add
}
else
{
+ if (context->strict_posix)
+ stop_parsing = TRUE;
+
/* Collect remaining args */
if (context->main_group &&
!parse_remaining_arg (context, context->main_group, &i,
GLIB_AVAILABLE_IN_ALL
gboolean g_option_context_get_ignore_unknown_options (GOptionContext *context);
+GLIB_AVAILABLE_IN_2_44
+void g_option_context_set_strict_posix (GOptionContext *context,
+ gboolean strict_posix);
+GLIB_AVAILABLE_IN_2_44
+gboolean g_option_context_get_strict_posix (GOptionContext *context);
+
GLIB_AVAILABLE_IN_ALL
void g_option_context_add_main_entries (GOptionContext *context,
const GOptionEntry *entries,
g_option_context_free (context);
}
+static gint
+option_context_parse_command_line (GOptionContext *context,
+ const gchar *command_line)
+{
+ gchar **argv;
+ guint argv_len, argv_new_len;
+ gboolean success;
+
+ argv = split_string (command_line, NULL);
+ argv_len = g_strv_length (argv);
+
+ success = g_option_context_parse_strv (context, &argv, NULL);
+ argv_new_len = g_strv_length (argv);
+
+ g_strfreev (argv);
+ return success ? argv_len - argv_new_len : -1;
+}
+
+static void
+test_strict_posix (void)
+{
+ GOptionContext *context;
+ gboolean foo;
+ gboolean bar;
+ GOptionEntry entries[] = {
+ { "foo", 'f', 0, G_OPTION_ARG_NONE, &foo, NULL, NULL },
+ { "bar", 'b', 0, G_OPTION_ARG_NONE, &bar, NULL, NULL },
+ { NULL }
+ };
+ gint n_parsed;
+
+ context = g_option_context_new (NULL);
+ g_option_context_add_main_entries (context, entries, NULL);
+
+ foo = bar = FALSE;
+ g_option_context_set_strict_posix (context, FALSE);
+ n_parsed = option_context_parse_command_line (context, "program --foo command --bar");
+ g_assert_cmpint (n_parsed, ==, 2);
+ g_assert (foo == TRUE);
+ g_assert (bar == TRUE);
+
+ foo = bar = FALSE;
+ g_option_context_set_strict_posix (context, TRUE);
+ n_parsed = option_context_parse_command_line (context, "program --foo command --bar");
+ g_assert_cmpint (n_parsed, ==, 1);
+ g_assert (foo == TRUE);
+ g_assert (bar == FALSE);
+
+ foo = bar = FALSE;
+ g_option_context_set_strict_posix (context, TRUE);
+ n_parsed = option_context_parse_command_line (context, "program --foo --bar command");
+ g_assert_cmpint (n_parsed, ==, 2);
+ g_assert (foo == TRUE);
+ g_assert (bar == TRUE);
+
+ foo = bar = FALSE;
+ g_option_context_set_strict_posix (context, TRUE);
+ n_parsed = option_context_parse_command_line (context, "program command --foo --bar");
+ g_assert_cmpint (n_parsed, ==, 0);
+ g_assert (foo == FALSE);
+ g_assert (bar == FALSE);
+
+ g_option_context_free (context);
+}
+
static void
flag_reverse_string (void)
{
g_test_add_func ("/option/group/main", test_main_group);
g_test_add_func ("/option/group/error-hook", test_error_hook);
g_test_add_func ("/option/group/parse", test_group_parse);
+ g_test_add_func ("/option/strict-posix", test_strict_posix);
/* Test that restoration on failure works */
g_test_add_func ("/option/restoration/int", error_test1);