hook gvariant vectors up to kdbus
[platform/upstream/glib.git] / glib / goption.c
1 /* goption.c - Option parser
2  *
3  *  Copyright (C) 1999, 2003 Red Hat Software
4  *  Copyright (C) 2004       Anders Carlsson <andersca@gnome.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /**
21  * SECTION:option
22  * @Short_description: parses commandline options
23  * @Title: Commandline option parser
24  *
25  * The GOption commandline parser is intended to be a simpler replacement
26  * for the popt library. It supports short and long commandline options,
27  * as shown in the following example:
28  *
29  * `testtreemodel -r 1 --max-size 20 --rand --display=:1.0 -vb -- file1 file2`
30  *
31  * The example demonstrates a number of features of the GOption
32  * commandline parser:
33  *
34  * - Options can be single letters, prefixed by a single dash.
35  *
36  * - Multiple short options can be grouped behind a single dash.
37  *
38  * - Long options are prefixed by two consecutive dashes.
39  *
40  * - Options can have an extra argument, which can be a number, a string or
41  *   a filename. For long options, the extra argument can be appended with
42  *   an equals sign after the option name, which is useful if the extra
43  *   argument starts with a dash, which would otherwise cause it to be
44  *   interpreted as another option.
45  *
46  * - Non-option arguments are returned to the application as rest arguments.
47  *
48  * - An argument consisting solely of two dashes turns off further parsing,
49  *   any remaining arguments (even those starting with a dash) are returned
50  *   to the application as rest arguments.
51  *
52  * Another important feature of GOption is that it can automatically
53  * generate nicely formatted help output. Unless it is explicitly turned
54  * off with g_option_context_set_help_enabled(), GOption will recognize
55  * the `--help`, `-?`, `--help-all` and `--help-groupname` options
56  * (where `groupname` is the name of a #GOptionGroup) and write a text
57  * similar to the one shown in the following example to stdout.
58  *
59  * |[
60  * Usage:
61  *   testtreemodel [OPTION...] - test tree model performance
62  *  
63  * Help Options:
64  *   -h, --help               Show help options
65  *   --help-all               Show all help options
66  *   --help-gtk               Show GTK+ Options
67  *  
68  * Application Options:
69  *   -r, --repeats=N          Average over N repetitions
70  *   -m, --max-size=M         Test up to 2^M items
71  *   --display=DISPLAY        X display to use
72  *   -v, --verbose            Be verbose
73  *   -b, --beep               Beep when done
74  *   --rand                   Randomize the data
75  * ]|
76  *
77  * GOption groups options in #GOptionGroups, which makes it easy to
78  * incorporate options from multiple sources. The intended use for this is
79  * to let applications collect option groups from the libraries it uses,
80  * add them to their #GOptionContext, and parse all options by a single call
81  * to g_option_context_parse(). See gtk_get_option_group() for an example.
82  *
83  * If an option is declared to be of type string or filename, GOption takes
84  * care of converting it to the right encoding; strings are returned in
85  * UTF-8, filenames are returned in the GLib filename encoding. Note that
86  * this only works if setlocale() has been called before
87  * g_option_context_parse().
88  *
89  * Here is a complete example of setting up GOption to parse the example
90  * commandline above and produce the example help output.
91  * |[<!-- language="C" --> 
92  * static gint repeats = 2;
93  * static gint max_size = 8;
94  * static gboolean verbose = FALSE;
95  * static gboolean beep = FALSE;
96  * static gboolean randomize = FALSE;
97  *
98  * static GOptionEntry entries[] =
99  * {
100  *   { "repeats", 'r', 0, G_OPTION_ARG_INT, &repeats, "Average over N repetitions", "N" },
101  *   { "max-size", 'm', 0, G_OPTION_ARG_INT, &max_size, "Test up to 2^M items", "M" },
102  *   { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL },
103  *   { "beep", 'b', 0, G_OPTION_ARG_NONE, &beep, "Beep when done", NULL },
104  *   { "rand", 0, 0, G_OPTION_ARG_NONE, &randomize, "Randomize the data", NULL },
105  *   { NULL }
106  * };
107  *
108  * int
109  * main (int argc, char *argv[])
110  * {
111  *   GError *error = NULL;
112  *   GOptionContext *context;
113  *
114  *   context = g_option_context_new ("- test tree model performance");
115  *   g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
116  *   g_option_context_add_group (context, gtk_get_option_group (TRUE));
117  *   if (!g_option_context_parse (context, &argc, &argv, &error))
118  *     {
119  *       g_print ("option parsing failed: %s\n", error->message);
120  *       exit (1);
121  *     }
122  *
123  *   ...
124  *
125  * }
126  * ]|
127  *
128  * On UNIX systems, the argv that is passed to main() has no particular
129  * encoding, even to the extent that different parts of it may have
130  * different encodings.  In general, normal arguments and flags will be
131  * in the current locale and filenames should be considered to be opaque
132  * byte strings.  Proper use of %G_OPTION_ARG_FILENAME vs
133  * %G_OPTION_ARG_STRING is therefore important.
134  *
135  * Note that on Windows, filenames do have an encoding, but using
136  * #GOptionContext with the argv as passed to main() will result in a
137  * program that can only accept commandline arguments with characters
138  * from the system codepage.  This can cause problems when attempting to
139  * deal with filenames containing Unicode characters that fall outside
140  * of the codepage.
141  *
142  * A solution to this is to use g_win32_get_command_line() and
143  * g_option_context_parse_strv() which will properly handle full Unicode
144  * filenames.  If you are using #GApplication, this is done
145  * automatically for you.
146  *
147  * The following example shows how you can use #GOptionContext directly
148  * in order to correctly deal with Unicode filenames on Windows:
149  *
150  * |[<!-- language="C" --> 
151  * int
152  * main (int argc, char **argv)
153  * {
154  *   GError *error = NULL;
155  *   GOptionContext *context;
156  *   gchar **args;
157  *
158  * #ifdef G_OS_WIN32
159  *   args = g_win32_get_command_line ();
160  * #else
161  *   args = g_strdupv (argv);
162  * #endif
163  *
164  *   // set up context
165  *
166  *   if (!g_option_context_parse_strv (context, &args, &error))
167  *     {
168  *       // error happened
169  *     }
170  *
171  *   ...
172  *
173  *   g_strfreev (args);
174  *
175  *   ...
176  * }
177  * ]|
178  */
179
180 #include "config.h"
181
182 #include <string.h>
183 #include <stdlib.h>
184 #include <stdio.h>
185 #include <errno.h>
186
187 #if defined __OpenBSD__
188 #include <unistd.h>
189 #include <sys/sysctl.h>
190 #endif
191
192 #include "goption.h"
193
194 #include "gprintf.h"
195 #include "glibintl.h"
196
197 #define TRANSLATE(group, str) (((group)->translate_func ? (* (group)->translate_func) ((str), (group)->translate_data) : (str)))
198
199 #define NO_ARG(entry) ((entry)->arg == G_OPTION_ARG_NONE ||       \
200                        ((entry)->arg == G_OPTION_ARG_CALLBACK &&  \
201                         ((entry)->flags & G_OPTION_FLAG_NO_ARG)))
202
203 #define OPTIONAL_ARG(entry) ((entry)->arg == G_OPTION_ARG_CALLBACK &&  \
204                        (entry)->flags & G_OPTION_FLAG_OPTIONAL_ARG)
205
206 typedef struct
207 {
208   GOptionArg arg_type;
209   gpointer arg_data;
210   union
211   {
212     gboolean bool;
213     gint integer;
214     gchar *str;
215     gchar **array;
216     gdouble dbl;
217     gint64 int64;
218   } prev;
219   union
220   {
221     gchar *str;
222     struct
223     {
224       gint len;
225       gchar **data;
226     } array;
227   } allocated;
228 } Change;
229
230 typedef struct
231 {
232   gchar **ptr;
233   gchar *value;
234 } PendingNull;
235
236 struct _GOptionContext
237 {
238   GList           *groups;
239
240   gchar           *parameter_string;
241   gchar           *summary;
242   gchar           *description;
243
244   GTranslateFunc   translate_func;
245   GDestroyNotify   translate_notify;
246   gpointer         translate_data;
247
248   guint            help_enabled   : 1;
249   guint            ignore_unknown : 1;
250   guint            strv_mode      : 1;
251   guint            strict_posix   : 1;
252
253   GOptionGroup    *main_group;
254
255   /* We keep a list of change so we can revert them */
256   GList           *changes;
257
258   /* We also keep track of all argv elements
259    * that should be NULLed or modified.
260    */
261   GList           *pending_nulls;
262 };
263
264 struct _GOptionGroup
265 {
266   gchar           *name;
267   gchar           *description;
268   gchar           *help_description;
269
270   GDestroyNotify   destroy_notify;
271   gpointer         user_data;
272
273   GTranslateFunc   translate_func;
274   GDestroyNotify   translate_notify;
275   gpointer         translate_data;
276
277   GOptionEntry    *entries;
278   gint             n_entries;
279
280   GOptionParseFunc pre_parse_func;
281   GOptionParseFunc post_parse_func;
282   GOptionErrorFunc error_func;
283 };
284
285 static void free_changes_list (GOptionContext *context,
286                                gboolean        revert);
287 static void free_pending_nulls (GOptionContext *context,
288                                 gboolean        perform_nulls);
289
290
291 static int
292 _g_unichar_get_width (gunichar c)
293 {
294   if (G_UNLIKELY (g_unichar_iszerowidth (c)))
295     return 0;
296
297   /* we ignore the fact that we should call g_unichar_iswide_cjk() under
298    * some locales (legacy East Asian ones) */
299   if (g_unichar_iswide (c))
300     return 2;
301
302   return 1;
303 }
304
305 static glong
306 _g_utf8_strwidth (const gchar *p)
307 {
308   glong len = 0;
309   g_return_val_if_fail (p != NULL, 0);
310
311   while (*p)
312     {
313       len += _g_unichar_get_width (g_utf8_get_char (p));
314       p = g_utf8_next_char (p);
315     }
316
317   return len;
318 }
319
320 G_DEFINE_QUARK (g-option-context-error-quark, g_option_error)
321
322 /**
323  * g_option_context_new:
324  * @parameter_string: (allow-none): a string which is displayed in
325  *    the first line of `--help` output, after the usage summary
326  *    `programname [OPTION...]`
327  *
328  * Creates a new option context.
329  *
330  * The @parameter_string can serve multiple purposes. It can be used
331  * to add descriptions for "rest" arguments, which are not parsed by
332  * the #GOptionContext, typically something like "FILES" or
333  * "FILE1 FILE2...". If you are using #G_OPTION_REMAINING for
334  * collecting "rest" arguments, GLib handles this automatically by
335  * using the @arg_description of the corresponding #GOptionEntry in
336  * the usage summary.
337  *
338  * Another usage is to give a short summary of the program
339  * functionality, like " - frob the strings", which will be displayed
340  * in the same line as the usage. For a longer description of the
341  * program functionality that should be displayed as a paragraph
342  * below the usage line, use g_option_context_set_summary().
343  *
344  * Note that the @parameter_string is translated using the
345  * function set with g_option_context_set_translate_func(), so
346  * it should normally be passed untranslated.
347  *
348  * Returns: a newly created #GOptionContext, which must be
349  *    freed with g_option_context_free() after use.
350  *
351  * Since: 2.6
352  */
353 GOptionContext *
354 g_option_context_new (const gchar *parameter_string)
355
356 {
357   GOptionContext *context;
358
359   context = g_new0 (GOptionContext, 1);
360
361   context->parameter_string = g_strdup (parameter_string);
362   context->strict_posix = FALSE;
363   context->help_enabled = TRUE;
364   context->ignore_unknown = FALSE;
365
366   return context;
367 }
368
369 /**
370  * g_option_context_free:
371  * @context: a #GOptionContext
372  *
373  * Frees context and all the groups which have been
374  * added to it.
375  *
376  * Please note that parsed arguments need to be freed separately (see
377  * #GOptionEntry).
378  *
379  * Since: 2.6
380  */
381 void g_option_context_free (GOptionContext *context)
382 {
383   g_return_if_fail (context != NULL);
384
385   g_list_free_full (context->groups, (GDestroyNotify) g_option_group_free);
386
387   if (context->main_group)
388     g_option_group_free (context->main_group);
389
390   free_changes_list (context, FALSE);
391   free_pending_nulls (context, FALSE);
392
393   g_free (context->parameter_string);
394   g_free (context->summary);
395   g_free (context->description);
396
397   if (context->translate_notify)
398     (* context->translate_notify) (context->translate_data);
399
400   g_free (context);
401 }
402
403
404 /**
405  * g_option_context_set_help_enabled:
406  * @context: a #GOptionContext
407  * @help_enabled: %TRUE to enable `--help`, %FALSE to disable it
408  *
409  * Enables or disables automatic generation of `--help` output.
410  * By default, g_option_context_parse() recognizes `--help`, `-h`,
411  * `-?`, `--help-all` and `--help-groupname` and creates suitable
412  * output to stdout.
413  *
414  * Since: 2.6
415  */
416 void g_option_context_set_help_enabled (GOptionContext *context,
417                                         gboolean        help_enabled)
418
419 {
420   g_return_if_fail (context != NULL);
421
422   context->help_enabled = help_enabled;
423 }
424
425 /**
426  * g_option_context_get_help_enabled:
427  * @context: a #GOptionContext
428  *
429  * Returns whether automatic `--help` generation
430  * is turned on for @context. See g_option_context_set_help_enabled().
431  *
432  * Returns: %TRUE if automatic help generation is turned on.
433  *
434  * Since: 2.6
435  */
436 gboolean
437 g_option_context_get_help_enabled (GOptionContext *context)
438 {
439   g_return_val_if_fail (context != NULL, FALSE);
440
441   return context->help_enabled;
442 }
443
444 /**
445  * g_option_context_set_ignore_unknown_options:
446  * @context: a #GOptionContext
447  * @ignore_unknown: %TRUE to ignore unknown options, %FALSE to produce
448  *    an error when unknown options are met
449  *
450  * Sets whether to ignore unknown options or not. If an argument is
451  * ignored, it is left in the @argv array after parsing. By default,
452  * g_option_context_parse() treats unknown options as error.
453  *
454  * This setting does not affect non-option arguments (i.e. arguments
455  * which don't start with a dash). But note that GOption cannot reliably
456  * determine whether a non-option belongs to a preceding unknown option.
457  *
458  * Since: 2.6
459  **/
460 void
461 g_option_context_set_ignore_unknown_options (GOptionContext *context,
462                                              gboolean        ignore_unknown)
463 {
464   g_return_if_fail (context != NULL);
465
466   context->ignore_unknown = ignore_unknown;
467 }
468
469 /**
470  * g_option_context_get_ignore_unknown_options:
471  * @context: a #GOptionContext
472  *
473  * Returns whether unknown options are ignored or not. See
474  * g_option_context_set_ignore_unknown_options().
475  *
476  * Returns: %TRUE if unknown options are ignored.
477  *
478  * Since: 2.6
479  **/
480 gboolean
481 g_option_context_get_ignore_unknown_options (GOptionContext *context)
482 {
483   g_return_val_if_fail (context != NULL, FALSE);
484
485   return context->ignore_unknown;
486 }
487
488 /**
489  * g_option_context_set_strict_posix:
490  * @context: a #GoptionContext
491  *
492  * Sets strict POSIX mode.
493  *
494  * By default, this mode is disabled.
495  *
496  * In strict POSIX mode, the first non-argument parameter encountered
497  * (eg: filename) terminates argument processing.  Remaining arguments
498  * are treated as non-options and are not attempted to be parsed.
499  *
500  * If strict POSIX mode is disabled then parsing is done in the GNU way
501  * where option arguments can be freely mixed with non-options.
502  *
503  * As an example, consider "ls foo -l".  With GNU style parsing, this
504  * will list "foo" in long mode.  In strict POSIX style, this will list
505  * the files named "foo" and "-l".
506  *
507  * It may be useful to force strict POSIX mode when creating "verb
508  * style" command line tools.  For example, the "gsettings" command line
509  * tool supports the global option "--schemadir" as well as many
510  * subcommands ("get", "set", etc.) which each have their own set of
511  * arguments.  Using strict POSIX mode will allow parsing the global
512  * options up to the verb name while leaving the remaining options to be
513  * parsed by the relevant subcommand (which can be determined by
514  * examining the verb name, which should be present in argv[1] after
515  * parsing).
516  *
517  * Since: 2.44
518  **/
519 void
520 g_option_context_set_strict_posix (GOptionContext *context,
521                                    gboolean        strict_posix)
522 {
523   g_return_if_fail (context != NULL);
524
525   context->strict_posix = strict_posix;
526 }
527
528 /**
529  * g_option_context_get_strict_posix:
530  * @context: a #GoptionContext
531  *
532  * Returns whether strict POSIX code is enabled.
533  *
534  * See g_option_context_set_strict_posix() for more information.
535  *
536  * Since: 2.44
537  **/
538 gboolean
539 g_option_context_get_strict_posix (GOptionContext *context)
540 {
541   g_return_val_if_fail (context != NULL, FALSE);
542
543   return context->strict_posix;
544 }
545
546 /**
547  * g_option_context_add_group:
548  * @context: a #GOptionContext
549  * @group: the group to add
550  *
551  * Adds a #GOptionGroup to the @context, so that parsing with @context
552  * will recognize the options in the group. Note that the group will
553  * be freed together with the context when g_option_context_free() is
554  * called, so you must not free the group yourself after adding it
555  * to a context.
556  *
557  * Since: 2.6
558  **/
559 void
560 g_option_context_add_group (GOptionContext *context,
561                             GOptionGroup   *group)
562 {
563   GList *list;
564
565   g_return_if_fail (context != NULL);
566   g_return_if_fail (group != NULL);
567   g_return_if_fail (group->name != NULL);
568   g_return_if_fail (group->description != NULL);
569   g_return_if_fail (group->help_description != NULL);
570
571   for (list = context->groups; list; list = list->next)
572     {
573       GOptionGroup *g = (GOptionGroup *)list->data;
574
575       if ((group->name == NULL && g->name == NULL) ||
576           (group->name && g->name && strcmp (group->name, g->name) == 0))
577         g_warning ("A group named \"%s\" is already part of this GOptionContext",
578                    group->name);
579     }
580
581   context->groups = g_list_append (context->groups, group);
582 }
583
584 /**
585  * g_option_context_set_main_group:
586  * @context: a #GOptionContext
587  * @group: the group to set as main group
588  *
589  * Sets a #GOptionGroup as main group of the @context.
590  * This has the same effect as calling g_option_context_add_group(),
591  * the only difference is that the options in the main group are
592  * treated differently when generating `--help` output.
593  *
594  * Since: 2.6
595  **/
596 void
597 g_option_context_set_main_group (GOptionContext *context,
598                                  GOptionGroup   *group)
599 {
600   g_return_if_fail (context != NULL);
601   g_return_if_fail (group != NULL);
602
603   if (context->main_group)
604     {
605       g_warning ("This GOptionContext already has a main group");
606
607       return;
608     }
609
610   context->main_group = group;
611 }
612
613 /**
614  * g_option_context_get_main_group:
615  * @context: a #GOptionContext
616  *
617  * Returns a pointer to the main group of @context.
618  *
619  * Returns: the main group of @context, or %NULL if @context doesn't
620  *  have a main group. Note that group belongs to @context and should
621  *  not be modified or freed.
622  *
623  * Since: 2.6
624  **/
625 GOptionGroup *
626 g_option_context_get_main_group (GOptionContext *context)
627 {
628   g_return_val_if_fail (context != NULL, NULL);
629
630   return context->main_group;
631 }
632
633 /**
634  * g_option_context_add_main_entries:
635  * @context: a #GOptionContext
636  * @entries: a %NULL-terminated array of #GOptionEntrys
637  * @translation_domain: (allow-none): a translation domain to use for translating
638  *    the `--help` output for the options in @entries
639  *    with gettext(), or %NULL
640  *
641  * A convenience function which creates a main group if it doesn't
642  * exist, adds the @entries to it and sets the translation domain.
643  *
644  * Since: 2.6
645  **/
646 void
647 g_option_context_add_main_entries (GOptionContext      *context,
648                                    const GOptionEntry  *entries,
649                                    const gchar         *translation_domain)
650 {
651   g_return_if_fail (entries != NULL);
652
653   if (!context->main_group)
654     context->main_group = g_option_group_new (NULL, NULL, NULL, NULL, NULL);
655
656   g_option_group_add_entries (context->main_group, entries);
657   g_option_group_set_translation_domain (context->main_group, translation_domain);
658 }
659
660 static gint
661 calculate_max_length (GOptionGroup *group,
662                       GHashTable   *aliases)
663 {
664   GOptionEntry *entry;
665   gint i, len, max_length;
666   const gchar *long_name;
667
668   max_length = 0;
669
670   for (i = 0; i < group->n_entries; i++)
671     {
672       entry = &group->entries[i];
673
674       if (entry->flags & G_OPTION_FLAG_HIDDEN)
675         continue;
676
677       long_name = g_hash_table_lookup (aliases, &entry->long_name);
678       if (!long_name)
679         long_name = entry->long_name;
680       len = _g_utf8_strwidth (long_name);
681
682       if (entry->short_name)
683         len += 4;
684
685       if (!NO_ARG (entry) && entry->arg_description)
686         len += 1 + _g_utf8_strwidth (TRANSLATE (group, entry->arg_description));
687
688       max_length = MAX (max_length, len);
689     }
690
691   return max_length;
692 }
693
694 static void
695 print_entry (GOptionGroup       *group,
696              gint                max_length,
697              const GOptionEntry *entry,
698              GString            *string,
699              GHashTable         *aliases)
700 {
701   GString *str;
702   const gchar *long_name;
703
704   if (entry->flags & G_OPTION_FLAG_HIDDEN)
705     return;
706
707   if (entry->long_name[0] == 0)
708     return;
709
710   long_name = g_hash_table_lookup (aliases, &entry->long_name);
711   if (!long_name)
712     long_name = entry->long_name;
713
714   str = g_string_new (NULL);
715
716   if (entry->short_name)
717     g_string_append_printf (str, "  -%c, --%s", entry->short_name, long_name);
718   else
719     g_string_append_printf (str, "  --%s", long_name);
720
721   if (entry->arg_description)
722     g_string_append_printf (str, "=%s", TRANSLATE (group, entry->arg_description));
723
724   g_string_append_printf (string, "%s%*s %s\n", str->str,
725                           (int) (max_length + 4 - _g_utf8_strwidth (str->str)), "",
726                           entry->description ? TRANSLATE (group, entry->description) : "");
727   g_string_free (str, TRUE);
728 }
729
730 static gboolean
731 group_has_visible_entries (GOptionContext *context,
732                            GOptionGroup *group,
733                            gboolean      main_entries)
734 {
735   GOptionFlags reject_filter = G_OPTION_FLAG_HIDDEN;
736   GOptionEntry *entry;
737   gint i, l;
738   gboolean main_group = group == context->main_group;
739
740   if (!main_entries)
741     reject_filter |= G_OPTION_FLAG_IN_MAIN;
742
743   for (i = 0, l = (group ? group->n_entries : 0); i < l; i++)
744     {
745       entry = &group->entries[i];
746
747       if (main_entries && !main_group && !(entry->flags & G_OPTION_FLAG_IN_MAIN))
748         continue;
749       if (entry->long_name[0] == 0) /* ignore rest entry */
750         continue;
751       if (!(entry->flags & reject_filter))
752         return TRUE;
753     }
754
755   return FALSE;
756 }
757
758 static gboolean
759 group_list_has_visible_entries (GOptionContext *context,
760                                 GList          *group_list,
761                                 gboolean       main_entries)
762 {
763   while (group_list)
764     {
765       if (group_has_visible_entries (context, group_list->data, main_entries))
766         return TRUE;
767
768       group_list = group_list->next;
769     }
770
771   return FALSE;
772 }
773
774 static gboolean
775 context_has_h_entry (GOptionContext *context)
776 {
777   gsize i;
778   GList *list;
779
780   if (context->main_group)
781     {
782       for (i = 0; i < context->main_group->n_entries; i++)
783         {
784           if (context->main_group->entries[i].short_name == 'h')
785             return TRUE;
786         }
787     }
788
789   for (list = context->groups; list != NULL; list = g_list_next (list))
790     {
791      GOptionGroup *group;
792
793       group = (GOptionGroup*)list->data;
794       for (i = 0; i < group->n_entries; i++)
795         {
796           if (group->entries[i].short_name == 'h')
797             return TRUE;
798         }
799     }
800   return FALSE;
801 }
802
803 /**
804  * g_option_context_get_help:
805  * @context: a #GOptionContext
806  * @main_help: if %TRUE, only include the main group
807  * @group: (allow-none): the #GOptionGroup to create help for, or %NULL
808  *
809  * Returns a formatted, translated help text for the given context.
810  * To obtain the text produced by `--help`, call
811  * `g_option_context_get_help (context, TRUE, NULL)`.
812  * To obtain the text produced by `--help-all`, call
813  * `g_option_context_get_help (context, FALSE, NULL)`.
814  * To obtain the help text for an option group, call
815  * `g_option_context_get_help (context, FALSE, group)`.
816  *
817  * Returns: A newly allocated string containing the help text
818  *
819  * Since: 2.14
820  */
821 gchar *
822 g_option_context_get_help (GOptionContext *context,
823                            gboolean        main_help,
824                            GOptionGroup   *group)
825 {
826   GList *list;
827   gint max_length = 0, len;
828   gint i;
829   GOptionEntry *entry;
830   GHashTable *shadow_map;
831   GHashTable *aliases;
832   gboolean seen[256];
833   const gchar *rest_description;
834   GString *string;
835   guchar token;
836
837   string = g_string_sized_new (1024);
838
839   rest_description = NULL;
840   if (context->main_group)
841     {
842
843       for (i = 0; i < context->main_group->n_entries; i++)
844         {
845           entry = &context->main_group->entries[i];
846           if (entry->long_name[0] == 0)
847             {
848               rest_description = TRANSLATE (context->main_group, entry->arg_description);
849               break;
850             }
851         }
852     }
853
854   g_string_append_printf (string, "%s\n  %s %s",
855                           _("Usage:"), g_get_prgname(), _("[OPTION...]"));
856
857   if (rest_description)
858     {
859       g_string_append (string, " ");
860       g_string_append (string, rest_description);
861     }
862
863   if (context->parameter_string)
864     {
865       g_string_append (string, " ");
866       g_string_append (string, TRANSLATE (context, context->parameter_string));
867     }
868
869   g_string_append (string, "\n\n");
870
871   if (context->summary)
872     {
873       g_string_append (string, TRANSLATE (context, context->summary));
874       g_string_append (string, "\n\n");
875     }
876
877   memset (seen, 0, sizeof (gboolean) * 256);
878   shadow_map = g_hash_table_new (g_str_hash, g_str_equal);
879   aliases = g_hash_table_new_full (NULL, NULL, NULL, g_free);
880
881   if (context->main_group)
882     {
883       for (i = 0; i < context->main_group->n_entries; i++)
884         {
885           entry = &context->main_group->entries[i];
886           g_hash_table_insert (shadow_map,
887                                (gpointer)entry->long_name,
888                                entry);
889
890           if (seen[(guchar)entry->short_name])
891             entry->short_name = 0;
892           else
893             seen[(guchar)entry->short_name] = TRUE;
894         }
895     }
896
897   list = context->groups;
898   while (list != NULL)
899     {
900       GOptionGroup *g = list->data;
901       for (i = 0; i < g->n_entries; i++)
902         {
903           entry = &g->entries[i];
904           if (g_hash_table_lookup (shadow_map, entry->long_name) &&
905               !(entry->flags & G_OPTION_FLAG_NOALIAS))
906             {
907               g_hash_table_insert (aliases, &entry->long_name,
908                                    g_strdup_printf ("%s-%s", g->name, entry->long_name));
909             }
910           else
911             g_hash_table_insert (shadow_map, (gpointer)entry->long_name, entry);
912
913           if (seen[(guchar)entry->short_name] &&
914               !(entry->flags & G_OPTION_FLAG_NOALIAS))
915             entry->short_name = 0;
916           else
917             seen[(guchar)entry->short_name] = TRUE;
918         }
919       list = list->next;
920     }
921
922   g_hash_table_destroy (shadow_map);
923
924   list = context->groups;
925
926   if (context->help_enabled)
927     {
928       max_length = _g_utf8_strwidth ("-?, --help");
929
930       if (list)
931         {
932           len = _g_utf8_strwidth ("--help-all");
933           max_length = MAX (max_length, len);
934         }
935     }
936
937   if (context->main_group)
938     {
939       len = calculate_max_length (context->main_group, aliases);
940       max_length = MAX (max_length, len);
941     }
942
943   while (list != NULL)
944     {
945       GOptionGroup *g = list->data;
946
947       if (context->help_enabled)
948         {
949           /* First, we check the --help-<groupname> options */
950           len = _g_utf8_strwidth ("--help-") + _g_utf8_strwidth (g->name);
951           max_length = MAX (max_length, len);
952         }
953
954       /* Then we go through the entries */
955       len = calculate_max_length (g, aliases);
956       max_length = MAX (max_length, len);
957
958       list = list->next;
959     }
960
961   /* Add a bit of padding */
962   max_length += 4;
963
964   if (!group && context->help_enabled)
965     {
966       list = context->groups;
967
968       token = context_has_h_entry (context) ? '?' : 'h';
969
970       g_string_append_printf (string, "%s\n  -%c, --%-*s %s\n",
971                               _("Help Options:"), token, max_length - 4, "help",
972                               _("Show help options"));
973
974       /* We only want --help-all when there are groups */
975       if (list)
976         g_string_append_printf (string, "  --%-*s %s\n",
977                                 max_length, "help-all",
978                                 _("Show all help options"));
979
980       while (list)
981         {
982           GOptionGroup *g = list->data;
983
984           if (group_has_visible_entries (context, g, FALSE))
985             g_string_append_printf (string, "  --help-%-*s %s\n",
986                                     max_length - 5, g->name,
987                                     TRANSLATE (g, g->help_description));
988
989           list = list->next;
990         }
991
992       g_string_append (string, "\n");
993     }
994
995   if (group)
996     {
997       /* Print a certain group */
998
999       if (group_has_visible_entries (context, group, FALSE))
1000         {
1001           g_string_append (string, TRANSLATE (group, group->description));
1002           g_string_append (string, "\n");
1003           for (i = 0; i < group->n_entries; i++)
1004             print_entry (group, max_length, &group->entries[i], string, aliases);
1005           g_string_append (string, "\n");
1006         }
1007     }
1008   else if (!main_help)
1009     {
1010       /* Print all groups */
1011
1012       list = context->groups;
1013
1014       while (list)
1015         {
1016           GOptionGroup *g = list->data;
1017
1018           if (group_has_visible_entries (context, g, FALSE))
1019             {
1020               g_string_append (string, g->description);
1021               g_string_append (string, "\n");
1022               for (i = 0; i < g->n_entries; i++)
1023                 if (!(g->entries[i].flags & G_OPTION_FLAG_IN_MAIN))
1024                   print_entry (g, max_length, &g->entries[i], string, aliases);
1025
1026               g_string_append (string, "\n");
1027             }
1028
1029           list = list->next;
1030         }
1031     }
1032
1033   /* Print application options if --help or --help-all has been specified */
1034   if ((main_help || !group) &&
1035       (group_has_visible_entries (context, context->main_group, TRUE) ||
1036        group_list_has_visible_entries (context, context->groups, TRUE)))
1037     {
1038       list = context->groups;
1039
1040       g_string_append (string,  _("Application Options:"));
1041       g_string_append (string, "\n");
1042       if (context->main_group)
1043         for (i = 0; i < context->main_group->n_entries; i++)
1044           print_entry (context->main_group, max_length,
1045                        &context->main_group->entries[i], string, aliases);
1046
1047       while (list != NULL)
1048         {
1049           GOptionGroup *g = list->data;
1050
1051           /* Print main entries from other groups */
1052           for (i = 0; i < g->n_entries; i++)
1053             if (g->entries[i].flags & G_OPTION_FLAG_IN_MAIN)
1054               print_entry (g, max_length, &g->entries[i], string, aliases);
1055
1056           list = list->next;
1057         }
1058
1059       g_string_append (string, "\n");
1060     }
1061
1062   if (context->description)
1063     {
1064       g_string_append (string, TRANSLATE (context, context->description));
1065       g_string_append (string, "\n");
1066     }
1067
1068   g_hash_table_destroy (aliases);
1069
1070   return g_string_free (string, FALSE);
1071 }
1072
1073 G_GNUC_NORETURN
1074 static void
1075 print_help (GOptionContext *context,
1076             gboolean        main_help,
1077             GOptionGroup   *group)
1078 {
1079   gchar *help;
1080
1081   help = g_option_context_get_help (context, main_help, group);
1082   g_print ("%s", help);
1083   g_free (help);
1084
1085   exit (0);
1086 }
1087
1088 static gboolean
1089 parse_int (const gchar *arg_name,
1090            const gchar *arg,
1091            gint        *result,
1092            GError     **error)
1093 {
1094   gchar *end;
1095   glong tmp;
1096
1097   errno = 0;
1098   tmp = strtol (arg, &end, 0);
1099
1100   if (*arg == '\0' || *end != '\0')
1101     {
1102       g_set_error (error,
1103                    G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1104                    _("Cannot parse integer value '%s' for %s"),
1105                    arg, arg_name);
1106       return FALSE;
1107     }
1108
1109   *result = tmp;
1110   if (*result != tmp || errno == ERANGE)
1111     {
1112       g_set_error (error,
1113                    G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1114                    _("Integer value '%s' for %s out of range"),
1115                    arg, arg_name);
1116       return FALSE;
1117     }
1118
1119   return TRUE;
1120 }
1121
1122
1123 static gboolean
1124 parse_double (const gchar *arg_name,
1125            const gchar *arg,
1126            gdouble        *result,
1127            GError     **error)
1128 {
1129   gchar *end;
1130   gdouble tmp;
1131
1132   errno = 0;
1133   tmp = g_strtod (arg, &end);
1134
1135   if (*arg == '\0' || *end != '\0')
1136     {
1137       g_set_error (error,
1138                    G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1139                    _("Cannot parse double value '%s' for %s"),
1140                    arg, arg_name);
1141       return FALSE;
1142     }
1143   if (errno == ERANGE)
1144     {
1145       g_set_error (error,
1146                    G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1147                    _("Double value '%s' for %s out of range"),
1148                    arg, arg_name);
1149       return FALSE;
1150     }
1151
1152   *result = tmp;
1153
1154   return TRUE;
1155 }
1156
1157
1158 static gboolean
1159 parse_int64 (const gchar *arg_name,
1160              const gchar *arg,
1161              gint64      *result,
1162              GError     **error)
1163 {
1164   gchar *end;
1165   gint64 tmp;
1166
1167   errno = 0;
1168   tmp = g_ascii_strtoll (arg, &end, 0);
1169
1170   if (*arg == '\0' || *end != '\0')
1171     {
1172       g_set_error (error,
1173                    G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1174                    _("Cannot parse integer value '%s' for %s"),
1175                    arg, arg_name);
1176       return FALSE;
1177     }
1178   if (errno == ERANGE)
1179     {
1180       g_set_error (error,
1181                    G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1182                    _("Integer value '%s' for %s out of range"),
1183                    arg, arg_name);
1184       return FALSE;
1185     }
1186
1187   *result = tmp;
1188
1189   return TRUE;
1190 }
1191
1192
1193 static Change *
1194 get_change (GOptionContext *context,
1195             GOptionArg      arg_type,
1196             gpointer        arg_data)
1197 {
1198   GList *list;
1199   Change *change = NULL;
1200
1201   for (list = context->changes; list != NULL; list = list->next)
1202     {
1203       change = list->data;
1204
1205       if (change->arg_data == arg_data)
1206         goto found;
1207     }
1208
1209   change = g_new0 (Change, 1);
1210   change->arg_type = arg_type;
1211   change->arg_data = arg_data;
1212
1213   context->changes = g_list_prepend (context->changes, change);
1214
1215  found:
1216
1217   return change;
1218 }
1219
1220 static void
1221 add_pending_null (GOptionContext *context,
1222                   gchar         **ptr,
1223                   gchar          *value)
1224 {
1225   PendingNull *n;
1226
1227   n = g_new0 (PendingNull, 1);
1228   n->ptr = ptr;
1229   n->value = value;
1230
1231   context->pending_nulls = g_list_prepend (context->pending_nulls, n);
1232 }
1233
1234 static gboolean
1235 parse_arg (GOptionContext *context,
1236            GOptionGroup   *group,
1237            GOptionEntry   *entry,
1238            const gchar    *value,
1239            const gchar    *option_name,
1240            GError        **error)
1241
1242 {
1243   Change *change;
1244
1245   g_assert (value || OPTIONAL_ARG (entry) || NO_ARG (entry));
1246
1247   switch (entry->arg)
1248     {
1249     case G_OPTION_ARG_NONE:
1250       {
1251         (void) get_change (context, G_OPTION_ARG_NONE,
1252                            entry->arg_data);
1253
1254         *(gboolean *)entry->arg_data = !(entry->flags & G_OPTION_FLAG_REVERSE);
1255         break;
1256       }
1257     case G_OPTION_ARG_STRING:
1258       {
1259         gchar *data;
1260
1261 #ifdef G_OS_WIN32
1262         if (!context->strv_mode)
1263           data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1264         else
1265           data = g_strdup (value);
1266 #else
1267         data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1268 #endif
1269
1270         if (!data)
1271           return FALSE;
1272
1273         change = get_change (context, G_OPTION_ARG_STRING,
1274                              entry->arg_data);
1275         g_free (change->allocated.str);
1276
1277         change->prev.str = *(gchar **)entry->arg_data;
1278         change->allocated.str = data;
1279
1280         *(gchar **)entry->arg_data = data;
1281         break;
1282       }
1283     case G_OPTION_ARG_STRING_ARRAY:
1284       {
1285         gchar *data;
1286
1287 #ifdef G_OS_WIN32
1288         if (!context->strv_mode)
1289           data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1290         else
1291           data = g_strdup (value);
1292 #else
1293         data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1294 #endif
1295
1296         if (!data)
1297           return FALSE;
1298
1299         change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
1300                              entry->arg_data);
1301
1302         if (change->allocated.array.len == 0)
1303           {
1304             change->prev.array = *(gchar ***)entry->arg_data;
1305             change->allocated.array.data = g_new (gchar *, 2);
1306           }
1307         else
1308           change->allocated.array.data =
1309             g_renew (gchar *, change->allocated.array.data,
1310                      change->allocated.array.len + 2);
1311
1312         change->allocated.array.data[change->allocated.array.len] = data;
1313         change->allocated.array.data[change->allocated.array.len + 1] = NULL;
1314
1315         change->allocated.array.len ++;
1316
1317         *(gchar ***)entry->arg_data = change->allocated.array.data;
1318
1319         break;
1320       }
1321
1322     case G_OPTION_ARG_FILENAME:
1323       {
1324         gchar *data;
1325
1326 #ifdef G_OS_WIN32
1327         if (!context->strv_mode)
1328           data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1329         else
1330           data = g_strdup (value);
1331
1332         if (!data)
1333           return FALSE;
1334 #else
1335         data = g_strdup (value);
1336 #endif
1337         change = get_change (context, G_OPTION_ARG_FILENAME,
1338                              entry->arg_data);
1339         g_free (change->allocated.str);
1340
1341         change->prev.str = *(gchar **)entry->arg_data;
1342         change->allocated.str = data;
1343
1344         *(gchar **)entry->arg_data = data;
1345         break;
1346       }
1347
1348     case G_OPTION_ARG_FILENAME_ARRAY:
1349       {
1350         gchar *data;
1351
1352 #ifdef G_OS_WIN32
1353         if (!context->strv_mode)
1354           data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1355         else
1356           data = g_strdup (value);
1357
1358         if (!data)
1359           return FALSE;
1360 #else
1361         data = g_strdup (value);
1362 #endif
1363         change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
1364                              entry->arg_data);
1365
1366         if (change->allocated.array.len == 0)
1367           {
1368             change->prev.array = *(gchar ***)entry->arg_data;
1369             change->allocated.array.data = g_new (gchar *, 2);
1370           }
1371         else
1372           change->allocated.array.data =
1373             g_renew (gchar *, change->allocated.array.data,
1374                      change->allocated.array.len + 2);
1375
1376         change->allocated.array.data[change->allocated.array.len] = data;
1377         change->allocated.array.data[change->allocated.array.len + 1] = NULL;
1378
1379         change->allocated.array.len ++;
1380
1381         *(gchar ***)entry->arg_data = change->allocated.array.data;
1382
1383         break;
1384       }
1385
1386     case G_OPTION_ARG_INT:
1387       {
1388         gint data;
1389
1390         if (!parse_int (option_name, value,
1391                         &data,
1392                         error))
1393           return FALSE;
1394
1395         change = get_change (context, G_OPTION_ARG_INT,
1396                              entry->arg_data);
1397         change->prev.integer = *(gint *)entry->arg_data;
1398         *(gint *)entry->arg_data = data;
1399         break;
1400       }
1401     case G_OPTION_ARG_CALLBACK:
1402       {
1403         gchar *data;
1404         gboolean retval;
1405
1406         if (!value && entry->flags & G_OPTION_FLAG_OPTIONAL_ARG)
1407           data = NULL;
1408         else if (entry->flags & G_OPTION_FLAG_NO_ARG)
1409           data = NULL;
1410         else if (entry->flags & G_OPTION_FLAG_FILENAME)
1411           {
1412 #ifdef G_OS_WIN32
1413             if (!context->strv_mode)
1414               data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1415             else
1416               data = g_strdup (value);
1417 #else
1418             data = g_strdup (value);
1419 #endif
1420           }
1421         else
1422           data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1423
1424         if (!(entry->flags & (G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG)) &&
1425             !data)
1426           return FALSE;
1427
1428         retval = (* (GOptionArgFunc) entry->arg_data) (option_name, data, group->user_data, error);
1429
1430         if (!retval && error != NULL && *error == NULL)
1431           g_set_error (error,
1432                        G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
1433                        _("Error parsing option %s"), option_name);
1434
1435         g_free (data);
1436
1437         return retval;
1438
1439         break;
1440       }
1441     case G_OPTION_ARG_DOUBLE:
1442       {
1443         gdouble data;
1444
1445         if (!parse_double (option_name, value,
1446                         &data,
1447                         error))
1448           {
1449             return FALSE;
1450           }
1451
1452         change = get_change (context, G_OPTION_ARG_DOUBLE,
1453                              entry->arg_data);
1454         change->prev.dbl = *(gdouble *)entry->arg_data;
1455         *(gdouble *)entry->arg_data = data;
1456         break;
1457       }
1458     case G_OPTION_ARG_INT64:
1459       {
1460         gint64 data;
1461
1462         if (!parse_int64 (option_name, value,
1463                          &data,
1464                          error))
1465           {
1466             return FALSE;
1467           }
1468
1469         change = get_change (context, G_OPTION_ARG_INT64,
1470                              entry->arg_data);
1471         change->prev.int64 = *(gint64 *)entry->arg_data;
1472         *(gint64 *)entry->arg_data = data;
1473         break;
1474       }
1475     default:
1476       g_assert_not_reached ();
1477     }
1478
1479   return TRUE;
1480 }
1481
1482 static gboolean
1483 parse_short_option (GOptionContext *context,
1484                     GOptionGroup   *group,
1485                     gint            idx,
1486                     gint           *new_idx,
1487                     gchar           arg,
1488                     gint           *argc,
1489                     gchar        ***argv,
1490                     GError        **error,
1491                     gboolean       *parsed)
1492 {
1493   gint j;
1494
1495   for (j = 0; j < group->n_entries; j++)
1496     {
1497       if (arg == group->entries[j].short_name)
1498         {
1499           gchar *option_name;
1500           gchar *value = NULL;
1501
1502           option_name = g_strdup_printf ("-%c", group->entries[j].short_name);
1503
1504           if (NO_ARG (&group->entries[j]))
1505             value = NULL;
1506           else
1507             {
1508               if (*new_idx > idx)
1509                 {
1510                   g_set_error (error,
1511                                G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
1512                                _("Error parsing option %s"), option_name);
1513                   g_free (option_name);
1514                   return FALSE;
1515                 }
1516
1517               if (idx < *argc - 1)
1518                 {
1519                   if (!OPTIONAL_ARG (&group->entries[j]))
1520                     {
1521                       value = (*argv)[idx + 1];
1522                       add_pending_null (context, &((*argv)[idx + 1]), NULL);
1523                       *new_idx = idx + 1;
1524                     }
1525                   else
1526                     {
1527                       if ((*argv)[idx + 1][0] == '-')
1528                         value = NULL;
1529                       else
1530                         {
1531                           value = (*argv)[idx + 1];
1532                           add_pending_null (context, &((*argv)[idx + 1]), NULL);
1533                           *new_idx = idx + 1;
1534                         }
1535                     }
1536                 }
1537               else if (idx >= *argc - 1 && OPTIONAL_ARG (&group->entries[j]))
1538                 value = NULL;
1539               else
1540                 {
1541                   g_set_error (error,
1542                                G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1543                                _("Missing argument for %s"), option_name);
1544                   g_free (option_name);
1545                   return FALSE;
1546                 }
1547             }
1548
1549           if (!parse_arg (context, group, &group->entries[j],
1550                           value, option_name, error))
1551             {
1552               g_free (option_name);
1553               return FALSE;
1554             }
1555
1556           g_free (option_name);
1557           *parsed = TRUE;
1558         }
1559     }
1560
1561   return TRUE;
1562 }
1563
1564 static gboolean
1565 parse_long_option (GOptionContext *context,
1566                    GOptionGroup   *group,
1567                    gint           *idx,
1568                    gchar          *arg,
1569                    gboolean        aliased,
1570                    gint           *argc,
1571                    gchar        ***argv,
1572                    GError        **error,
1573                    gboolean       *parsed)
1574 {
1575   gint j;
1576
1577   for (j = 0; j < group->n_entries; j++)
1578     {
1579       if (*idx >= *argc)
1580         return TRUE;
1581
1582       if (aliased && (group->entries[j].flags & G_OPTION_FLAG_NOALIAS))
1583         continue;
1584
1585       if (NO_ARG (&group->entries[j]) &&
1586           strcmp (arg, group->entries[j].long_name) == 0)
1587         {
1588           gchar *option_name;
1589           gboolean retval;
1590
1591           option_name = g_strconcat ("--", group->entries[j].long_name, NULL);
1592           retval = parse_arg (context, group, &group->entries[j],
1593                               NULL, option_name, error);
1594           g_free (option_name);
1595
1596           add_pending_null (context, &((*argv)[*idx]), NULL);
1597           *parsed = TRUE;
1598
1599           return retval;
1600         }
1601       else
1602         {
1603           gint len = strlen (group->entries[j].long_name);
1604
1605           if (strncmp (arg, group->entries[j].long_name, len) == 0 &&
1606               (arg[len] == '=' || arg[len] == 0))
1607             {
1608               gchar *value = NULL;
1609               gchar *option_name;
1610
1611               add_pending_null (context, &((*argv)[*idx]), NULL);
1612               option_name = g_strconcat ("--", group->entries[j].long_name, NULL);
1613
1614               if (arg[len] == '=')
1615                 value = arg + len + 1;
1616               else if (*idx < *argc - 1)
1617                 {
1618                   if (!OPTIONAL_ARG (&group->entries[j]))
1619                     {
1620                       value = (*argv)[*idx + 1];
1621                       add_pending_null (context, &((*argv)[*idx + 1]), NULL);
1622                       (*idx)++;
1623                     }
1624                   else
1625                     {
1626                       if ((*argv)[*idx + 1][0] == '-')
1627                         {
1628                           gboolean retval;
1629                           retval = parse_arg (context, group, &group->entries[j],
1630                                               NULL, option_name, error);
1631                           *parsed = TRUE;
1632                           g_free (option_name);
1633                           return retval;
1634                         }
1635                       else
1636                         {
1637                           value = (*argv)[*idx + 1];
1638                           add_pending_null (context, &((*argv)[*idx + 1]), NULL);
1639                           (*idx)++;
1640                         }
1641                     }
1642                 }
1643               else if (*idx >= *argc - 1 && OPTIONAL_ARG (&group->entries[j]))
1644                 {
1645                     gboolean retval;
1646                     retval = parse_arg (context, group, &group->entries[j],
1647                                         NULL, option_name, error);
1648                     *parsed = TRUE;
1649                     g_free (option_name);
1650                     return retval;
1651                 }
1652               else
1653                 {
1654                   g_set_error (error,
1655                                G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1656                                _("Missing argument for %s"), option_name);
1657                   g_free (option_name);
1658                   return FALSE;
1659                 }
1660
1661               if (!parse_arg (context, group, &group->entries[j],
1662                               value, option_name, error))
1663                 {
1664                   g_free (option_name);
1665                   return FALSE;
1666                 }
1667
1668               g_free (option_name);
1669               *parsed = TRUE;
1670             }
1671         }
1672     }
1673
1674   return TRUE;
1675 }
1676
1677 static gboolean
1678 parse_remaining_arg (GOptionContext *context,
1679                      GOptionGroup   *group,
1680                      gint           *idx,
1681                      gint           *argc,
1682                      gchar        ***argv,
1683                      GError        **error,
1684                      gboolean       *parsed)
1685 {
1686   gint j;
1687
1688   for (j = 0; j < group->n_entries; j++)
1689     {
1690       if (*idx >= *argc)
1691         return TRUE;
1692
1693       if (group->entries[j].long_name[0])
1694         continue;
1695
1696       g_return_val_if_fail (group->entries[j].arg == G_OPTION_ARG_CALLBACK ||
1697                             group->entries[j].arg == G_OPTION_ARG_STRING_ARRAY ||
1698                             group->entries[j].arg == G_OPTION_ARG_FILENAME_ARRAY, FALSE);
1699
1700       add_pending_null (context, &((*argv)[*idx]), NULL);
1701
1702       if (!parse_arg (context, group, &group->entries[j], (*argv)[*idx], "", error))
1703         return FALSE;
1704
1705       *parsed = TRUE;
1706       return TRUE;
1707     }
1708
1709   return TRUE;
1710 }
1711
1712 static void
1713 free_changes_list (GOptionContext *context,
1714                    gboolean        revert)
1715 {
1716   GList *list;
1717
1718   for (list = context->changes; list != NULL; list = list->next)
1719     {
1720       Change *change = list->data;
1721
1722       if (revert)
1723         {
1724           switch (change->arg_type)
1725             {
1726             case G_OPTION_ARG_NONE:
1727               *(gboolean *)change->arg_data = change->prev.bool;
1728               break;
1729             case G_OPTION_ARG_INT:
1730               *(gint *)change->arg_data = change->prev.integer;
1731               break;
1732             case G_OPTION_ARG_STRING:
1733             case G_OPTION_ARG_FILENAME:
1734               g_free (change->allocated.str);
1735               *(gchar **)change->arg_data = change->prev.str;
1736               break;
1737             case G_OPTION_ARG_STRING_ARRAY:
1738             case G_OPTION_ARG_FILENAME_ARRAY:
1739               g_strfreev (change->allocated.array.data);
1740               *(gchar ***)change->arg_data = change->prev.array;
1741               break;
1742             case G_OPTION_ARG_DOUBLE:
1743               *(gdouble *)change->arg_data = change->prev.dbl;
1744               break;
1745             case G_OPTION_ARG_INT64:
1746               *(gint64 *)change->arg_data = change->prev.int64;
1747               break;
1748             default:
1749               g_assert_not_reached ();
1750             }
1751         }
1752
1753       g_free (change);
1754     }
1755
1756   g_list_free (context->changes);
1757   context->changes = NULL;
1758 }
1759
1760 static void
1761 free_pending_nulls (GOptionContext *context,
1762                     gboolean        perform_nulls)
1763 {
1764   GList *list;
1765
1766   for (list = context->pending_nulls; list != NULL; list = list->next)
1767     {
1768       PendingNull *n = list->data;
1769
1770       if (perform_nulls)
1771         {
1772           if (n->value)
1773             {
1774               /* Copy back the short options */
1775               *(n->ptr)[0] = '-';
1776               strcpy (*n->ptr + 1, n->value);
1777             }
1778           else
1779             {
1780               if (context->strv_mode)
1781                 g_free (*n->ptr);
1782
1783               *n->ptr = NULL;
1784             }
1785         }
1786
1787       g_free (n->value);
1788       g_free (n);
1789     }
1790
1791   g_list_free (context->pending_nulls);
1792   context->pending_nulls = NULL;
1793 }
1794
1795 /* Use a platform-specific mechanism to look up the first argument to
1796  * the current process. 
1797  * Note if you implement this for other platforms, also add it to
1798  * tests/option-argv0.c
1799  */
1800 static char *
1801 platform_get_argv0 (void)
1802 {
1803 #if defined __linux
1804   char *cmdline;
1805   char *base_arg0;
1806   gsize len;
1807
1808   if (!g_file_get_contents ("/proc/self/cmdline",
1809                             &cmdline,
1810                             &len,
1811                             NULL))
1812     return NULL;
1813   /* Sanity check for a NUL terminator. */
1814   if (!memchr (cmdline, 0, len))
1815     return NULL;
1816   /* We could just return cmdline, but I think it's better
1817    * to hold on to a smaller malloc block; the arguments
1818    * could be large.
1819    */
1820   base_arg0 = g_path_get_basename (cmdline);
1821   g_free (cmdline);
1822   return base_arg0;
1823 #elif defined __OpenBSD__
1824   char **cmdline;
1825   char *base_arg0;
1826   gsize len;
1827
1828   int mib[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
1829
1830   if (sysctl (mib, G_N_ELEMENTS (mib), NULL, &len, NULL, 0) == -1)
1831       return NULL;
1832
1833   cmdline = g_malloc0 (len);
1834
1835   if (sysctl (mib, G_N_ELEMENTS (mib), cmdline, &len, NULL, 0) == -1)
1836     {
1837       g_free (cmdline);
1838       return NULL;
1839     }
1840
1841   /* We could just return cmdline, but I think it's better
1842    * to hold on to a smaller malloc block; the arguments
1843    * could be large.
1844    */
1845   base_arg0 = g_path_get_basename (*cmdline);
1846   g_free (cmdline);
1847   return base_arg0;
1848 #endif
1849
1850   return NULL;
1851 }
1852
1853 /**
1854  * g_option_context_parse:
1855  * @context: a #GOptionContext
1856  * @argc: (inout) (allow-none): a pointer to the number of command line arguments
1857  * @argv: (inout) (array length=argc) (allow-none): a pointer to the array of command line arguments
1858  * @error: a return location for errors
1859  *
1860  * Parses the command line arguments, recognizing options
1861  * which have been added to @context. A side-effect of
1862  * calling this function is that g_set_prgname() will be
1863  * called.
1864  *
1865  * If the parsing is successful, any parsed arguments are
1866  * removed from the array and @argc and @argv are updated
1867  * accordingly. A '--' option is stripped from @argv
1868  * unless there are unparsed options before and after it,
1869  * or some of the options after it start with '-'. In case
1870  * of an error, @argc and @argv are left unmodified.
1871  *
1872  * If automatic `--help` support is enabled
1873  * (see g_option_context_set_help_enabled()), and the
1874  * @argv array contains one of the recognized help options,
1875  * this function will produce help output to stdout and
1876  * call `exit (0)`.
1877  *
1878  * Note that function depends on the [current locale][setlocale] for
1879  * automatic character set conversion of string and filename
1880  * arguments.
1881  *
1882  * Returns: %TRUE if the parsing was successful,
1883  *               %FALSE if an error occurred
1884  *
1885  * Since: 2.6
1886  **/
1887 gboolean
1888 g_option_context_parse (GOptionContext   *context,
1889                         gint             *argc,
1890                         gchar          ***argv,
1891                         GError          **error)
1892 {
1893   gint i, j, k;
1894   GList *list;
1895
1896   /* Set program name */
1897   if (!g_get_prgname())
1898     {
1899       gchar *prgname;
1900
1901       if (argc && argv && *argc)
1902         prgname = g_path_get_basename ((*argv)[0]);
1903       else
1904         prgname = platform_get_argv0 ();
1905
1906       if (prgname)
1907         g_set_prgname (prgname);
1908       else
1909         g_set_prgname ("<unknown>");
1910
1911       g_free (prgname);
1912     }
1913
1914   /* Call pre-parse hooks */
1915   list = context->groups;
1916   while (list)
1917     {
1918       GOptionGroup *group = list->data;
1919
1920       if (group->pre_parse_func)
1921         {
1922           if (!(* group->pre_parse_func) (context, group,
1923                                           group->user_data, error))
1924             goto fail;
1925         }
1926
1927       list = list->next;
1928     }
1929
1930   if (context->main_group && context->main_group->pre_parse_func)
1931     {
1932       if (!(* context->main_group->pre_parse_func) (context, context->main_group,
1933                                                     context->main_group->user_data, error))
1934         goto fail;
1935     }
1936
1937   if (argc && argv)
1938     {
1939       gboolean stop_parsing = FALSE;
1940       gboolean has_unknown = FALSE;
1941       gint separator_pos = 0;
1942
1943       for (i = 1; i < *argc; i++)
1944         {
1945           gchar *arg, *dash;
1946           gboolean parsed = FALSE;
1947
1948           if ((*argv)[i][0] == '-' && (*argv)[i][1] != '\0' && !stop_parsing)
1949             {
1950               if ((*argv)[i][1] == '-')
1951                 {
1952                   /* -- option */
1953
1954                   arg = (*argv)[i] + 2;
1955
1956                   /* '--' terminates list of arguments */
1957                   if (*arg == 0)
1958                     {
1959                       separator_pos = i;
1960                       stop_parsing = TRUE;
1961                       continue;
1962                     }
1963
1964                   /* Handle help options */
1965                   if (context->help_enabled)
1966                     {
1967                       if (strcmp (arg, "help") == 0)
1968                         print_help (context, TRUE, NULL);
1969                       else if (strcmp (arg, "help-all") == 0)
1970                         print_help (context, FALSE, NULL);
1971                       else if (strncmp (arg, "help-", 5) == 0)
1972                         {
1973                           list = context->groups;
1974
1975                           while (list)
1976                             {
1977                               GOptionGroup *group = list->data;
1978
1979                               if (strcmp (arg + 5, group->name) == 0)
1980                                 print_help (context, FALSE, group);
1981
1982                               list = list->next;
1983                             }
1984                         }
1985                     }
1986
1987                   if (context->main_group &&
1988                       !parse_long_option (context, context->main_group, &i, arg,
1989                                           FALSE, argc, argv, error, &parsed))
1990                     goto fail;
1991
1992                   if (parsed)
1993                     continue;
1994
1995                   /* Try the groups */
1996                   list = context->groups;
1997                   while (list)
1998                     {
1999                       GOptionGroup *group = list->data;
2000
2001                       if (!parse_long_option (context, group, &i, arg,
2002                                               FALSE, argc, argv, error, &parsed))
2003                         goto fail;
2004
2005                       if (parsed)
2006                         break;
2007
2008                       list = list->next;
2009                     }
2010
2011                   if (parsed)
2012                     continue;
2013
2014                   /* Now look for --<group>-<option> */
2015                   dash = strchr (arg, '-');
2016                   if (dash)
2017                     {
2018                       /* Try the groups */
2019                       list = context->groups;
2020                       while (list)
2021                         {
2022                           GOptionGroup *group = list->data;
2023
2024                           if (strncmp (group->name, arg, dash - arg) == 0)
2025                             {
2026                               if (!parse_long_option (context, group, &i, dash + 1,
2027                                                       TRUE, argc, argv, error, &parsed))
2028                                 goto fail;
2029
2030                               if (parsed)
2031                                 break;
2032                             }
2033
2034                           list = list->next;
2035                         }
2036                     }
2037
2038                   if (context->ignore_unknown)
2039                     continue;
2040                 }
2041               else
2042                 { /* short option */
2043                   gint new_i = i, arg_length;
2044                   gboolean *nulled_out = NULL;
2045                   gboolean has_h_entry = context_has_h_entry (context);
2046                   arg = (*argv)[i] + 1;
2047                   arg_length = strlen (arg);
2048                   nulled_out = g_newa (gboolean, arg_length);
2049                   memset (nulled_out, 0, arg_length * sizeof (gboolean));
2050                   for (j = 0; j < arg_length; j++)
2051                     {
2052                       if (context->help_enabled && (arg[j] == '?' ||
2053                         (arg[j] == 'h' && !has_h_entry)))
2054                         print_help (context, TRUE, NULL);
2055                       parsed = FALSE;
2056                       if (context->main_group &&
2057                           !parse_short_option (context, context->main_group,
2058                                                i, &new_i, arg[j],
2059                                                argc, argv, error, &parsed))
2060                         goto fail;
2061                       if (!parsed)
2062                         {
2063                           /* Try the groups */
2064                           list = context->groups;
2065                           while (list)
2066                             {
2067                               GOptionGroup *group = list->data;
2068                               if (!parse_short_option (context, group, i, &new_i, arg[j],
2069                                                        argc, argv, error, &parsed))
2070                                 goto fail;
2071                               if (parsed)
2072                                 break;
2073                               list = list->next;
2074                             }
2075                         }
2076
2077                       if (context->ignore_unknown && parsed)
2078                         nulled_out[j] = TRUE;
2079                       else if (context->ignore_unknown)
2080                         continue;
2081                       else if (!parsed)
2082                         break;
2083                       /* !context->ignore_unknown && parsed */
2084                     }
2085                   if (context->ignore_unknown)
2086                     {
2087                       gchar *new_arg = NULL;
2088                       gint arg_index = 0;
2089                       for (j = 0; j < arg_length; j++)
2090                         {
2091                           if (!nulled_out[j])
2092                             {
2093                               if (!new_arg)
2094                                 new_arg = g_malloc (arg_length + 1);
2095                               new_arg[arg_index++] = arg[j];
2096                             }
2097                         }
2098                       if (new_arg)
2099                         new_arg[arg_index] = '\0';
2100                       add_pending_null (context, &((*argv)[i]), new_arg);
2101                       i = new_i;
2102                     }
2103                   else if (parsed)
2104                     {
2105                       add_pending_null (context, &((*argv)[i]), NULL);
2106                       i = new_i;
2107                     }
2108                 }
2109
2110               if (!parsed)
2111                 has_unknown = TRUE;
2112
2113               if (!parsed && !context->ignore_unknown)
2114                 {
2115                   g_set_error (error,
2116                                G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION,
2117                                    _("Unknown option %s"), (*argv)[i]);
2118                   goto fail;
2119                 }
2120             }
2121           else
2122             {
2123               if (context->strict_posix)
2124                 stop_parsing = TRUE;
2125
2126               /* Collect remaining args */
2127               if (context->main_group &&
2128                   !parse_remaining_arg (context, context->main_group, &i,
2129                                         argc, argv, error, &parsed))
2130                 goto fail;
2131
2132               if (!parsed && (has_unknown || (*argv)[i][0] == '-'))
2133                 separator_pos = 0;
2134             }
2135         }
2136
2137       if (separator_pos > 0)
2138         add_pending_null (context, &((*argv)[separator_pos]), NULL);
2139
2140     }
2141
2142   /* Call post-parse hooks */
2143   list = context->groups;
2144   while (list)
2145     {
2146       GOptionGroup *group = list->data;
2147
2148       if (group->post_parse_func)
2149         {
2150           if (!(* group->post_parse_func) (context, group,
2151                                            group->user_data, error))
2152             goto fail;
2153         }
2154
2155       list = list->next;
2156     }
2157
2158   if (context->main_group && context->main_group->post_parse_func)
2159     {
2160       if (!(* context->main_group->post_parse_func) (context, context->main_group,
2161                                                      context->main_group->user_data, error))
2162         goto fail;
2163     }
2164
2165   if (argc && argv)
2166     {
2167       free_pending_nulls (context, TRUE);
2168
2169       for (i = 1; i < *argc; i++)
2170         {
2171           for (k = i; k < *argc; k++)
2172             if ((*argv)[k] != NULL)
2173               break;
2174
2175           if (k > i)
2176             {
2177               k -= i;
2178               for (j = i + k; j < *argc; j++)
2179                 {
2180                   (*argv)[j-k] = (*argv)[j];
2181                   (*argv)[j] = NULL;
2182                 }
2183               *argc -= k;
2184             }
2185         }
2186     }
2187
2188   return TRUE;
2189
2190  fail:
2191
2192   /* Call error hooks */
2193   list = context->groups;
2194   while (list)
2195     {
2196       GOptionGroup *group = list->data;
2197
2198       if (group->error_func)
2199         (* group->error_func) (context, group,
2200                                group->user_data, error);
2201
2202       list = list->next;
2203     }
2204
2205   if (context->main_group && context->main_group->error_func)
2206     (* context->main_group->error_func) (context, context->main_group,
2207                                          context->main_group->user_data, error);
2208
2209   free_changes_list (context, TRUE);
2210   free_pending_nulls (context, FALSE);
2211
2212   return FALSE;
2213 }
2214
2215 /**
2216  * g_option_group_new:
2217  * @name: the name for the option group, this is used to provide
2218  *   help for the options in this group with `--help-`@name
2219  * @description: a description for this group to be shown in
2220  *   `--help`. This string is translated using the translation
2221  *   domain or translation function of the group
2222  * @help_description: a description for the `--help-`@name option.
2223  *   This string is translated using the translation domain or translation function
2224  *   of the group
2225  * @user_data: (allow-none): user data that will be passed to the pre- and post-parse hooks,
2226  *   the error hook and to callbacks of %G_OPTION_ARG_CALLBACK options, or %NULL
2227  * @destroy: (allow-none): a function that will be called to free @user_data, or %NULL
2228  *
2229  * Creates a new #GOptionGroup.
2230  *
2231  * Returns: a newly created option group. It should be added
2232  *   to a #GOptionContext or freed with g_option_group_free().
2233  *
2234  * Since: 2.6
2235  **/
2236 GOptionGroup *
2237 g_option_group_new (const gchar    *name,
2238                     const gchar    *description,
2239                     const gchar    *help_description,
2240                     gpointer        user_data,
2241                     GDestroyNotify  destroy)
2242
2243 {
2244   GOptionGroup *group;
2245
2246   group = g_new0 (GOptionGroup, 1);
2247   group->name = g_strdup (name);
2248   group->description = g_strdup (description);
2249   group->help_description = g_strdup (help_description);
2250   group->user_data = user_data;
2251   group->destroy_notify = destroy;
2252
2253   return group;
2254 }
2255
2256
2257 /**
2258  * g_option_group_free:
2259  * @group: a #GOptionGroup
2260  *
2261  * Frees a #GOptionGroup. Note that you must not free groups
2262  * which have been added to a #GOptionContext.
2263  *
2264  * Since: 2.6
2265  */
2266 void
2267 g_option_group_free (GOptionGroup *group)
2268 {
2269   g_return_if_fail (group != NULL);
2270
2271   g_free (group->name);
2272   g_free (group->description);
2273   g_free (group->help_description);
2274
2275   g_free (group->entries);
2276
2277   if (group->destroy_notify)
2278     (* group->destroy_notify) (group->user_data);
2279
2280   if (group->translate_notify)
2281     (* group->translate_notify) (group->translate_data);
2282
2283   g_free (group);
2284 }
2285
2286
2287 /**
2288  * g_option_group_add_entries:
2289  * @group: a #GOptionGroup
2290  * @entries: a %NULL-terminated array of #GOptionEntrys
2291  *
2292  * Adds the options specified in @entries to @group.
2293  *
2294  * Since: 2.6
2295  **/
2296 void
2297 g_option_group_add_entries (GOptionGroup       *group,
2298                             const GOptionEntry *entries)
2299 {
2300   gint i, n_entries;
2301
2302   g_return_if_fail (entries != NULL);
2303
2304   for (n_entries = 0; entries[n_entries].long_name != NULL; n_entries++) ;
2305
2306   group->entries = g_renew (GOptionEntry, group->entries, group->n_entries + n_entries);
2307
2308   memcpy (group->entries + group->n_entries, entries, sizeof (GOptionEntry) * n_entries);
2309
2310   for (i = group->n_entries; i < group->n_entries + n_entries; i++)
2311     {
2312       gchar c = group->entries[i].short_name;
2313
2314       if (c == '-' || (c != 0 && !g_ascii_isprint (c)))
2315         {
2316           g_warning (G_STRLOC ": ignoring invalid short option '%c' (%d) in entry %s:%s",
2317               c, c, group->name, group->entries[i].long_name);
2318           group->entries[i].short_name = '\0';
2319         }
2320
2321       if (group->entries[i].arg != G_OPTION_ARG_NONE &&
2322           (group->entries[i].flags & G_OPTION_FLAG_REVERSE) != 0)
2323         {
2324           g_warning (G_STRLOC ": ignoring reverse flag on option of arg-type %d in entry %s:%s",
2325               group->entries[i].arg, group->name, group->entries[i].long_name);
2326
2327           group->entries[i].flags &= ~G_OPTION_FLAG_REVERSE;
2328         }
2329
2330       if (group->entries[i].arg != G_OPTION_ARG_CALLBACK &&
2331           (group->entries[i].flags & (G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG|G_OPTION_FLAG_FILENAME)) != 0)
2332         {
2333           g_warning (G_STRLOC ": ignoring no-arg, optional-arg or filename flags (%d) on option of arg-type %d in entry %s:%s",
2334               group->entries[i].flags, group->entries[i].arg, group->name, group->entries[i].long_name);
2335
2336           group->entries[i].flags &= ~(G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG|G_OPTION_FLAG_FILENAME);
2337         }
2338     }
2339
2340   group->n_entries += n_entries;
2341 }
2342
2343 /**
2344  * g_option_group_set_parse_hooks:
2345  * @group: a #GOptionGroup
2346  * @pre_parse_func: (allow-none): a function to call before parsing, or %NULL
2347  * @post_parse_func: (allow-none): a function to call after parsing, or %NULL
2348  *
2349  * Associates two functions with @group which will be called
2350  * from g_option_context_parse() before the first option is parsed
2351  * and after the last option has been parsed, respectively.
2352  *
2353  * Note that the user data to be passed to @pre_parse_func and
2354  * @post_parse_func can be specified when constructing the group
2355  * with g_option_group_new().
2356  *
2357  * Since: 2.6
2358  **/
2359 void
2360 g_option_group_set_parse_hooks (GOptionGroup     *group,
2361                                 GOptionParseFunc  pre_parse_func,
2362                                 GOptionParseFunc  post_parse_func)
2363 {
2364   g_return_if_fail (group != NULL);
2365
2366   group->pre_parse_func = pre_parse_func;
2367   group->post_parse_func = post_parse_func;
2368 }
2369
2370 /**
2371  * g_option_group_set_error_hook:
2372  * @group: a #GOptionGroup
2373  * @error_func: a function to call when an error occurs
2374  *
2375  * Associates a function with @group which will be called
2376  * from g_option_context_parse() when an error occurs.
2377  *
2378  * Note that the user data to be passed to @error_func can be
2379  * specified when constructing the group with g_option_group_new().
2380  *
2381  * Since: 2.6
2382  **/
2383 void
2384 g_option_group_set_error_hook (GOptionGroup     *group,
2385                                GOptionErrorFunc  error_func)
2386 {
2387   g_return_if_fail (group != NULL);
2388
2389   group->error_func = error_func;
2390 }
2391
2392
2393 /**
2394  * g_option_group_set_translate_func:
2395  * @group: a #GOptionGroup
2396  * @func: (allow-none): the #GTranslateFunc, or %NULL
2397  * @data: (allow-none): user data to pass to @func, or %NULL
2398  * @destroy_notify: (allow-none): a function which gets called to free @data, or %NULL
2399  *
2400  * Sets the function which is used to translate user-visible strings,
2401  * for `--help` output. Different groups can use different
2402  * #GTranslateFuncs. If @func is %NULL, strings are not translated.
2403  *
2404  * If you are using gettext(), you only need to set the translation
2405  * domain, see g_option_group_set_translation_domain().
2406  *
2407  * Since: 2.6
2408  **/
2409 void
2410 g_option_group_set_translate_func (GOptionGroup   *group,
2411                                    GTranslateFunc  func,
2412                                    gpointer        data,
2413                                    GDestroyNotify  destroy_notify)
2414 {
2415   g_return_if_fail (group != NULL);
2416
2417   if (group->translate_notify)
2418     group->translate_notify (group->translate_data);
2419
2420   group->translate_func = func;
2421   group->translate_data = data;
2422   group->translate_notify = destroy_notify;
2423 }
2424
2425 static const gchar *
2426 dgettext_swapped (const gchar *msgid,
2427                   const gchar *domainname)
2428 {
2429   return g_dgettext (domainname, msgid);
2430 }
2431
2432 /**
2433  * g_option_group_set_translation_domain:
2434  * @group: a #GOptionGroup
2435  * @domain: the domain to use
2436  *
2437  * A convenience function to use gettext() for translating
2438  * user-visible strings.
2439  *
2440  * Since: 2.6
2441  **/
2442 void
2443 g_option_group_set_translation_domain (GOptionGroup *group,
2444                                        const gchar  *domain)
2445 {
2446   g_return_if_fail (group != NULL);
2447
2448   g_option_group_set_translate_func (group,
2449                                      (GTranslateFunc)dgettext_swapped,
2450                                      g_strdup (domain),
2451                                      g_free);
2452 }
2453
2454 /**
2455  * g_option_context_set_translate_func:
2456  * @context: a #GOptionContext
2457  * @func: (allow-none): the #GTranslateFunc, or %NULL
2458  * @data: (allow-none): user data to pass to @func, or %NULL
2459  * @destroy_notify: (allow-none): a function which gets called to free @data, or %NULL
2460  *
2461  * Sets the function which is used to translate the contexts
2462  * user-visible strings, for `--help` output. If @func is %NULL,
2463  * strings are not translated.
2464  *
2465  * Note that option groups have their own translation functions,
2466  * this function only affects the @parameter_string (see g_option_context_new()),
2467  * the summary (see g_option_context_set_summary()) and the description
2468  * (see g_option_context_set_description()).
2469  *
2470  * If you are using gettext(), you only need to set the translation
2471  * domain, see g_option_context_set_translation_domain().
2472  *
2473  * Since: 2.12
2474  **/
2475 void
2476 g_option_context_set_translate_func (GOptionContext *context,
2477                                      GTranslateFunc func,
2478                                      gpointer       data,
2479                                      GDestroyNotify destroy_notify)
2480 {
2481   g_return_if_fail (context != NULL);
2482
2483   if (context->translate_notify)
2484     context->translate_notify (context->translate_data);
2485
2486   context->translate_func = func;
2487   context->translate_data = data;
2488   context->translate_notify = destroy_notify;
2489 }
2490
2491 /**
2492  * g_option_context_set_translation_domain:
2493  * @context: a #GOptionContext
2494  * @domain: the domain to use
2495  *
2496  * A convenience function to use gettext() for translating
2497  * user-visible strings.
2498  *
2499  * Since: 2.12
2500  **/
2501 void
2502 g_option_context_set_translation_domain (GOptionContext *context,
2503                                          const gchar     *domain)
2504 {
2505   g_return_if_fail (context != NULL);
2506
2507   g_option_context_set_translate_func (context,
2508                                        (GTranslateFunc)dgettext_swapped,
2509                                        g_strdup (domain),
2510                                        g_free);
2511 }
2512
2513 /**
2514  * g_option_context_set_summary:
2515  * @context: a #GOptionContext
2516  * @summary: (allow-none): a string to be shown in `--help` output
2517  *  before the list of options, or %NULL
2518  *
2519  * Adds a string to be displayed in `--help` output before the list
2520  * of options. This is typically a summary of the program functionality.
2521  *
2522  * Note that the summary is translated (see
2523  * g_option_context_set_translate_func() and
2524  * g_option_context_set_translation_domain()).
2525  *
2526  * Since: 2.12
2527  */
2528 void
2529 g_option_context_set_summary (GOptionContext *context,
2530                               const gchar    *summary)
2531 {
2532   g_return_if_fail (context != NULL);
2533
2534   g_free (context->summary);
2535   context->summary = g_strdup (summary);
2536 }
2537
2538
2539 /**
2540  * g_option_context_get_summary:
2541  * @context: a #GOptionContext
2542  *
2543  * Returns the summary. See g_option_context_set_summary().
2544  *
2545  * Returns: the summary
2546  *
2547  * Since: 2.12
2548  */
2549 const gchar *
2550 g_option_context_get_summary (GOptionContext *context)
2551 {
2552   g_return_val_if_fail (context != NULL, NULL);
2553
2554   return context->summary;
2555 }
2556
2557 /**
2558  * g_option_context_set_description:
2559  * @context: a #GOptionContext
2560  * @description: (allow-none): a string to be shown in `--help` output
2561  *   after the list of options, or %NULL
2562  *
2563  * Adds a string to be displayed in `--help` output after the list
2564  * of options. This text often includes a bug reporting address.
2565  *
2566  * Note that the summary is translated (see
2567  * g_option_context_set_translate_func()).
2568  *
2569  * Since: 2.12
2570  */
2571 void
2572 g_option_context_set_description (GOptionContext *context,
2573                                   const gchar    *description)
2574 {
2575   g_return_if_fail (context != NULL);
2576
2577   g_free (context->description);
2578   context->description = g_strdup (description);
2579 }
2580
2581
2582 /**
2583  * g_option_context_get_description:
2584  * @context: a #GOptionContext
2585  *
2586  * Returns the description. See g_option_context_set_description().
2587  *
2588  * Returns: the description
2589  *
2590  * Since: 2.12
2591  */
2592 const gchar *
2593 g_option_context_get_description (GOptionContext *context)
2594 {
2595   g_return_val_if_fail (context != NULL, NULL);
2596
2597   return context->description;
2598 }
2599
2600 /**
2601  * g_option_context_parse_strv:
2602  * @context: a #GOptionContext
2603  * @arguments: (inout) (array null-terminated=1): a pointer to the
2604  *    command line arguments (which must be in UTF-8 on Windows)
2605  * @error: a return location for errors
2606  *
2607  * Parses the command line arguments.
2608  *
2609  * This function is similar to g_option_context_parse() except that it
2610  * respects the normal memory rules when dealing with a strv instead of
2611  * assuming that the passed-in array is the argv of the main function.
2612  *
2613  * In particular, strings that are removed from the arguments list will
2614  * be freed using g_free().
2615  *
2616  * On Windows, the strings are expected to be in UTF-8.  This is in
2617  * contrast to g_option_context_parse() which expects them to be in the
2618  * system codepage, which is how they are passed as @argv to main().
2619  * See g_win32_get_command_line() for a solution.
2620  *
2621  * This function is useful if you are trying to use #GOptionContext with
2622  * #GApplication.
2623  *
2624  * Returns: %TRUE if the parsing was successful,
2625  *          %FALSE if an error occurred
2626  *
2627  * Since: 2.40
2628  **/
2629 gboolean
2630 g_option_context_parse_strv (GOptionContext   *context,
2631                              gchar          ***arguments,
2632                              GError          **error)
2633 {
2634   gboolean success;
2635   gint argc;
2636
2637   context->strv_mode = TRUE;
2638   argc = g_strv_length (*arguments);
2639   success = g_option_context_parse (context, &argc, arguments, error);
2640   context->strv_mode = FALSE;
2641
2642   return success;
2643 }