From 3a7a09668253973235e7e48fcaf9b06051c8c3b2 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 18 Jun 2005 04:55:26 +0000 Subject: [PATCH] Add G_OPTION_FLAG_NO_ARG and G_OPTION_FLAG_FILENAME to allow greater 2005-06-18 Matthias Clasen * glib/goption.h: * glib/goption.c: Add G_OPTION_FLAG_NO_ARG and G_OPTION_FLAG_FILENAME to allow greater control of G_OPTION_ARG_CALLBACK options. (#302632, Dan Winship) * tests/option-test.c: test callback args --- ChangeLog | 9 ++++ ChangeLog.pre-2-10 | 9 ++++ ChangeLog.pre-2-12 | 9 ++++ ChangeLog.pre-2-8 | 9 ++++ docs/reference/ChangeLog | 5 +++ docs/reference/glib/tmpl/option.sgml | 11 +++-- glib/goption.c | 31 ++++++++++---- glib/goption.h | 4 +- tests/option-test.c | 79 ++++++++++++++++++++++++++++++++++++ 9 files changed, 153 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 47afe36..cd102ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2005-06-18 Matthias Clasen + + * glib/goption.h: + * glib/goption.c: Add G_OPTION_FLAG_NO_ARG and + G_OPTION_FLAG_FILENAME to allow greater control of + G_OPTION_ARG_CALLBACK options. (#302632, Dan Winship) + + * tests/option-test.c: test callback args + 2005-06-14 Theppitak Karoonboonyanan * configure.in: Added 'th' (Thai) to ALL_LINGUAS. diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 47afe36..cd102ae 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,12 @@ +2005-06-18 Matthias Clasen + + * glib/goption.h: + * glib/goption.c: Add G_OPTION_FLAG_NO_ARG and + G_OPTION_FLAG_FILENAME to allow greater control of + G_OPTION_ARG_CALLBACK options. (#302632, Dan Winship) + + * tests/option-test.c: test callback args + 2005-06-14 Theppitak Karoonboonyanan * configure.in: Added 'th' (Thai) to ALL_LINGUAS. diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 47afe36..cd102ae 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,12 @@ +2005-06-18 Matthias Clasen + + * glib/goption.h: + * glib/goption.c: Add G_OPTION_FLAG_NO_ARG and + G_OPTION_FLAG_FILENAME to allow greater control of + G_OPTION_ARG_CALLBACK options. (#302632, Dan Winship) + + * tests/option-test.c: test callback args + 2005-06-14 Theppitak Karoonboonyanan * configure.in: Added 'th' (Thai) to ALL_LINGUAS. diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 47afe36..cd102ae 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,12 @@ +2005-06-18 Matthias Clasen + + * glib/goption.h: + * glib/goption.c: Add G_OPTION_FLAG_NO_ARG and + G_OPTION_FLAG_FILENAME to allow greater control of + G_OPTION_ARG_CALLBACK options. (#302632, Dan Winship) + + * tests/option-test.c: test callback args + 2005-06-14 Theppitak Karoonboonyanan * configure.in: Added 'th' (Thai) to ALL_LINGUAS. diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index 9e7d06d..9b13ec6 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,8 @@ +2005-06-18 Matthias Clasen + + * glib/tmpl/option.sgml (GOptionFlags): document + G_OPTION_FLAG_NO_ARG and G_OPTION_FLAG_FILENAME (Dan Winship) + 2005-06-16 Mathieu Lacage * gobject/tut_gtype.xml: fix typo reported by Hong Gang XU. diff --git a/docs/reference/glib/tmpl/option.sgml b/docs/reference/glib/tmpl/option.sgml index 3aa2c1b..d0f6acd 100644 --- a/docs/reference/glib/tmpl/option.sgml +++ b/docs/reference/glib/tmpl/option.sgml @@ -124,9 +124,6 @@ main (int argc, char *argv[]) - - - Error codes returned by option parsing. @@ -267,8 +264,14 @@ Flags which modify individual options. output. @G_OPTION_FLAG_IN_MAIN: The option appears in the main section of the output, even if it is defined in a group. -@G_OPTION_FLAG_REVERSE: For options of the G_OPTION_ARG_NONE kind, this flag +@G_OPTION_FLAG_REVERSE: For options of the %G_OPTION_ARG_NONE kind, this flag indicates that the sense of the option is reversed. +@G_OPTION_FLAG_NO_ARG: For options of the %G_OPTION_ARG_CALLBACK kind, + this flag indicates that the callback does not take any argument + (like a %G_OPTION_ARG_NONE option). Since 2.8 +@G_OPTION_FLAG_FILENAME: For options of the %G_OPTION_ARG_CALLBACK + kind, this flag indicates that the argument should be passed to the + callback in the GLib filename encoding rather than UTF-8. Since 2.8 diff --git a/glib/goption.c b/glib/goption.c index 4f2d2b6..78a66c7 100644 --- a/glib/goption.c +++ b/glib/goption.c @@ -33,6 +33,10 @@ #define TRANSLATE(group, str) (((group)->translate_func ? (* (group)->translate_func) ((str), (group)->translate_data) : (str))) +#define NO_ARG(entry) ((entry)->arg == G_OPTION_ARG_NONE || \ + ((entry)->arg == G_OPTION_ARG_CALLBACK && \ + ((entry)->flags & G_OPTION_FLAG_NO_ARG))) + typedef struct { GOptionArg arg_type; @@ -393,7 +397,7 @@ calculate_max_length (GOptionGroup *group) if (entry->short_name) len += 4; - if (entry->arg != G_OPTION_ARG_NONE && entry->arg_description) + if (!NO_ARG (entry) && entry->arg_description) len += 1 + g_utf8_strlen (TRANSLATE (group, entry->arg_description), -1); max_length = MAX (max_length, len); @@ -847,17 +851,28 @@ parse_arg (GOptionContext *context, } case G_OPTION_ARG_CALLBACK: { - gchar *tmp; + gchar *data; gboolean retval; - tmp = g_locale_to_utf8 (value, -1, NULL, NULL, error); + if (entry->flags & G_OPTION_FLAG_NO_ARG) + data = NULL; + else if (entry->flags & G_OPTION_FLAG_FILENAME) + { +#ifdef G_OS_WIN32 + data = g_locale_to_utf8 (value, -1, NULL, NULL, error); +#else + data = g_strdup (value); +#endif + } + else + data = g_locale_to_utf8 (value, -1, NULL, NULL, error); - if (!value) + if (!(entry->flags & G_OPTION_FLAG_NO_ARG) && !data) return FALSE; - retval = (* (GOptionArgFunc) entry->arg_data) (option_name, tmp, group->user_data, error); + retval = (* (GOptionArgFunc) entry->arg_data) (option_name, data, group->user_data, error); - g_free (tmp); + g_free (data); return retval; @@ -887,7 +902,7 @@ parse_short_option (GOptionContext *context, { if (arg == group->entries[j].short_name) { - if (group->entries[j].arg == G_OPTION_ARG_NONE) + if (NO_ARG (&group->entries[j])) { parse_arg (context, group, &group->entries[j], NULL, NULL, error); @@ -954,7 +969,7 @@ parse_long_option (GOptionContext *context, if (*index >= *argc) return TRUE; - if (group->entries[j].arg == G_OPTION_ARG_NONE && + if (NO_ARG (&group->entries[j]) && strcmp (arg, group->entries[j].long_name) == 0) { parse_arg (context, group, &group->entries[j], diff --git a/glib/goption.h b/glib/goption.h index 285bf01..dcd36e4 100644 --- a/glib/goption.h +++ b/glib/goption.h @@ -34,7 +34,9 @@ typedef enum { G_OPTION_FLAG_HIDDEN = 1 << 0, G_OPTION_FLAG_IN_MAIN = 1 << 1, - G_OPTION_FLAG_REVERSE = 1 << 2 + G_OPTION_FLAG_REVERSE = 1 << 2, + G_OPTION_FLAG_NO_ARG = 1 << 3, + G_OPTION_FLAG_FILENAME = 1 << 4 } GOptionFlags; typedef enum diff --git a/tests/option-test.c b/tests/option-test.c index 3c4035f..ffd1761 100644 --- a/tests/option-test.c +++ b/tests/option-test.c @@ -9,6 +9,9 @@ int arg_test1_int; gchar *arg_test2_string; gchar *arg_test3_filename; +gchar *callback_test1_string; +gboolean callback_test2_int; + gchar **array_test1_array; gboolean ignore_test1_boolean; @@ -324,6 +327,78 @@ arg_test3 (void) g_option_context_free (context); } +static gboolean +callback_parse1 (const gchar *option_name, const gchar *value, + gpointer data, GError **error) +{ + callback_test1_string = g_strdup (value); + return TRUE; +} + +void +callback_test1 (void) +{ + GOptionContext *context; + gboolean retval; + GError *error = NULL; + gchar **argv; + int argc; + GOptionEntry entries [] = + { { "test", 0, 0, G_OPTION_ARG_CALLBACK, callback_parse1, 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 --test foo.txt", &argc); + + retval = g_option_context_parse (context, &argc, &argv, &error); + g_assert (retval); + + g_assert (strcmp (callback_test1_string, "foo.txt") == 0); + + g_free (callback_test1_string); + + g_strfreev (argv); + g_option_context_free (context); +} + +static gboolean +callback_parse2 (const gchar *option_name, const gchar *value, + gpointer data, GError **error) +{ + callback_test2_int++; + return TRUE; +} + +void +callback_test2 (void) +{ + GOptionContext *context; + gboolean retval; + GError *error = NULL; + gchar **argv; + int argc; + GOptionEntry entries [] = + { { "test", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, callback_parse2, 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 --test --test", &argc); + + retval = g_option_context_parse (context, &argc, &argv, &error); + g_assert (retval); + + g_assert (callback_test2_int == 2); + + g_strfreev (argv); + g_option_context_free (context); +} + void ignore_test1 (void) { @@ -937,6 +1012,10 @@ main (int argc, char **argv) /* Test string arrays */ array_test1 (); + /* Test callback args */ + callback_test1 (); + callback_test2 (); + /* Test ignoring options */ ignore_test1 (); ignore_test2 (); -- 2.7.4