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