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