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