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