X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgoption.c;h=6438281200d255758b6feefd79b721db479a7245;hb=d0083f7e2dd621c6b78496bdb6ecf5d580c5e110;hp=799ea09989407c031c269b0e2dda67a4874b0f33;hpb=8073759f8cad2033169730c1b95af5b763e3c126;p=platform%2Fupstream%2Fglib.git diff --git a/glib/goption.c b/glib/goption.c index 799ea09..6438281 100644 --- a/glib/goption.c +++ b/glib/goption.c @@ -14,9 +14,7 @@ * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library; if not, see . */ /** @@ -28,40 +26,37 @@ * for the popt library. It supports short and long commandline options, * as shown in the following example: * - * testtreemodel -r 1 --max-size 20 --rand --display=:1.0 -vb -- file1 file2 + * `testtreemodel -r 1 --max-size 20 --rand --display=:1.0 -vb -- file1 file2` * * The example demonstrates a number of features of the GOption - * commandline parser - * - * Options can be single letters, prefixed by a single dash. Multiple - * short options can be grouped behind a single dash. - * - * Long options are prefixed by two consecutive dashes. - * - * Options can have an extra argument, which can be a number, a string or + * commandline parser: + * + * - Options can be single letters, prefixed by a single dash. + * + * - Multiple short options can be grouped behind a single dash. + * + * - Long options are prefixed by two consecutive dashes. + * + * - Options can have an extra argument, which can be a number, a string or * a filename. For long options, the extra argument can be appended with * an equals sign after the option name, which is useful if the extra * argument starts with a dash, which would otherwise cause it to be * interpreted as another option. - * - * Non-option arguments are returned to the application as rest arguments. - * - * An argument consisting solely of two dashes turns off further parsing, + * + * - Non-option arguments are returned to the application as rest arguments. + * + * - An argument consisting solely of two dashes turns off further parsing, * any remaining arguments (even those starting with a dash) are returned * to the application as rest arguments. - * * * Another important feature of GOption is that it can automatically * generate nicely formatted help output. Unless it is explicitly turned * off with g_option_context_set_help_enabled(), GOption will recognize - * the , , - * and - * groupname options - * (where groupname is the name of a - * #GOptionGroup) and write a text similar to the one shown in the - * following example to stdout. - * - * + * the `--help`, `-?`, `--help-all` and `--help-groupname` options + * (where `groupname` is the name of a #GOptionGroup) and write a text + * similar to the one shown in the following example to stdout. + * + * |[ * Usage: * testtreemodel [OPTION...] - test tree model performance * @@ -77,9 +72,9 @@ * -v, --verbose Be verbose * -b, --beep Beep when done * --rand Randomize the data - * + * ]| * - * GOption groups options in #GOptionGroups, which makes it easy to + * GOption groups options in #GOptionGroups, which makes it easy to * incorporate options from multiple sources. The intended use for this is * to let applications collect option groups from the libraries it uses, * add them to their #GOptionContext, and parse all options by a single call @@ -93,13 +88,12 @@ * * Here is a complete example of setting up GOption to parse the example * commandline above and produce the example help output. - * - * + * |[ * static gint repeats = 2; * static gint max_size = 8; * static gboolean verbose = FALSE; * static gboolean beep = FALSE; - * static gboolean rand = FALSE; + * static gboolean randomize = FALSE; * * static GOptionEntry entries[] = * { @@ -107,7 +101,7 @@ * { "max-size", 'm', 0, G_OPTION_ARG_INT, &max_size, "Test up to 2^M items", "M" }, * { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL }, * { "beep", 'b', 0, G_OPTION_ARG_NONE, &beep, "Beep when done", NULL }, - * { "rand", 0, 0, G_OPTION_ARG_NONE, &rand, "Randomize the data", NULL }, + * { "rand", 0, 0, G_OPTION_ARG_NONE, &randomize, "Randomize the data", NULL }, * { NULL } * }; * @@ -126,10 +120,61 @@ * exit (1); * } * - * /* ... */ + * ... * * } - * + * ]| + * + * On UNIX systems, the argv that is passed to main() has no particular + * encoding, even to the extent that different parts of it may have + * different encodings. In general, normal arguments and flags will be + * in the current locale and filenames should be considered to be opaque + * byte strings. Proper use of %G_OPTION_ARG_FILENAME vs + * %G_OPTION_ARG_STRING is therefore important. + * + * Note that on Windows, filenames do have an encoding, but using + * #GOptionContext with the argv as passed to main() will result in a + * program that can only accept commandline arguments with characters + * from the system codepage. This can cause problems when attempting to + * deal with filenames containing Unicode characters that fall outside + * of the codepage. + * + * A solution to this is to use g_win32_get_command_line() and + * g_option_context_parse_strv() which will properly handle full Unicode + * filenames. If you are using #GApplication, this is done + * automatically for you. + * + * The following example shows how you can use #GOptionContext directly + * in order to correctly deal with Unicode filenames on Windows: + * + * |[ + * int + * main (int argc, char **argv) + * { + * GError *error = NULL; + * GOptionContext *context; + * gchar **args; + * + * #ifdef G_OS_WIN32 + * args = g_win32_get_command_line (); + * #else + * args = g_strdupv (argv); + * #endif + * + * // set up context + * + * if (!g_option_context_parse_strv (context, &args, &error)) + * { + * // error happened + * } + * + * ... + * + * g_strfreev (args); + * + * ... + * } + * ]| */ #include "config.h" @@ -139,6 +184,11 @@ #include #include +#if defined __OpenBSD__ +#include +#include +#endif + #include "goption.h" #include "gprintf.h" @@ -197,6 +247,7 @@ struct _GOptionContext guint help_enabled : 1; guint ignore_unknown : 1; + guint strv_mode : 1; GOptionGroup *main_group; @@ -251,54 +302,27 @@ _g_unichar_get_width (gunichar c) } static glong -_g_utf8_strwidth (const gchar *p, - gssize max) +_g_utf8_strwidth (const gchar *p) { glong len = 0; - const gchar *start = p; - g_return_val_if_fail (p != NULL || max == 0, 0); + g_return_val_if_fail (p != NULL, 0); - if (max < 0) + while (*p) { - while (*p) - { - len += _g_unichar_get_width (g_utf8_get_char (p)); - p = g_utf8_next_char (p); - } - } - else - { - if (max == 0 || !*p) - return 0; - - /* this case may not be quite correct */ - len += _g_unichar_get_width (g_utf8_get_char (p)); p = g_utf8_next_char (p); - - while (p - start < max && *p) - { - len += _g_unichar_get_width (g_utf8_get_char (p)); - p = g_utf8_next_char (p); - } } return len; } - -GQuark -g_option_error_quark (void) -{ - return g_quark_from_static_string ("g-option-context-error-quark"); -} +G_DEFINE_QUARK (g-option-context-error-quark, g_option_error) /** * g_option_context_new: - * @parameter_string: a string which is displayed in - * the first line of output, after the - * usage summary - * programname [OPTION...] + * @parameter_string: (allow-none): a string which is displayed in + * the first line of `--help` output, after the usage summary + * `programname [OPTION...]` * * Creates a new option context. * @@ -356,8 +380,7 @@ 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); + g_list_free_full (context->groups, (GDestroyNotify) g_option_group_free); if (context->main_group) g_option_group_free (context->main_group); @@ -379,14 +402,12 @@ void g_option_context_free (GOptionContext *context) /** * g_option_context_set_help_enabled: * @context: a #GOptionContext - * @help_enabled: %TRUE to enable , %FALSE to disable it + * @help_enabled: %TRUE to enable `--help`, %FALSE to disable it * - * Enables or disables automatic generation of - * output. By default, g_option_context_parse() recognizes - * , , - * , - * and groupname and creates - * suitable output to stdout. + * Enables or disables automatic generation of `--help` output. + * By default, g_option_context_parse() recognizes `--help`, `-h`, + * `-?`, `--help-all` and `--help-groupname` and creates suitable + * output to stdout. * * Since: 2.6 */ @@ -403,7 +424,7 @@ void g_option_context_set_help_enabled (GOptionContext *context, * g_option_context_get_help_enabled: * @context: a #GOptionContext * - * Returns whether automatic generation + * Returns whether automatic `--help` generation * is turned on for @context. See g_option_context_set_help_enabled(). * * Returns: %TRUE if automatic help generation is turned on. @@ -508,7 +529,7 @@ g_option_context_add_group (GOptionContext *context, * Sets a #GOptionGroup as main group of the @context. * This has the same effect as calling g_option_context_add_group(), * the only difference is that the options in the main group are - * treated differently when generating output. + * treated differently when generating `--help` output. * * Since: 2.6 **/ @@ -535,7 +556,7 @@ g_option_context_set_main_group (GOptionContext *context, * * Returns a pointer to the main group of @context. * - * Return value: the main group of @context, or %NULL if @context doesn't + * Returns: the main group of @context, or %NULL if @context doesn't * have a main group. Note that group belongs to @context and should * not be modified or freed. * @@ -552,9 +573,9 @@ g_option_context_get_main_group (GOptionContext *context) /** * g_option_context_add_main_entries: * @context: a #GOptionContext - * @entries: a %NULL-terminated array of #GOptionEntrys - * @translation_domain: a translation domain to use for translating - * the output for the options in @entries + * @entries: a %NULL-terminated array of #GOptionEntrys + * @translation_domain: (allow-none): a translation domain to use for translating + * the `--help` output for the options in @entries * with gettext(), or %NULL * * A convenience function which creates a main group if it doesn't @@ -577,10 +598,12 @@ g_option_context_add_main_entries (GOptionContext *context, } static gint -calculate_max_length (GOptionGroup *group) +calculate_max_length (GOptionGroup *group, + GHashTable *aliases) { GOptionEntry *entry; gint i, len, max_length; + const gchar *long_name; max_length = 0; @@ -591,13 +614,16 @@ calculate_max_length (GOptionGroup *group) if (entry->flags & G_OPTION_FLAG_HIDDEN) continue; - len = _g_utf8_strwidth (entry->long_name, -1); + long_name = g_hash_table_lookup (aliases, &entry->long_name); + if (!long_name) + long_name = entry->long_name; + len = _g_utf8_strwidth (long_name); if (entry->short_name) len += 4; if (!NO_ARG (entry) && entry->arg_description) - len += 1 + _g_utf8_strwidth (TRANSLATE (group, entry->arg_description), -1); + len += 1 + _g_utf8_strwidth (TRANSLATE (group, entry->arg_description)); max_length = MAX (max_length, len); } @@ -609,9 +635,11 @@ static void print_entry (GOptionGroup *group, gint max_length, const GOptionEntry *entry, - GString *string) + GString *string, + GHashTable *aliases) { GString *str; + const gchar *long_name; if (entry->flags & G_OPTION_FLAG_HIDDEN) return; @@ -619,18 +647,22 @@ print_entry (GOptionGroup *group, if (entry->long_name[0] == 0) return; + long_name = g_hash_table_lookup (aliases, &entry->long_name); + if (!long_name) + long_name = entry->long_name; + str = g_string_new (NULL); if (entry->short_name) - g_string_append_printf (str, " -%c, --%s", entry->short_name, entry->long_name); + g_string_append_printf (str, " -%c, --%s", entry->short_name, long_name); else - g_string_append_printf (str, " --%s", entry->long_name); + g_string_append_printf (str, " --%s", long_name); if (entry->arg_description) g_string_append_printf (str, "=%s", TRANSLATE (group, entry->arg_description)); g_string_append_printf (string, "%s%*s %s\n", str->str, - (int) (max_length + 4 - _g_utf8_strwidth (str->str, -1)), "", + (int) (max_length + 4 - _g_utf8_strwidth (str->str)), "", entry->description ? TRANSLATE (group, entry->description) : ""); g_string_free (str, TRUE); } @@ -654,6 +686,8 @@ group_has_visible_entries (GOptionContext *context, if (main_entries && !main_group && !(entry->flags & G_OPTION_FLAG_IN_MAIN)) continue; + if (entry->long_name[0] == 0) /* ignore rest entry */ + continue; if (!(entry->flags & reject_filter)) return TRUE; } @@ -662,7 +696,7 @@ group_has_visible_entries (GOptionContext *context, } static gboolean -group_list_has_visible_entires (GOptionContext *context, +group_list_has_visible_entries (GOptionContext *context, GList *group_list, gboolean main_entries) { @@ -710,15 +744,15 @@ context_has_h_entry (GOptionContext *context) * g_option_context_get_help: * @context: a #GOptionContext * @main_help: if %TRUE, only include the main group - * @group: the #GOptionGroup to create help for, or %NULL + * @group: (allow-none): the #GOptionGroup to create help for, or %NULL * * Returns a formatted, translated help text for the given context. - * To obtain the text produced by , call - * g_option_context_get_help (context, TRUE, NULL). - * To obtain the text produced by , call - * g_option_context_get_help (context, FALSE, NULL). + * To obtain the text produced by `--help`, call + * `g_option_context_get_help (context, TRUE, NULL)`. + * To obtain the text produced by `--help-all`, call + * `g_option_context_get_help (context, FALSE, NULL)`. * To obtain the help text for an option group, call - * g_option_context_get_help (context, FALSE, group). + * `g_option_context_get_help (context, FALSE, group)`. * * Returns: A newly allocated string containing the help text * @@ -730,10 +764,11 @@ g_option_context_get_help (GOptionContext *context, GOptionGroup *group) { GList *list; - gint max_length, len; + gint max_length = 0, len; gint i; GOptionEntry *entry; GHashTable *shadow_map; + GHashTable *aliases; gboolean seen[256]; const gchar *rest_description; GString *string; @@ -781,6 +816,7 @@ g_option_context_get_help (GOptionContext *context, memset (seen, 0, sizeof (gboolean) * 256); shadow_map = g_hash_table_new (g_str_hash, g_str_equal); + aliases = g_hash_table_new_full (NULL, NULL, NULL, g_free); if (context->main_group) { @@ -807,7 +843,10 @@ g_option_context_get_help (GOptionContext *context, entry = &g->entries[i]; if (g_hash_table_lookup (shadow_map, entry->long_name) && !(entry->flags & G_OPTION_FLAG_NOALIAS)) - entry->long_name = g_strdup_printf ("%s-%s", g->name, entry->long_name); + { + g_hash_table_insert (aliases, &entry->long_name, + g_strdup_printf ("%s-%s", g->name, entry->long_name)); + } else g_hash_table_insert (shadow_map, (gpointer)entry->long_name, entry); @@ -824,17 +863,20 @@ g_option_context_get_help (GOptionContext *context, list = context->groups; - max_length = _g_utf8_strwidth ("-?, --help", -1); - - if (list) + if (context->help_enabled) { - len = _g_utf8_strwidth ("--help-all", -1); - max_length = MAX (max_length, len); + max_length = _g_utf8_strwidth ("-?, --help"); + + if (list) + { + len = _g_utf8_strwidth ("--help-all"); + max_length = MAX (max_length, len); + } } if (context->main_group) { - len = calculate_max_length (context->main_group); + len = calculate_max_length (context->main_group, aliases); max_length = MAX (max_length, len); } @@ -842,12 +884,15 @@ g_option_context_get_help (GOptionContext *context, { GOptionGroup *g = list->data; - /* First, we check the --help- options */ - len = _g_utf8_strwidth ("--help-", -1) + _g_utf8_strwidth (g->name, -1); - max_length = MAX (max_length, len); + if (context->help_enabled) + { + /* First, we check the --help- options */ + len = _g_utf8_strwidth ("--help-") + _g_utf8_strwidth (g->name); + max_length = MAX (max_length, len); + } /* Then we go through the entries */ - len = calculate_max_length (g); + len = calculate_max_length (g, aliases); max_length = MAX (max_length, len); list = list->next; @@ -856,7 +901,7 @@ g_option_context_get_help (GOptionContext *context, /* Add a bit of padding */ max_length += 4; - if (!group) + if (!group && context->help_enabled) { list = context->groups; @@ -896,7 +941,7 @@ g_option_context_get_help (GOptionContext *context, g_string_append (string, TRANSLATE (group, group->description)); g_string_append (string, "\n"); for (i = 0; i < group->n_entries; i++) - print_entry (group, max_length, &group->entries[i], string); + print_entry (group, max_length, &group->entries[i], string, aliases); g_string_append (string, "\n"); } } @@ -916,7 +961,7 @@ g_option_context_get_help (GOptionContext *context, g_string_append (string, "\n"); for (i = 0; i < g->n_entries; i++) if (!(g->entries[i].flags & G_OPTION_FLAG_IN_MAIN)) - print_entry (g, max_length, &g->entries[i], string); + print_entry (g, max_length, &g->entries[i], string, aliases); g_string_append (string, "\n"); } @@ -928,7 +973,7 @@ g_option_context_get_help (GOptionContext *context, /* Print application options if --help or --help-all has been specified */ if ((main_help || !group) && (group_has_visible_entries (context, context->main_group, TRUE) || - group_list_has_visible_entires (context, context->groups, TRUE))) + group_list_has_visible_entries (context, context->groups, TRUE))) { list = context->groups; @@ -937,7 +982,7 @@ g_option_context_get_help (GOptionContext *context, if (context->main_group) for (i = 0; i < context->main_group->n_entries; i++) print_entry (context->main_group, max_length, - &context->main_group->entries[i], string); + &context->main_group->entries[i], string, aliases); while (list != NULL) { @@ -946,7 +991,7 @@ g_option_context_get_help (GOptionContext *context, /* Print main entries from other groups */ for (i = 0; i < g->n_entries; i++) if (g->entries[i].flags & G_OPTION_FLAG_IN_MAIN) - print_entry (g, max_length, &g->entries[i], string); + print_entry (g, max_length, &g->entries[i], string, aliases); list = list->next; } @@ -960,6 +1005,8 @@ g_option_context_get_help (GOptionContext *context, g_string_append (string, "\n"); } + g_hash_table_destroy (aliases); + return g_string_free (string, FALSE); } @@ -1141,8 +1188,8 @@ parse_arg (GOptionContext *context, { case G_OPTION_ARG_NONE: { - change = get_change (context, G_OPTION_ARG_NONE, - entry->arg_data); + (void) get_change (context, G_OPTION_ARG_NONE, + entry->arg_data); *(gboolean *)entry->arg_data = !(entry->flags & G_OPTION_FLAG_REVERSE); break; @@ -1151,7 +1198,14 @@ parse_arg (GOptionContext *context, { gchar *data; +#ifdef G_OS_WIN32 + if (!context->strv_mode) + data = g_locale_to_utf8 (value, -1, NULL, NULL, error); + else + data = g_strdup (value); +#else data = g_locale_to_utf8 (value, -1, NULL, NULL, error); +#endif if (!data) return FALSE; @@ -1170,7 +1224,14 @@ parse_arg (GOptionContext *context, { gchar *data; +#ifdef G_OS_WIN32 + if (!context->strv_mode) + data = g_locale_to_utf8 (value, -1, NULL, NULL, error); + else + data = g_strdup (value); +#else data = g_locale_to_utf8 (value, -1, NULL, NULL, error); +#endif if (!data) return FALSE; @@ -1203,7 +1264,10 @@ parse_arg (GOptionContext *context, gchar *data; #ifdef G_OS_WIN32 - data = g_locale_to_utf8 (value, -1, NULL, NULL, error); + if (!context->strv_mode) + data = g_locale_to_utf8 (value, -1, NULL, NULL, error); + else + data = g_strdup (value); if (!data) return FALSE; @@ -1226,7 +1290,10 @@ parse_arg (GOptionContext *context, gchar *data; #ifdef G_OS_WIN32 - data = g_locale_to_utf8 (value, -1, NULL, NULL, error); + if (!context->strv_mode) + data = g_locale_to_utf8 (value, -1, NULL, NULL, error); + else + data = g_strdup (value); if (!data) return FALSE; @@ -1283,7 +1350,10 @@ parse_arg (GOptionContext *context, else if (entry->flags & G_OPTION_FLAG_FILENAME) { #ifdef G_OS_WIN32 - data = g_locale_to_utf8 (value, -1, NULL, NULL, error); + if (!context->strv_mode) + data = g_locale_to_utf8 (value, -1, NULL, NULL, error); + else + data = g_strdup (value); #else data = g_strdup (value); #endif @@ -1646,7 +1716,12 @@ free_pending_nulls (GOptionContext *context, strcpy (*n->ptr + 1, n->value); } else - *n->ptr = NULL; + { + if (context->strv_mode) + g_free (*n->ptr); + + *n->ptr = NULL; + } } g_free (n->value); @@ -1665,7 +1740,7 @@ free_pending_nulls (GOptionContext *context, static char * platform_get_argv0 (void) { -#ifdef __linux +#if defined __linux char *cmdline; char *base_arg0; gsize len; @@ -1685,6 +1760,31 @@ platform_get_argv0 (void) base_arg0 = g_path_get_basename (cmdline); g_free (cmdline); return base_arg0; +#elif defined __OpenBSD__ + char **cmdline; + char *base_arg0; + gsize len; + + int mib[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV }; + + if (sysctl (mib, G_N_ELEMENTS (mib), NULL, &len, NULL, 0) == -1) + return NULL; + + cmdline = g_malloc0 (len); + + if (sysctl (mib, G_N_ELEMENTS (mib), cmdline, &len, NULL, 0) == -1) + { + g_free (cmdline); + return NULL; + } + + /* We could just return cmdline, but I think it's better + * to hold on to a smaller malloc block; the arguments + * could be large. + */ + base_arg0 = g_path_get_basename (*cmdline); + g_free (cmdline); + return base_arg0; #endif return NULL; @@ -1709,18 +1809,17 @@ platform_get_argv0 (void) * or some of the options after it start with '-'. In case * of an error, @argc and @argv are left unmodified. * - * If automatic support is enabled + * If automatic `--help` support is enabled * (see g_option_context_set_help_enabled()), and the * @argv array contains one of the recognized help options, * this function will produce help output to stdout and - * call exit (0). + * call `exit (0)`. * - * Note that function depends on the - * current locale for + * Note that function depends on the [current locale][setlocale] for * automatic character set conversion of string and filename * arguments. * - * Return value: %TRUE if the parsing was successful, + * Returns: %TRUE if the parsing was successful, * %FALSE if an error occurred * * Since: 2.6 @@ -1939,6 +2038,7 @@ g_option_context_parse (GOptionContext *context, if (new_arg) new_arg[arg_index] = '\0'; add_pending_null (context, &((*argv)[i]), new_arg); + i = new_i; } else if (parsed) { @@ -2052,20 +2152,20 @@ g_option_context_parse (GOptionContext *context, /** * g_option_group_new: * @name: the name for the option group, this is used to provide - * help for the options in this group with @name + * help for the options in this group with `--help-`@name * @description: a description for this group to be shown in - * . This string is translated using the translation + * `--help`. This string is translated using the translation * domain or translation function of the group - * @help_description: a description for the @name option. + * @help_description: a description for the `--help-`@name option. * This string is translated using the translation domain or translation function * of the group - * @user_data: user data that will be passed to the pre- and post-parse hooks, + * @user_data: (allow-none): user data that will be passed to the pre- and post-parse hooks, * the error hook and to callbacks of %G_OPTION_ARG_CALLBACK options, or %NULL - * @destroy: a function that will be called to free @user_data, or %NULL + * @destroy: (allow-none): a function that will be called to free @user_data, or %NULL * * Creates a new #GOptionGroup. * - * Return value: a newly created option group. It should be added + * Returns: a newly created option group. It should be added * to a #GOptionContext or freed with g_option_group_free(). * * Since: 2.6 @@ -2095,11 +2195,11 @@ g_option_group_new (const gchar *name, * g_option_group_free: * @group: a #GOptionGroup * - * Frees a #GOptionGroup. Note that you must not - * free groups which have been added to a #GOptionContext. + * Frees a #GOptionGroup. Note that you must not free groups + * which have been added to a #GOptionContext. * * Since: 2.6 - **/ + */ void g_option_group_free (GOptionGroup *group) { @@ -2124,7 +2224,7 @@ g_option_group_free (GOptionGroup *group) /** * g_option_group_add_entries: * @group: a #GOptionGroup - * @entries: a %NULL-terminated array of #GOptionEntrys + * @entries: a %NULL-terminated array of #GOptionEntrys * * Adds the options specified in @entries to @group. * @@ -2150,14 +2250,16 @@ g_option_group_add_entries (GOptionGroup *group, if (c == '-' || (c != 0 && !g_ascii_isprint (c))) { - g_warning (G_STRLOC ": ignoring invalid short option '%c' (%d)", c, c); - group->entries[i].short_name = 0; + g_warning (G_STRLOC ": ignoring invalid short option '%c' (%d) in entry %s:%s", + c, c, group->name, group->entries[i].long_name); + group->entries[i].short_name = '\0'; } if (group->entries[i].arg != G_OPTION_ARG_NONE && (group->entries[i].flags & G_OPTION_FLAG_REVERSE) != 0) { - g_warning (G_STRLOC ": ignoring reverse flag on option of type %d", group->entries[i].arg); + g_warning (G_STRLOC ": ignoring reverse flag on option of arg-type %d in entry %s:%s", + group->entries[i].arg, group->name, group->entries[i].long_name); group->entries[i].flags &= ~G_OPTION_FLAG_REVERSE; } @@ -2165,7 +2267,8 @@ g_option_group_add_entries (GOptionGroup *group, if (group->entries[i].arg != G_OPTION_ARG_CALLBACK && (group->entries[i].flags & (G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG|G_OPTION_FLAG_FILENAME)) != 0) { - g_warning (G_STRLOC ": ignoring no-arg, optional-arg or filename flags (%d) on option of type %d", group->entries[i].flags, group->entries[i].arg); + g_warning (G_STRLOC ": ignoring no-arg, optional-arg or filename flags (%d) on option of arg-type %d in entry %s:%s", + group->entries[i].flags, group->entries[i].arg, group->name, group->entries[i].long_name); group->entries[i].flags &= ~(G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG|G_OPTION_FLAG_FILENAME); } @@ -2177,8 +2280,8 @@ g_option_group_add_entries (GOptionGroup *group, /** * g_option_group_set_parse_hooks: * @group: a #GOptionGroup - * @pre_parse_func: a function to call before parsing, or %NULL - * @post_parse_func: a function to call after parsing, or %NULL + * @pre_parse_func: (allow-none): a function to call before parsing, or %NULL + * @post_parse_func: (allow-none): a function to call after parsing, or %NULL * * Associates two functions with @group which will be called * from g_option_context_parse() before the first option is parsed @@ -2227,14 +2330,13 @@ g_option_group_set_error_hook (GOptionGroup *group, /** * g_option_group_set_translate_func: * @group: a #GOptionGroup - * @func: the #GTranslateFunc, or %NULL - * @data: user data to pass to @func, or %NULL - * @destroy_notify: a function which gets called to free @data, or %NULL + * @func: (allow-none): the #GTranslateFunc, or %NULL + * @data: (allow-none): user data to pass to @func, or %NULL + * @destroy_notify: (allow-none): a function which gets called to free @data, or %NULL * - * Sets the function which is used to translate user-visible - * strings, for output. Different - * groups can use different #GTranslateFuncs. If @func - * is %NULL, strings are not translated. + * Sets the function which is used to translate user-visible strings, + * for `--help` output. Different groups can use different + * #GTranslateFuncs. If @func is %NULL, strings are not translated. * * If you are using gettext(), you only need to set the translation * domain, see g_option_group_set_translation_domain(). @@ -2289,13 +2391,13 @@ g_option_group_set_translation_domain (GOptionGroup *group, /** * g_option_context_set_translate_func: * @context: a #GOptionContext - * @func: the #GTranslateFunc, or %NULL - * @data: user data to pass to @func, or %NULL - * @destroy_notify: a function which gets called to free @data, or %NULL + * @func: (allow-none): the #GTranslateFunc, or %NULL + * @data: (allow-none): user data to pass to @func, or %NULL + * @destroy_notify: (allow-none): a function which gets called to free @data, or %NULL * * Sets the function which is used to translate the contexts - * user-visible strings, for output. - * If @func is %NULL, strings are not translated. + * user-visible strings, for `--help` output. If @func is %NULL, + * strings are not translated. * * Note that option groups have their own translation functions, * this function only affects the @parameter_string (see g_option_context_new()), @@ -2348,12 +2450,11 @@ g_option_context_set_translation_domain (GOptionContext *context, /** * g_option_context_set_summary: * @context: a #GOptionContext - * @summary: a string to be shown in output + * @summary: (allow-none): a string to be shown in `--help` output * before the list of options, or %NULL * - * Adds a string to be displayed in output - * before the list of options. This is typically a summary of the - * program functionality. + * Adds a string to be displayed in `--help` output before the list + * of options. This is typically a summary of the program functionality. * * Note that the summary is translated (see * g_option_context_set_translate_func() and @@ -2393,12 +2494,11 @@ g_option_context_get_summary (GOptionContext *context) /** * g_option_context_set_description: * @context: a #GOptionContext - * @description: a string to be shown in output + * @description: (allow-none): a string to be shown in `--help` output * after the list of options, or %NULL * - * Adds a string to be displayed in output - * after the list of options. This text often includes a bug reporting - * address. + * Adds a string to be displayed in `--help` output after the list + * of options. This text often includes a bug reporting address. * * Note that the summary is translated (see * g_option_context_set_translate_func()). @@ -2433,3 +2533,48 @@ g_option_context_get_description (GOptionContext *context) return context->description; } + +/** + * g_option_context_parse_strv: + * @context: a #GOptionContext + * @arguments: (inout) (array null-terminated=1): a pointer to the + * command line arguments (which must be in UTF-8 on Windows) + * @error: a return location for errors + * + * Parses the command line arguments. + * + * This function is similar to g_option_context_parse() except that it + * respects the normal memory rules when dealing with a strv instead of + * assuming that the passed-in array is the argv of the main function. + * + * In particular, strings that are removed from the arguments list will + * be freed using g_free(). + * + * On Windows, the strings are expected to be in UTF-8. This is in + * contrast to g_option_context_parse() which expects them to be in the + * system codepage, which is how they are passed as @argv to main(). + * See g_win32_get_command_line() for a solution. + * + * This function is useful if you are trying to use #GOptionContext with + * #GApplication. + * + * Returns: %TRUE if the parsing was successful, + * %FALSE if an error occurred + * + * Since: 2.40 + **/ +gboolean +g_option_context_parse_strv (GOptionContext *context, + gchar ***arguments, + GError **error) +{ + gboolean success; + gint argc; + + context->strv_mode = TRUE; + argc = g_strv_length (*arguments); + success = g_option_context_parse (context, &argc, arguments, error); + context->strv_mode = FALSE; + + return success; +}