2004-10-29 Matthias Clasen <mclasen@redhat.com>
+ * tests/option-test.c: Add tests for the handling of
+ non-option arguments, "--" and G_OPTION_REMAINING.
+
+ * glib/goption.[hc]: #define G_OPTION_REMAINING, which is
+ a special long option name, which can be used for an option
+ in the main group which collects the non-option arguments.
+ It must be of type G_OPTION_ARG_STRING_ARRAY or
+ G_OPTION_ARG_FILENAME_ARRAY. If the main group doesn't contain
+ an option whose name is G_OPTION_REMAINING, the non-option
+ arguments are left behind in argv as before.
+
* glib/goption.c: Add documentation.
2004-10-28 Matthias Clasen <mclasen@redhat.com>
2004-10-29 Matthias Clasen <mclasen@redhat.com>
+ * tests/option-test.c: Add tests for the handling of
+ non-option arguments, "--" and G_OPTION_REMAINING.
+
+ * glib/goption.[hc]: #define G_OPTION_REMAINING, which is
+ a special long option name, which can be used for an option
+ in the main group which collects the non-option arguments.
+ It must be of type G_OPTION_ARG_STRING_ARRAY or
+ G_OPTION_ARG_FILENAME_ARRAY. If the main group doesn't contain
+ an option whose name is G_OPTION_REMAINING, the non-option
+ arguments are left behind in argv as before.
+
* glib/goption.c: Add documentation.
2004-10-28 Matthias Clasen <mclasen@redhat.com>
2004-10-29 Matthias Clasen <mclasen@redhat.com>
+ * tests/option-test.c: Add tests for the handling of
+ non-option arguments, "--" and G_OPTION_REMAINING.
+
+ * glib/goption.[hc]: #define G_OPTION_REMAINING, which is
+ a special long option name, which can be used for an option
+ in the main group which collects the non-option arguments.
+ It must be of type G_OPTION_ARG_STRING_ARRAY or
+ G_OPTION_ARG_FILENAME_ARRAY. If the main group doesn't contain
+ an option whose name is G_OPTION_REMAINING, the non-option
+ arguments are left behind in argv as before.
+
* glib/goption.c: Add documentation.
2004-10-28 Matthias Clasen <mclasen@redhat.com>
2004-10-29 Matthias Clasen <mclasen@redhat.com>
+ * tests/option-test.c: Add tests for the handling of
+ non-option arguments, "--" and G_OPTION_REMAINING.
+
+ * glib/goption.[hc]: #define G_OPTION_REMAINING, which is
+ a special long option name, which can be used for an option
+ in the main group which collects the non-option arguments.
+ It must be of type G_OPTION_ARG_STRING_ARRAY or
+ G_OPTION_ARG_FILENAME_ARRAY. If the main group doesn't contain
+ an option whose name is G_OPTION_REMAINING, the non-option
+ arguments are left behind in argv as before.
+
* glib/goption.c: Add documentation.
2004-10-28 Matthias Clasen <mclasen@redhat.com>
2004-10-29 Matthias Clasen <mclasen@redhat.com>
+ * tests/option-test.c: Add tests for the handling of
+ non-option arguments, "--" and G_OPTION_REMAINING.
+
+ * glib/goption.[hc]: #define G_OPTION_REMAINING, which is
+ a special long option name, which can be used for an option
+ in the main group which collects the non-option arguments.
+ It must be of type G_OPTION_ARG_STRING_ARRAY or
+ G_OPTION_ARG_FILENAME_ARRAY. If the main group doesn't contain
+ an option whose name is G_OPTION_REMAINING, the non-option
+ arguments are left behind in argv as before.
+
* glib/goption.c: Add documentation.
2004-10-28 Matthias Clasen <mclasen@redhat.com>
* Boston, MA 02111-1307, USA.
*/
-#include "goption.h"
+#include "config.h"
#include "galias.h"
+
+#include "goption.h"
#include "glib.h"
#include "gi18n.h"
*
* Since: 2.6
*/
-void g_option_context_free (GOptionContext *context) {
-g_return_if_fail (context != NULL);
+void g_option_context_free (GOptionContext *context)
+{
+ g_return_if_fail (context != NULL);
g_list_foreach (context->groups, (GFunc)g_option_group_free, NULL);
g_list_free (context->groups);
/* Then we go through the entries */
for (i = 0; i < group->n_entries; i++)
{
+ if (group->entries[i].flags & G_OPTION_FLAG_HIDDEN)
+ continue;
+
len = g_utf8_strlen (group->entries[i].long_name, -1);
if (group->entries[i].short_name)
return TRUE;
}
+static gboolean
+parse_remaining_arg (GOptionContext *context,
+ GOptionGroup *group,
+ gint *index,
+ gint *argc,
+ gchar ***argv,
+ GError **error,
+ gboolean *parsed)
+{
+ gint j;
+
+ for (j = 0; j < group->n_entries; j++)
+ {
+ if (*index >= *argc)
+ return TRUE;
+
+ if (group->entries[j].long_name[0])
+ continue;
+
+ g_return_val_if_fail (group->entries[j].arg == G_OPTION_ARG_STRING_ARRAY ||
+ group->entries[j].arg == G_OPTION_ARG_FILENAME_ARRAY, FALSE);
+
+ add_pending_null (context, &((*argv)[*index]), NULL);
+
+ if (!parse_arg (context, group, &group->entries[j], (*argv)[*index], "", error))
+ return FALSE;
+
+ *parsed = TRUE;
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
static void
free_changes_list (GOptionContext *context,
gboolean revert)
if (argc && argv)
{
+ gboolean stop_parsing = FALSE;
+
for (i = 1; i < *argc; i++)
{
gchar *arg;
gboolean parsed = FALSE;
- if ((*argv)[i][0] == '-')
+ if ((*argv)[i][0] == '-' && !stop_parsing)
{
if ((*argv)[i][1] == '-')
{
if (*arg == 0)
{
add_pending_null (context, &((*argv)[i]), NULL);
- break;
+ stop_parsing = TRUE;
+ continue;
}
/* Handle help options */
goto fail;
}
}
+ else
+ {
+ /* Collect remaining args */
+ if (context->main_group &&
+ !parse_remaining_arg (context, context->main_group, &i,
+ argc, argv, error, &parsed))
+ goto fail;
+
+ }
}
/* Call post-parse hooks */
{
k -= i;
for (j = i + k; j < *argc; j++)
- (*argv)[j-k] = (*argv)[j];
+ {
+ (*argv)[j-k] = (*argv)[j];
+ (*argv)[j] = NULL;
+ }
*argc -= k;
}
}
group->translate_func = func;
group->translate_data = data;
- group->translate_notify = notify;
+ group->translate_notify = destroy_notify;
}
static gchar *
const gchar *arg_description;
};
+#define G_OPTION_REMAINING ""
+
GOptionContext *g_option_context_new (const gchar *parameter_string);
void g_option_context_free (GOptionContext *context);
void g_option_context_set_help_enabled (GOptionContext *context,
const gchar *domain);
-
-
-
G_END_DECLS
#endif /* __G_OPTION_H__ */
g_option_context_free (context);
}
+/* check that non-option arguments are left in argv by default */
+void
+rest_test1 (void)
+{
+ GOptionContext *context;
+ gboolean retval;
+ GError *error = NULL;
+ gchar **argv;
+ int argc;
+ GOptionEntry entries [] = {
+ { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
+ { NULL }
+ };
+
+ context = g_option_context_new (NULL);
+ g_option_context_add_main_entries (context, entries, NULL);
+
+ /* Now try parsing */
+ argv = split_string ("program foo --test bar", &argc);
+
+ retval = g_option_context_parse (context, &argc, &argv, &error);
+ g_assert (retval);
+
+ /* Check array */
+ g_assert (ignore_test1_boolean);
+ g_assert (strcmp (argv[0], "program") == 0);
+ g_assert (strcmp (argv[1], "foo") == 0);
+ g_assert (strcmp (argv[2], "bar") == 0);
+ g_assert (argv[3] == NULL);
+
+ g_strfreev (argv);
+ g_option_context_free (context);
+}
+
+/* check that -- works */
+void
+rest_test2 (void)
+{
+ GOptionContext *context;
+ gboolean retval;
+ GError *error = NULL;
+ gchar **argv;
+ int argc;
+ GOptionEntry entries [] = {
+ { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
+ { NULL }
+ };
+
+ context = g_option_context_new (NULL);
+ g_option_context_add_main_entries (context, entries, NULL);
+
+ /* Now try parsing */
+ argv = split_string ("program foo --test -- -bar", &argc);
+
+ retval = g_option_context_parse (context, &argc, &argv, &error);
+ g_assert (retval);
+
+ /* Check array */
+ g_assert (ignore_test1_boolean);
+ g_assert (strcmp (argv[0], "program") == 0);
+ g_assert (strcmp (argv[1], "foo") == 0);
+ g_assert (strcmp (argv[2], "-bar") == 0);
+ g_assert (argv[3] == NULL);
+
+ g_strfreev (argv);
+ g_option_context_free (context);
+}
+
+/* check that G_OPTION_REMAINING collects non-option arguments */
+void
+rest_test3 (void)
+{
+ GOptionContext *context;
+ gboolean retval;
+ GError *error = NULL;
+ gchar **argv;
+ int argc;
+ GOptionEntry entries [] = {
+ { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
+ { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL },
+ { NULL }
+ };
+
+ context = g_option_context_new (NULL);
+ g_option_context_add_main_entries (context, entries, NULL);
+
+ /* Now try parsing */
+ argv = split_string ("program foo --test bar", &argc);
+
+ retval = g_option_context_parse (context, &argc, &argv, &error);
+ g_assert (retval);
+
+ /* Check array */
+ g_assert (ignore_test1_boolean);
+ g_assert (strcmp (array_test1_array[0], "foo") == 0);
+ g_assert (strcmp (array_test1_array[1], "bar") == 0);
+ g_assert (array_test1_array[2] == NULL);
+
+ g_strfreev (array_test1_array);
+
+ g_strfreev (argv);
+ g_option_context_free (context);
+}
+
+
+/* check that G_OPTION_REMAINING and -- work together */
+void
+rest_test4 (void)
+{
+ GOptionContext *context;
+ gboolean retval;
+ GError *error = NULL;
+ gchar **argv;
+ int argc;
+ GOptionEntry entries [] = {
+ { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
+ { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL },
+ { NULL }
+ };
+
+ context = g_option_context_new (NULL);
+ g_option_context_add_main_entries (context, entries, NULL);
+
+ /* Now try parsing */
+ argv = split_string ("program foo --test -- -bar", &argc);
+
+ retval = g_option_context_parse (context, &argc, &argv, &error);
+ g_assert (retval);
+
+ /* Check array */
+ g_assert (ignore_test1_boolean);
+ g_assert (strcmp (array_test1_array[0], "foo") == 0);
+ g_assert (strcmp (array_test1_array[1], "-bar") == 0);
+ g_assert (array_test1_array[2] == NULL);
+
+ g_strfreev (array_test1_array);
+
+ g_strfreev (argv);
+ g_option_context_free (context);
+}
+
+/* test that G_OPTION_REMAINING works with G_OPTION_ARG_FILENAME_ARRAY */
+void
+rest_test5 (void)
+{
+ GOptionContext *context;
+ gboolean retval;
+ GError *error = NULL;
+ gchar **argv;
+ int argc;
+ GOptionEntry entries [] = {
+ { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
+ { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &array_test1_array, NULL, NULL },
+ { NULL }
+ };
+
+ context = g_option_context_new (NULL);
+ g_option_context_add_main_entries (context, entries, NULL);
+
+ /* Now try parsing */
+ argv = split_string ("program foo --test bar", &argc);
+
+ retval = g_option_context_parse (context, &argc, &argv, &error);
+ g_assert (retval);
+
+ /* Check array */
+ g_assert (ignore_test1_boolean);
+ g_assert (strcmp (array_test1_array[0], "foo") == 0);
+ g_assert (strcmp (array_test1_array[1], "bar") == 0);
+ g_assert (array_test1_array[2] == NULL);
+
+ g_strfreev (array_test1_array);
+
+ g_strfreev (argv);
+ g_option_context_free (context);
+}
+
+
int
main (int argc, char **argv)
{
empty_test2 ();
empty_test3 ();
+ /* Test handling of rest args */
+ rest_test1 ();
+ rest_test2 ();
+ rest_test3 ();
+ rest_test4 ();
+ rest_test5 ();
+
return 0;
}