Improve the description of parameter_string in the docs. (#336085, Claudio
[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 #include "config.h"
23
24 #include "goption.h"
25 #include "glib.h"
26 #include "glibintl.h"
27
28 #include "galias.h"
29
30 #include <string.h>
31 #include <stdlib.h>
32 #include <errno.h>
33
34 #define TRANSLATE(group, str) (((group)->translate_func ? (* (group)->translate_func) ((str), (group)->translate_data) : (str)))
35
36 #define NO_ARG(entry) ((entry)->arg == G_OPTION_ARG_NONE ||       \
37                        ((entry)->arg == G_OPTION_ARG_CALLBACK &&  \
38                         ((entry)->flags & G_OPTION_FLAG_NO_ARG)))
39
40 #define OPTIONAL_ARG(entry) ((entry)->arg == G_OPTION_ARG_CALLBACK &&  \
41                        (entry)->flags & G_OPTION_FLAG_OPTIONAL_ARG)
42
43 typedef struct 
44 {
45   GOptionArg arg_type;
46   gpointer arg_data;  
47   union 
48   {
49     gboolean bool;
50     gint integer;
51     gchar *str;
52     gchar **array;
53   } prev;
54   union 
55   {
56     gchar *str;
57     struct 
58     {
59       gint len;
60       gchar **data;
61     } array;
62   } allocated;
63 } Change;
64
65 typedef struct
66 {
67   gchar **ptr;
68   gchar *value;
69 } PendingNull;
70
71 struct _GOptionContext
72 {
73   GList *groups;
74
75   gchar *parameter_string;
76
77   gboolean help_enabled;
78   gboolean ignore_unknown;
79   
80   GOptionGroup *main_group;
81
82   /* We keep a list of change so we can revert them */
83   GList *changes;
84   
85   /* We also keep track of all argv elements that should be NULLed or
86    * modified.
87    */
88   GList *pending_nulls;
89 };
90
91 struct _GOptionGroup
92 {
93   gchar *name;
94   gchar *description;
95   gchar *help_description;
96
97   GDestroyNotify  destroy_notify;
98   gpointer        user_data;
99
100   GTranslateFunc  translate_func;
101   GDestroyNotify  translate_notify;
102   gpointer        translate_data;
103
104   GOptionEntry *entries;
105   gint         n_entries;
106
107   GOptionParseFunc pre_parse_func;
108   GOptionParseFunc post_parse_func;
109   GOptionErrorFunc error_func;
110 };
111
112 static void free_changes_list (GOptionContext *context,
113                                gboolean        revert);
114 static void free_pending_nulls (GOptionContext *context,
115                                 gboolean        perform_nulls);
116
117 GQuark
118 g_option_error_quark (void)
119 {
120   static GQuark q = 0;
121   
122   if (q == 0)
123     q = g_quark_from_static_string ("g-option-context-error-quark");
124
125   return q;
126 }
127
128 /**
129  * g_option_context_new:
130  * @parameter_string: a string which is displayed in
131  *    the first line of <option>--help</option> output, after the
132  *    usage summary 
133  *    <literal><replaceable>programname</replaceable> [OPTION...]</literal>
134  *
135  * Creates a new option context. 
136  *
137  * The @parameter_text can serve multiple purposes. It can be used
138  * to add descriptions for "rest" arguments, which are not parsed by
139  * the #GOptionContext, typically something like "FILES" or
140  * "FILE1 FILE2...". (If you are using #G_OPTION_REMAINING for
141  * collecting "rest" arguments, GLib handles this automatically by
142  * using the @arg_description of the corresponding #GOptionEntry in
143  * the usage summary.)
144  *
145  * Another common usage is to give a summary of the program
146  * functionality. This can be a short summary on the same line,  
147  * like " - frob the strings", or a longer description in a paragraph  
148  * below the usage summary. In this case, @parameter_string should start  
149  * with two newlines, to separate the description from the usage summary:  
150  * "\n\nA program to frob strings, which will..."
151  *
152  * Returns: a newly created #GOptionContext, which must be
153  *    freed with g_option_context_free() after use.
154  *
155  * Since: 2.6
156  */
157 GOptionContext *
158 g_option_context_new (const gchar *parameter_string)
159
160 {
161   GOptionContext *context;
162
163   context = g_new0 (GOptionContext, 1);
164
165   context->parameter_string = g_strdup (parameter_string);
166   context->help_enabled = TRUE;
167   context->ignore_unknown = FALSE;
168
169   return context;
170 }
171
172 /**
173  * g_option_context_free:
174  * @context: a #GOptionContext 
175  *
176  * Frees context and all the groups which have been 
177  * added to it.
178  *
179  * Since: 2.6
180  */
181 void g_option_context_free (GOptionContext *context) 
182 {
183   g_return_if_fail (context != NULL);
184
185   g_list_foreach (context->groups, (GFunc)g_option_group_free, NULL);
186   g_list_free (context->groups);
187
188   if (context->main_group) 
189     g_option_group_free (context->main_group);
190
191   free_changes_list (context, FALSE);
192   free_pending_nulls (context, FALSE);
193   
194   g_free (context->parameter_string);
195   
196   g_free (context);
197 }
198
199
200 /**
201  * g_option_context_set_help_enabled:
202  * @context: a #GOptionContext
203  * @help_enabled: %TRUE to enable <option>--help</option>, %FALSE to disable it
204  *
205  * Enables or disables automatic generation of <option>--help</option> 
206  * output. By default, g_option_context_parse() recognizes
207  * <option>--help</option>, <option>-?</option>, <option>--help-all</option>
208  * and <option>--help-</option><replaceable>groupname</replaceable> and creates
209  * suitable output to stdout. 
210  *
211  * Since: 2.6
212  */
213 void g_option_context_set_help_enabled (GOptionContext *context,
214                                         gboolean        help_enabled)
215
216 {
217   g_return_if_fail (context != NULL);
218
219   context->help_enabled = help_enabled;
220 }
221
222 /**
223  * g_option_context_get_help_enabled:
224  * @context: a #GOptionContext
225  * 
226  * Returns whether automatic <option>--help</option> generation
227  * is turned on for @context. See g_option_context_set_help_enabled().
228  * 
229  * Returns: %TRUE if automatic help generation is turned on.
230  *
231  * Since: 2.6
232  */
233 gboolean 
234 g_option_context_get_help_enabled (GOptionContext *context) 
235 {
236   g_return_val_if_fail (context != NULL, FALSE);
237   
238   return context->help_enabled;
239 }
240
241 /**
242  * g_option_context_set_ignore_unknown_options:
243  * @context: a #GOptionContext
244  * @ignore_unknown: %TRUE to ignore unknown options, %FALSE to produce
245  *    an error when unknown options are met
246  * 
247  * Sets whether to ignore unknown options or not. If an argument is 
248  * ignored, it is left in the @argv array after parsing. By default, 
249  * g_option_context_parse() treats unknown options as error.
250  * 
251  * This setting does not affect non-option arguments (i.e. arguments 
252  * which don't start with a dash). But note that GOption cannot reliably
253  * determine whether a non-option belongs to a preceding unknown option.
254  *
255  * Since: 2.6
256  **/
257 void
258 g_option_context_set_ignore_unknown_options (GOptionContext *context,
259                                              gboolean        ignore_unknown)
260 {
261   g_return_if_fail (context != NULL);
262
263   context->ignore_unknown = ignore_unknown;
264 }
265
266 /**
267  * g_option_context_get_ignore_unknown_options:
268  * @context: a #GOptionContext
269  * 
270  * Returns whether unknown options are ignored or not. See
271  * g_option_context_set_ignore_unknown_options().
272  * 
273  * Returns: %TRUE if unknown options are ignored.
274  * 
275  * Since: 2.6
276  **/
277 gboolean
278 g_option_context_get_ignore_unknown_options (GOptionContext *context)
279 {
280   g_return_val_if_fail (context != NULL, FALSE);
281
282   return context->ignore_unknown;
283 }
284
285 /**
286  * g_option_context_add_group:
287  * @context: a #GOptionContext
288  * @group: the group to add
289  * 
290  * Adds a #GOptionGroup to the @context, so that parsing with @context
291  * will recognize the options in the group. Note that the group will
292  * be freed together with the context when g_option_context_free() is
293  * called, so you must not free the group yourself after adding it
294  * to a context.
295  *
296  * Since: 2.6
297  **/
298 void
299 g_option_context_add_group (GOptionContext *context,
300                             GOptionGroup   *group)
301 {
302   GList *list;
303
304   g_return_if_fail (context != NULL);
305   g_return_if_fail (group != NULL);
306   g_return_if_fail (group->name != NULL);
307   g_return_if_fail (group->description != NULL);
308   g_return_if_fail (group->help_description != NULL);
309
310   for (list = context->groups; list; list = list->next)
311     {
312       GOptionGroup *g = (GOptionGroup *)list->data;
313
314       if ((group->name == NULL && g->name == NULL) ||
315           (group->name && g->name && strcmp (group->name, g->name) == 0))
316         g_warning ("A group named \"%s\" is already part of this GOptionContext", 
317                    group->name);
318     }
319
320   context->groups = g_list_append (context->groups, group);
321 }
322
323 /**
324  * g_option_context_set_main_group:
325  * @context: a #GOptionContext
326  * @group: the group to set as main group
327  * 
328  * Sets a #GOptionGroup as main group of the @context. 
329  * This has the same effect as calling g_option_context_add_group(), 
330  * the only difference is that the options in the main group are 
331  * treated differently when generating <option>--help</option> output.
332  *
333  * Since: 2.6
334  **/
335 void
336 g_option_context_set_main_group (GOptionContext *context,
337                                  GOptionGroup   *group)
338 {
339   g_return_if_fail (context != NULL);
340   g_return_if_fail (group != NULL);
341
342   if (context->main_group)
343     {
344       g_warning ("This GOptionContext already has a main group");
345
346       return;
347     }
348   
349   context->main_group = group;
350 }
351
352 /**
353  * g_option_context_get_main_group:
354  * @context: a #GOptionContext
355  * 
356  * Returns a pointer to the main group of @context.
357  * 
358  * Return value: the main group of @context, or %NULL if @context doesn't
359  *  have a main group. Note that group belongs to @context and should
360  *  not be modified or freed.
361  *
362  * Since: 2.6
363  **/
364 GOptionGroup *
365 g_option_context_get_main_group (GOptionContext *context)
366 {
367   g_return_val_if_fail (context != NULL, NULL);
368
369   return context->main_group;
370 }
371
372 /**
373  * g_option_context_add_main_entries:
374  * @context: a #GOptionContext
375  * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
376  * @translation_domain: a translation domain to use for translating
377  *    the <option>--help</option> output for the options in @entries
378  *    with gettext(), or %NULL
379  * 
380  * A convenience function which creates a main group if it doesn't 
381  * exist, adds the @entries to it and sets the translation domain.
382  * 
383  * Since: 2.6
384  **/
385 void
386 g_option_context_add_main_entries (GOptionContext      *context,
387                                    const GOptionEntry  *entries,
388                                    const gchar         *translation_domain)
389 {
390   g_return_if_fail (entries != NULL);
391
392   if (!context->main_group)
393     context->main_group = g_option_group_new (NULL, NULL, NULL, NULL, NULL);
394   
395   g_option_group_add_entries (context->main_group, entries);
396   g_option_group_set_translation_domain (context->main_group, translation_domain);
397 }
398
399 static gint
400 calculate_max_length (GOptionGroup *group)
401 {
402   GOptionEntry *entry;
403   gint i, len, max_length;
404
405   max_length = 0;
406
407   for (i = 0; i < group->n_entries; i++)
408     {
409       entry = &group->entries[i];
410
411       if (entry->flags & G_OPTION_FLAG_HIDDEN)
412         continue;
413
414       len = g_utf8_strlen (entry->long_name, -1);
415       
416       if (entry->short_name)
417         len += 4;
418       
419       if (!NO_ARG (entry) && entry->arg_description)
420         len += 1 + g_utf8_strlen (TRANSLATE (group, entry->arg_description), -1);
421       
422       max_length = MAX (max_length, len);
423     }
424
425   return max_length;
426 }
427
428 static void
429 print_entry (GOptionGroup       *group,
430              gint                max_length,
431              const GOptionEntry *entry)
432 {
433   GString *str;
434
435   if (entry->flags & G_OPTION_FLAG_HIDDEN)
436     return;
437
438   if (entry->long_name[0] == 0)
439     return;
440
441   str = g_string_new (NULL);
442   
443   if (entry->short_name)
444     g_string_append_printf (str, "  -%c, --%s", entry->short_name, entry->long_name);
445   else
446     g_string_append_printf (str, "  --%s", entry->long_name);
447   
448   if (entry->arg_description)
449     g_string_append_printf (str, "=%s", TRANSLATE (group, entry->arg_description));
450   
451   g_print ("%-*s %s\n", max_length + 4, str->str,
452            entry->description ? TRANSLATE (group, entry->description) : "");
453   g_string_free (str, TRUE);  
454 }
455
456 static void
457 print_help (GOptionContext *context,
458             gboolean        main_help,
459             GOptionGroup   *group) 
460 {
461   GList *list;
462   gint max_length, len;
463   gint i;
464   GOptionEntry *entry;
465   GHashTable *shadow_map;
466   gboolean seen[256];
467   const gchar *rest_description;
468   
469   rest_description = NULL;
470   if (context->main_group)
471     {
472       for (i = 0; i < context->main_group->n_entries; i++)
473         {
474           entry = &context->main_group->entries[i];
475           if (entry->long_name[0] == 0)
476             {
477               rest_description = entry->arg_description;
478               break;
479             }
480         }
481     }
482   
483   g_print ("%s\n  %s %s%s%s%s%s\n\n", 
484            _("Usage:"), g_get_prgname(), _("[OPTION...]"),
485            rest_description ? " " : "",
486            rest_description ? rest_description : "",
487            context->parameter_string ? " " : "",
488            context->parameter_string ? context->parameter_string : "");
489
490   memset (seen, 0, sizeof (gboolean) * 256);
491   shadow_map = g_hash_table_new (g_str_hash, g_str_equal);
492
493   if (context->main_group)
494     {
495       for (i = 0; i < context->main_group->n_entries; i++)
496         {
497           entry = &context->main_group->entries[i];
498           g_hash_table_insert (shadow_map, 
499                                (gpointer)entry->long_name, 
500                                entry);
501           
502           if (seen[(guchar)entry->short_name])
503             entry->short_name = 0;
504           else
505             seen[(guchar)entry->short_name] = TRUE;
506         }
507     }
508
509   list = context->groups;
510   while (list != NULL)
511     {
512       GOptionGroup *group = list->data;
513       for (i = 0; i < group->n_entries; i++)
514         {
515           entry = &group->entries[i];
516           if (g_hash_table_lookup (shadow_map, entry->long_name) && 
517               !(entry->flags && G_OPTION_FLAG_NOALIAS))
518             entry->long_name = g_strdup_printf ("%s-%s", group->name, entry->long_name);
519           else  
520             g_hash_table_insert (shadow_map, (gpointer)entry->long_name, entry);
521
522           if (seen[(guchar)entry->short_name] && 
523               !(entry->flags && G_OPTION_FLAG_NOALIAS))
524             entry->short_name = 0;
525           else
526             seen[(guchar)entry->short_name] = TRUE;
527         }
528       list = list->next;
529     }
530
531   g_hash_table_destroy (shadow_map);
532
533   list = context->groups;
534
535   max_length = g_utf8_strlen ("-?, --help", -1);
536
537   if (list)
538     {
539       len = g_utf8_strlen ("--help-all", -1);
540       max_length = MAX (max_length, len);
541     }
542
543   if (context->main_group)
544     {
545       len = calculate_max_length (context->main_group);
546       max_length = MAX (max_length, len);
547     }
548
549   while (list != NULL)
550     {
551       GOptionGroup *group = list->data;
552       
553       /* First, we check the --help-<groupname> options */
554       len = g_utf8_strlen ("--help-", -1) + g_utf8_strlen (group->name, -1);
555       max_length = MAX (max_length, len);
556
557       /* Then we go through the entries */
558       len = calculate_max_length (group);
559       max_length = MAX (max_length, len);
560       
561       list = list->next;
562     }
563
564   /* Add a bit of padding */
565   max_length += 4;
566
567   if (!group)
568     {
569       list = context->groups;
570       
571       g_print ("%s\n  -%c, --%-*s %s\n", 
572                _("Help Options:"), '?', max_length - 4, "help", 
573                _("Show help options"));
574       
575       /* We only want --help-all when there are groups */
576       if (list)
577         g_print ("  --%-*s %s\n", max_length, "help-all", 
578                  _("Show all help options"));
579       
580       while (list)
581         {
582           GOptionGroup *group = list->data;
583           
584           g_print ("  --help-%-*s %s\n", max_length - 5, group->name, 
585                    TRANSLATE (group, group->help_description));
586           
587           list = list->next;
588         }
589
590       g_print ("\n");
591     }
592
593   if (group)
594     {
595       /* Print a certain group */
596       
597       g_print ("%s\n", TRANSLATE (group, group->description));
598       for (i = 0; i < group->n_entries; i++)
599         print_entry (group, max_length, &group->entries[i]);
600       g_print ("\n");
601     }
602   else if (!main_help)
603     {
604       /* Print all groups */
605
606       list = context->groups;
607
608       while (list)
609         {
610           GOptionGroup *group = list->data;
611
612           g_print ("%s\n", group->description);
613
614           for (i = 0; i < group->n_entries; i++)
615             if (!(group->entries[i].flags & G_OPTION_FLAG_IN_MAIN))
616               print_entry (group, max_length, &group->entries[i]);
617           
618           g_print ("\n");
619           list = list->next;
620         }
621     }
622   
623   /* Print application options if --help or --help-all has been specified */
624   if (main_help || !group)
625     {
626       list = context->groups;
627
628       g_print ("%s\n", _("Application Options:"));
629
630       if (context->main_group)
631         for (i = 0; i < context->main_group->n_entries; i++) 
632           print_entry (context->main_group, max_length, 
633                        &context->main_group->entries[i]);
634
635       while (list != NULL)
636         {
637           GOptionGroup *group = list->data;
638
639           /* Print main entries from other groups */
640           for (i = 0; i < group->n_entries; i++)
641             if (group->entries[i].flags & G_OPTION_FLAG_IN_MAIN)
642               print_entry (group, max_length, &group->entries[i]);
643           
644           list = list->next;
645         }
646
647       g_print ("\n");
648     }
649   
650   exit (0);
651 }
652
653 static gboolean
654 parse_int (const gchar *arg_name,
655            const gchar *arg,
656            gint        *result,
657            GError     **error)
658 {
659   gchar *end;
660   glong tmp;
661
662   errno = 0;
663   tmp = strtol (arg, &end, 0);
664   
665   if (*arg == '\0' || *end != '\0')
666     {
667       g_set_error (error,
668                    G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
669                    _("Cannot parse integer value '%s' for %s"),
670                    arg, arg_name);
671       return FALSE;
672     }
673
674   *result = tmp;
675   if (*result != tmp || errno == ERANGE)
676     {
677       g_set_error (error,
678                    G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
679                    _("Integer value '%s' for %s out of range"),
680                    arg, arg_name);
681       return FALSE;
682     }
683
684   return TRUE;
685 }
686
687 static Change *
688 get_change (GOptionContext *context,
689             GOptionArg      arg_type,
690             gpointer        arg_data)
691 {
692   GList *list;
693   Change *change = NULL;
694   
695   for (list = context->changes; list != NULL; list = list->next)
696     {
697       change = list->data;
698
699       if (change->arg_data == arg_data)
700         goto found;
701     }
702
703   change = g_new0 (Change, 1);
704   change->arg_type = arg_type;
705   change->arg_data = arg_data;
706   
707   context->changes = g_list_prepend (context->changes, change);
708   
709  found:
710
711   return change;
712 }
713
714 static void
715 add_pending_null (GOptionContext *context,
716                   gchar         **ptr,
717                   gchar          *value)
718 {
719   PendingNull *n;
720
721   n = g_new0 (PendingNull, 1);
722   n->ptr = ptr;
723   n->value = value;
724
725   context->pending_nulls = g_list_prepend (context->pending_nulls, n);
726 }
727                   
728 static gboolean
729 parse_arg (GOptionContext *context,
730            GOptionGroup   *group,
731            GOptionEntry   *entry,
732            const gchar    *value,
733            const gchar    *option_name,
734            GError        **error)
735      
736 {
737   Change *change;
738   
739   switch (entry->arg)
740     {
741     case G_OPTION_ARG_NONE:
742       {
743         change = get_change (context, G_OPTION_ARG_NONE,
744                              entry->arg_data);
745
746         *(gboolean *)entry->arg_data = !(entry->flags & G_OPTION_FLAG_REVERSE);
747         break;
748       }      
749     case G_OPTION_ARG_STRING:
750       {
751         gchar *data;
752         
753         data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
754
755         if (!data)
756           return FALSE;
757
758         change = get_change (context, G_OPTION_ARG_STRING,
759                              entry->arg_data);
760         g_free (change->allocated.str);
761         
762         change->prev.str = *(gchar **)entry->arg_data;
763         change->allocated.str = data;
764         
765         *(gchar **)entry->arg_data = data;
766         break;
767       }
768     case G_OPTION_ARG_STRING_ARRAY:
769       {
770         gchar *data;
771
772         data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
773
774         if (!data)
775           return FALSE;
776
777         change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
778                              entry->arg_data);
779
780         if (change->allocated.array.len == 0)
781           {
782             change->prev.array = *(gchar ***)entry->arg_data;
783             change->allocated.array.data = g_new (gchar *, 2);
784           }
785         else
786           change->allocated.array.data =
787             g_renew (gchar *, change->allocated.array.data,
788                      change->allocated.array.len + 2);
789
790         change->allocated.array.data[change->allocated.array.len] = data;
791         change->allocated.array.data[change->allocated.array.len + 1] = NULL;
792
793         change->allocated.array.len ++;
794
795         *(gchar ***)entry->arg_data = change->allocated.array.data;
796
797         break;
798       }
799       
800     case G_OPTION_ARG_FILENAME:
801       {
802         gchar *data;
803
804 #ifdef G_OS_WIN32
805         data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
806         
807         if (!data)
808           return FALSE;
809 #else
810         data = g_strdup (value);
811 #endif
812         change = get_change (context, G_OPTION_ARG_FILENAME,
813                              entry->arg_data);
814         g_free (change->allocated.str);
815         
816         change->prev.str = *(gchar **)entry->arg_data;
817         change->allocated.str = data;
818
819         *(gchar **)entry->arg_data = data;
820         break;
821       }
822
823     case G_OPTION_ARG_FILENAME_ARRAY:
824       {
825         gchar *data;
826         
827 #ifdef G_OS_WIN32
828         data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
829         
830         if (!data)
831           return FALSE;
832 #else
833         data = g_strdup (value);
834 #endif
835         change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
836                              entry->arg_data);
837
838         if (change->allocated.array.len == 0)
839           {
840             change->prev.array = *(gchar ***)entry->arg_data;
841             change->allocated.array.data = g_new (gchar *, 2);
842           }
843         else
844           change->allocated.array.data =
845             g_renew (gchar *, change->allocated.array.data,
846                      change->allocated.array.len + 2);
847
848         change->allocated.array.data[change->allocated.array.len] = data;
849         change->allocated.array.data[change->allocated.array.len + 1] = NULL;
850
851         change->allocated.array.len ++;
852
853         *(gchar ***)entry->arg_data = change->allocated.array.data;
854
855         break;
856       }
857       
858     case G_OPTION_ARG_INT:
859       {
860         gint data;
861
862         if (!parse_int (option_name, value,
863                         &data,
864                         error))
865           return FALSE;
866
867         change = get_change (context, G_OPTION_ARG_INT,
868                              entry->arg_data);
869         change->prev.integer = *(gint *)entry->arg_data;
870         *(gint *)entry->arg_data = data;
871         break;
872       }
873     case G_OPTION_ARG_CALLBACK:
874       {
875         gchar *data;
876         gboolean retval;
877
878         if (!value && entry->flags & G_OPTION_FLAG_OPTIONAL_ARG)
879           data = NULL;
880         else if (entry->flags & G_OPTION_FLAG_NO_ARG)
881           data = NULL;
882         else if (entry->flags & G_OPTION_FLAG_FILENAME)
883           {
884 #ifdef G_OS_WIN32
885             data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
886 #else
887             data = g_strdup (value);
888 #endif
889           }
890         else
891           data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
892
893         if (!(entry->flags & (G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG)) && 
894             !data)
895           return FALSE;
896
897         retval = (* (GOptionArgFunc) entry->arg_data) (option_name, data, group->user_data, error);
898         
899         g_free (data);
900         
901         return retval;
902         
903         break;
904       }
905     default:
906       g_assert_not_reached ();
907     }
908
909   return TRUE;
910 }
911
912 static gboolean
913 parse_short_option (GOptionContext *context,
914                     GOptionGroup   *group,
915                     gint            index,
916                     gint           *new_index,
917                     gchar           arg,
918                     gint           *argc,
919                     gchar        ***argv,
920                     GError        **error,
921                     gboolean       *parsed)
922 {
923   gint j;
924     
925   for (j = 0; j < group->n_entries; j++)
926     {
927       if (arg == group->entries[j].short_name)
928         {
929           gchar *option_name;
930           gchar *value = NULL;
931           
932           option_name = g_strdup_printf ("-%c", group->entries[j].short_name);
933
934           if (NO_ARG (&group->entries[j]))
935             value = NULL;
936           else
937             {
938               if (*new_index > index)
939                 {
940                   g_set_error (error, 
941                                G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
942                                _("Error parsing option %s"), option_name);
943                   g_free (option_name);
944                   return FALSE;
945                 }
946
947               if (index < *argc - 1)
948                 {
949                   if (!OPTIONAL_ARG (&group->entries[j]))       
950                     {    
951                       value = (*argv)[index + 1];
952                       add_pending_null (context, &((*argv)[index + 1]), NULL);
953                       *new_index = index+1;
954                     }
955                   else
956                     {
957                       if ((*argv)[index + 1][0] == '-') 
958                         value = NULL;
959                       else
960                         {
961                           value = (*argv)[index + 1];
962                           add_pending_null (context, &((*argv)[index + 1]), NULL);
963                           *new_index = index + 1;
964                         }
965                     }
966                 }
967               else if (index >= *argc - 1 && OPTIONAL_ARG (&group->entries[j]))
968                 value = NULL;
969               else
970                 {
971                   g_set_error (error, 
972                                G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
973                                _("Missing argument for %s"), option_name);
974                   g_free (option_name);
975                   return FALSE;
976                 }
977             }
978
979           if (!parse_arg (context, group, &group->entries[j], 
980                           value, option_name, error))
981             {
982               g_free (option_name);
983               return FALSE;
984             }
985           
986           g_free (option_name);
987           *parsed = TRUE;
988         }
989     }
990
991   return TRUE;
992 }
993
994 static gboolean
995 parse_long_option (GOptionContext *context,
996                    GOptionGroup   *group,
997                    gint           *index,
998                    gchar          *arg,
999                    gboolean        aliased,
1000                    gint           *argc,
1001                    gchar        ***argv,
1002                    GError        **error,
1003                    gboolean       *parsed)
1004 {
1005   gint j;
1006
1007   for (j = 0; j < group->n_entries; j++)
1008     {
1009       if (*index >= *argc)
1010         return TRUE;
1011
1012       if (aliased && (group->entries[j].flags & G_OPTION_FLAG_NOALIAS))
1013         continue;
1014
1015       if (NO_ARG (&group->entries[j]) &&
1016           strcmp (arg, group->entries[j].long_name) == 0)
1017         {
1018           gchar *option_name;
1019
1020           option_name = g_strconcat ("--", group->entries[j].long_name, NULL);
1021           parse_arg (context, group, &group->entries[j],
1022                      NULL, option_name, error);
1023           g_free(option_name);
1024           
1025           add_pending_null (context, &((*argv)[*index]), NULL);
1026           *parsed = TRUE;
1027         }
1028       else
1029         {
1030           gint len = strlen (group->entries[j].long_name);
1031           
1032           if (strncmp (arg, group->entries[j].long_name, len) == 0 &&
1033               (arg[len] == '=' || arg[len] == 0))
1034             {
1035               gchar *value = NULL;
1036               gchar *option_name;
1037
1038               add_pending_null (context, &((*argv)[*index]), NULL);
1039               option_name = g_strconcat ("--", group->entries[j].long_name, NULL);
1040
1041               if (arg[len] == '=')
1042                 value = arg + len + 1;
1043               else if (*index < *argc - 1) 
1044                 {
1045                   if (!(group->entries[j].flags & G_OPTION_FLAG_OPTIONAL_ARG))  
1046                     {    
1047                       value = (*argv)[*index + 1];
1048                       add_pending_null (context, &((*argv)[*index + 1]), NULL);
1049                       (*index)++;
1050                     }
1051                   else
1052                     {
1053                       if ((*argv)[*index + 1][0] == '-') 
1054                         {
1055                           gboolean retval;
1056                           retval = parse_arg (context, group, &group->entries[j],
1057                                               NULL, option_name, error);
1058                           *parsed = TRUE;
1059                           g_free (option_name);
1060                           return retval;
1061                         }
1062                       else
1063                         {
1064                           value = (*argv)[*index + 1];
1065                           add_pending_null (context, &((*argv)[*index + 1]), NULL);
1066                           (*index)++;
1067                         }
1068                     }
1069                 }
1070               else if (*index >= *argc - 1 &&
1071                        group->entries[j].flags & G_OPTION_FLAG_OPTIONAL_ARG)
1072                 {
1073                     gboolean retval;
1074                     retval = parse_arg (context, group, &group->entries[j],
1075                                         NULL, option_name, error);
1076                     *parsed = TRUE;
1077                     g_free (option_name);
1078                     return retval;
1079                 }
1080               else
1081                 {
1082                   g_set_error (error, 
1083                                G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1084                                _("Missing argument for %s"), option_name);
1085                   g_free (option_name);
1086                   return FALSE;
1087                 }
1088
1089               if (!parse_arg (context, group, &group->entries[j], 
1090                               value, option_name, error))
1091                 {
1092                   g_free (option_name);
1093                   return FALSE;
1094                 }
1095
1096               g_free (option_name);
1097               *parsed = TRUE;
1098             } 
1099         }
1100     }
1101   
1102   return TRUE;
1103 }
1104
1105 static gboolean
1106 parse_remaining_arg (GOptionContext *context,
1107                      GOptionGroup   *group,
1108                      gint           *index,
1109                      gint           *argc,
1110                      gchar        ***argv,
1111                      GError        **error,
1112                      gboolean       *parsed)
1113 {
1114   gint j;
1115
1116   for (j = 0; j < group->n_entries; j++)
1117     {
1118       if (*index >= *argc)
1119         return TRUE;
1120
1121       if (group->entries[j].long_name[0])
1122         continue;
1123
1124       g_return_val_if_fail (group->entries[j].arg == G_OPTION_ARG_STRING_ARRAY ||
1125                             group->entries[j].arg == G_OPTION_ARG_FILENAME_ARRAY, FALSE);
1126       
1127       add_pending_null (context, &((*argv)[*index]), NULL);
1128       
1129       if (!parse_arg (context, group, &group->entries[j], (*argv)[*index], "", error))
1130         return FALSE;
1131       
1132       *parsed = TRUE;
1133       return TRUE;
1134     }
1135
1136   return TRUE;
1137 }
1138
1139 static void
1140 free_changes_list (GOptionContext *context,
1141                    gboolean        revert)
1142 {
1143   GList *list;
1144
1145   for (list = context->changes; list != NULL; list = list->next)
1146     {
1147       Change *change = list->data;
1148
1149       if (revert)
1150         {
1151           switch (change->arg_type)
1152             {
1153             case G_OPTION_ARG_NONE:
1154               *(gboolean *)change->arg_data = change->prev.bool;
1155               break;
1156             case G_OPTION_ARG_INT:
1157               *(gint *)change->arg_data = change->prev.integer;
1158               break;
1159             case G_OPTION_ARG_STRING:
1160             case G_OPTION_ARG_FILENAME:
1161               g_free (change->allocated.str);
1162               *(gchar **)change->arg_data = change->prev.str;
1163               break;
1164             case G_OPTION_ARG_STRING_ARRAY:
1165             case G_OPTION_ARG_FILENAME_ARRAY:
1166               g_strfreev (change->allocated.array.data);
1167               *(gchar ***)change->arg_data = change->prev.array;
1168               break;
1169             default:
1170               g_assert_not_reached ();
1171             }
1172         }
1173       
1174       g_free (change);
1175     }
1176
1177   g_list_free (context->changes);
1178   context->changes = NULL;
1179 }
1180
1181 static void
1182 free_pending_nulls (GOptionContext *context,
1183                     gboolean        perform_nulls)
1184 {
1185   GList *list;
1186
1187   for (list = context->pending_nulls; list != NULL; list = list->next)
1188     {
1189       PendingNull *n = list->data;
1190
1191       if (perform_nulls)
1192         {
1193           if (n->value)
1194             {
1195               /* Copy back the short options */
1196               *(n->ptr)[0] = '-';             
1197               strcpy (*n->ptr + 1, n->value);
1198             }
1199           else
1200             *n->ptr = NULL;
1201         }
1202       
1203       g_free (n->value);
1204       g_free (n);
1205     }
1206
1207   g_list_free (context->pending_nulls);
1208   context->pending_nulls = NULL;
1209 }
1210
1211 /**
1212  * g_option_context_parse:
1213  * @context: a #GOptionContext
1214  * @argc: a pointer to the number of command line arguments.
1215  * @argv: a pointer to the array of command line arguments.
1216  * @error: a return location for errors 
1217  * 
1218  * Parses the command line arguments, recognizing options
1219  * which have been added to @context. A side-effect of 
1220  * calling this function is that g_set_prgname() will be
1221  * called.
1222  *
1223  * If the parsing is successful, any parsed arguments are
1224  * removed from the array and @argc and @argv are updated 
1225  * accordingly. A '--' option is stripped from @argv
1226  * unless there are unparsed options before and after it, 
1227  * or some of the options after it start with '-'. In case 
1228  * of an error, @argc and @argv are left unmodified. 
1229  *
1230  * If automatic <option>--help</option> support is enabled
1231  * (see g_option_context_set_help_enabled()), and the 
1232  * @argv array contains one of the recognized help options,
1233  * this function will produce help output to stdout and
1234  * call <literal>exit (0)</literal>.
1235  * 
1236  * Return value: %TRUE if the parsing was successful, 
1237  *               %FALSE if an error occurred
1238  *
1239  * Since: 2.6
1240  **/
1241 gboolean
1242 g_option_context_parse (GOptionContext   *context,
1243                         gint             *argc,
1244                         gchar          ***argv,
1245                         GError          **error)
1246 {
1247   gint i, j, k;
1248   GList *list;
1249
1250   /* Set program name */
1251   if (!g_get_prgname())
1252     {
1253       if (argc && argv && *argc)
1254         {
1255           gchar *prgname;
1256           
1257           prgname = g_path_get_basename ((*argv)[0]);
1258           g_set_prgname (prgname);
1259           g_free (prgname);
1260         }
1261       else
1262         g_set_prgname ("<unknown>");
1263     }
1264
1265   /* Call pre-parse hooks */
1266   list = context->groups;
1267   while (list)
1268     {
1269       GOptionGroup *group = list->data;
1270       
1271       if (group->pre_parse_func)
1272         {
1273           if (!(* group->pre_parse_func) (context, group,
1274                                           group->user_data, error))
1275             goto fail;
1276         }
1277       
1278       list = list->next;
1279     }
1280
1281   if (context->main_group && context->main_group->pre_parse_func)
1282     {
1283       if (!(* context->main_group->pre_parse_func) (context, context->main_group,
1284                                                     context->main_group->user_data, error))
1285         goto fail;
1286     }
1287
1288   if (argc && argv)
1289     {
1290       gboolean stop_parsing = FALSE;
1291       gboolean has_unknown = FALSE;
1292       gint separator_pos = 0;
1293
1294       for (i = 1; i < *argc; i++)
1295         {
1296           gchar *arg, *dash;
1297           gboolean parsed = FALSE;
1298
1299           if ((*argv)[i][0] == '-' && (*argv)[i][1] != '\0' && !stop_parsing)
1300             {
1301               if ((*argv)[i][1] == '-')
1302                 {
1303                   /* -- option */
1304
1305                   arg = (*argv)[i] + 2;
1306
1307                   /* '--' terminates list of arguments */
1308                   if (*arg == 0)
1309                     {
1310                       separator_pos = i;
1311                       stop_parsing = TRUE;
1312                       continue;
1313                     }
1314
1315                   /* Handle help options */
1316                   if (context->help_enabled)
1317                     {
1318                       if (strcmp (arg, "help") == 0)
1319                         print_help (context, TRUE, NULL);
1320                       else if (strcmp (arg, "help-all") == 0)
1321                         print_help (context, FALSE, NULL);                    
1322                       else if (strncmp (arg, "help-", 5) == 0)
1323                         {
1324                           GList *list;
1325                           
1326                           list = context->groups;
1327                           
1328                           while (list)
1329                             {
1330                               GOptionGroup *group = list->data;
1331                               
1332                               if (strcmp (arg + 5, group->name) == 0)
1333                                 print_help (context, FALSE, group);                                           
1334                               
1335                               list = list->next;
1336                             }
1337                         }
1338                     }
1339
1340                   if (context->main_group &&
1341                       !parse_long_option (context, context->main_group, &i, arg,
1342                                           FALSE, argc, argv, error, &parsed))
1343                     goto fail;
1344
1345                   if (parsed)
1346                     continue;
1347                   
1348                   /* Try the groups */
1349                   list = context->groups;
1350                   while (list)
1351                     {
1352                       GOptionGroup *group = list->data;
1353                       
1354                       if (!parse_long_option (context, group, &i, arg, 
1355                                               FALSE, argc, argv, error, &parsed))
1356                         goto fail;
1357                       
1358                       if (parsed)
1359                         break;
1360                       
1361                       list = list->next;
1362                     }
1363                   
1364                   if (parsed)
1365                     continue;
1366
1367                   /* Now look for --<group>-<option> */
1368                   dash = strchr (arg, '-');
1369                   if (dash)
1370                     {
1371                       /* Try the groups */
1372                       list = context->groups;
1373                       while (list)
1374                         {
1375                           GOptionGroup *group = list->data;
1376                           
1377                           if (strncmp (group->name, arg, dash - arg) == 0)
1378                             {
1379                               if (!parse_long_option (context, group, &i, dash + 1,
1380                                                       TRUE, argc, argv, error, &parsed))
1381                                 goto fail;
1382                               
1383                               if (parsed)
1384                                 break;
1385                             }
1386                           
1387                           list = list->next;
1388                         }
1389                     }
1390                   
1391                   if (context->ignore_unknown)
1392                     continue;
1393                 }
1394               else
1395                 {
1396                   /* short option */
1397
1398                   gint new_i, j;
1399                   gboolean *nulled_out = NULL;
1400                   
1401                   arg = (*argv)[i] + 1;
1402
1403                   new_i = i;
1404
1405                   if (context->ignore_unknown)
1406                     nulled_out = g_new0 (gboolean, strlen (arg));
1407                   
1408                   for (j = 0; j < strlen (arg); j++)
1409                     {
1410                       if (context->help_enabled && arg[j] == '?')
1411                         print_help (context, TRUE, NULL);
1412                       
1413                       parsed = FALSE;
1414                       
1415                       if (context->main_group &&
1416                           !parse_short_option (context, context->main_group,
1417                                                i, &new_i, arg[j],
1418                                                argc, argv, error, &parsed))
1419                         {
1420
1421                           g_free (nulled_out);
1422                           goto fail;
1423                         }
1424
1425                       if (!parsed)
1426                         {
1427                           /* Try the groups */
1428                           list = context->groups;
1429                           while (list)
1430                             {
1431                               GOptionGroup *group = list->data;
1432                               
1433                               if (!parse_short_option (context, group, i, &new_i, arg[j],
1434                                                        argc, argv, error, &parsed))
1435                                 goto fail;
1436                               
1437                               if (parsed)
1438                                 break;
1439                           
1440                               list = list->next;
1441                             }
1442                         }
1443
1444                       if (context->ignore_unknown)
1445                         {
1446                           if (parsed)
1447                             nulled_out[j] = TRUE;
1448                           else
1449                             continue;
1450                         }
1451
1452                       if (!parsed)
1453                         break;
1454                     }
1455
1456                   if (context->ignore_unknown)
1457                     {
1458                       gchar *new_arg = NULL; 
1459                       gint arg_index = 0;
1460                       
1461                       for (j = 0; j < strlen (arg); j++)
1462                         {
1463                           if (!nulled_out[j])
1464                             {
1465                               if (!new_arg)
1466                                 new_arg = g_malloc (strlen (arg) + 1);
1467                               new_arg[arg_index++] = arg[j];
1468                             }
1469                         }
1470                       if (new_arg)
1471                         new_arg[arg_index] = '\0';
1472                       
1473                       add_pending_null (context, &((*argv)[i]), new_arg);
1474                     }
1475                   else if (parsed)
1476                     {
1477                       add_pending_null (context, &((*argv)[i]), NULL);
1478                       i = new_i;
1479                     }
1480                 }
1481               
1482               if (!parsed)
1483                 has_unknown = TRUE;
1484
1485               if (!parsed && !context->ignore_unknown)
1486                 {
1487                   g_set_error (error,
1488                                G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION,
1489                                    _("Unknown option %s"), (*argv)[i]);
1490                   goto fail;
1491                 }
1492             }
1493           else
1494             {
1495               /* Collect remaining args */
1496               if (context->main_group &&
1497                   !parse_remaining_arg (context, context->main_group, &i,
1498                                         argc, argv, error, &parsed))
1499                 goto fail;
1500               
1501               if (!parsed && (has_unknown || (*argv)[i][0] == '-'))
1502                 separator_pos = 0;
1503             }
1504         }
1505
1506       if (separator_pos > 0)
1507         add_pending_null (context, &((*argv)[separator_pos]), NULL);
1508         
1509     }
1510
1511   /* Call post-parse hooks */
1512   list = context->groups;
1513   while (list)
1514     {
1515       GOptionGroup *group = list->data;
1516       
1517       if (group->post_parse_func)
1518         {
1519           if (!(* group->post_parse_func) (context, group,
1520                                            group->user_data, error))
1521             goto fail;
1522         }
1523       
1524       list = list->next;
1525     }
1526   
1527   if (context->main_group && context->main_group->post_parse_func)
1528     {
1529       if (!(* context->main_group->post_parse_func) (context, context->main_group,
1530                                                      context->main_group->user_data, error))
1531         goto fail;
1532     }
1533   
1534   if (argc && argv)
1535     {
1536       free_pending_nulls (context, TRUE);
1537       
1538       for (i = 1; i < *argc; i++)
1539         {
1540           for (k = i; k < *argc; k++)
1541             if ((*argv)[k] != NULL)
1542               break;
1543           
1544           if (k > i)
1545             {
1546               k -= i;
1547               for (j = i + k; j < *argc; j++)
1548                 {
1549                   (*argv)[j-k] = (*argv)[j];
1550                   (*argv)[j] = NULL;
1551                 }
1552               *argc -= k;
1553             }
1554         }      
1555     }
1556
1557   return TRUE;
1558
1559  fail:
1560   
1561   /* Call error hooks */
1562   list = context->groups;
1563   while (list)
1564     {
1565       GOptionGroup *group = list->data;
1566       
1567       if (group->error_func)
1568         (* group->error_func) (context, group,
1569                                group->user_data, error);
1570       
1571       list = list->next;
1572     }
1573
1574   if (context->main_group && context->main_group->error_func)
1575     (* context->main_group->error_func) (context, context->main_group,
1576                                          context->main_group->user_data, error);
1577   
1578   free_changes_list (context, TRUE);
1579   free_pending_nulls (context, FALSE);
1580
1581   return FALSE;
1582 }
1583                                    
1584 /**
1585  * g_option_group_new:
1586  * @name: the name for the option group, this is used to provide
1587  *   help for the options in this group with <option>--help-</option>@name
1588  * @description: a description for this group to be shown in 
1589  *   <option>--help</option>. This string is translated using the translation
1590  *   domain or translation function of the group
1591  * @help_description: a description for the <option>--help-</option>@name option.
1592  *   This string is translated using the translation domain or translation function
1593  *   of the group
1594  * @user_data: user data that will be passed to the pre- and post-parse hooks,
1595  *   the error hook and to callbacks of %G_OPTION_ARG_CALLBACK options, or %NULL
1596  * @destroy: a function that will be called to free @user_data, or %NULL
1597  * 
1598  * Creates a new #GOptionGroup.
1599  * 
1600  * Return value: a newly created option group. It should be added 
1601  *   to a #GOptionContext or freed with g_option_group_free().
1602  *
1603  * Since: 2.6
1604  **/
1605 GOptionGroup *
1606 g_option_group_new (const gchar    *name,
1607                     const gchar    *description,
1608                     const gchar    *help_description,
1609                     gpointer        user_data,
1610                     GDestroyNotify  destroy)
1611
1612 {
1613   GOptionGroup *group;
1614
1615   group = g_new0 (GOptionGroup, 1);
1616   group->name = g_strdup (name);
1617   group->description = g_strdup (description);
1618   group->help_description = g_strdup (help_description);
1619   group->user_data = user_data;
1620   group->destroy_notify = destroy;
1621   
1622   return group;
1623 }
1624
1625
1626 /**
1627  * g_option_group_free:
1628  * @group: a #GOptionGroup
1629  * 
1630  * Frees a #GOptionGroup. Note that you must <emphasis>not</emphasis>
1631  * free groups which have been added to a #GOptionContext.
1632  *
1633  * Since: 2.6
1634  **/
1635 void
1636 g_option_group_free (GOptionGroup *group)
1637 {
1638   g_return_if_fail (group != NULL);
1639
1640   g_free (group->name);
1641   g_free (group->description);
1642   g_free (group->help_description);
1643
1644   g_free (group->entries);
1645   
1646   if (group->destroy_notify)
1647     (* group->destroy_notify) (group->user_data);
1648
1649   if (group->translate_notify)
1650     (* group->translate_notify) (group->translate_data);
1651   
1652   g_free (group);
1653 }
1654
1655
1656 /**
1657  * g_option_group_add_entries:
1658  * @group: a #GOptionGroup
1659  * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
1660  * 
1661  * Adds the options specified in @entries to @group.
1662  *
1663  * Since: 2.6
1664  **/
1665 void
1666 g_option_group_add_entries (GOptionGroup       *group,
1667                             const GOptionEntry *entries)
1668 {
1669   gint i, n_entries;
1670   
1671   g_return_if_fail (entries != NULL);
1672
1673   for (n_entries = 0; entries[n_entries].long_name != NULL; n_entries++) ;
1674
1675   group->entries = g_renew (GOptionEntry, group->entries, group->n_entries + n_entries);
1676
1677   memcpy (group->entries + group->n_entries, entries, sizeof (GOptionEntry) * n_entries);
1678
1679   for (i = group->n_entries; i < group->n_entries + n_entries; i++)
1680     {
1681       gchar c = group->entries[i].short_name;
1682
1683       if (c)
1684         {
1685           if (c == '-' || !g_ascii_isprint (c))
1686             {
1687               g_warning (G_STRLOC": ignoring invalid short option '%c' (%d)", c, c);
1688               group->entries[i].short_name = 0;
1689             }
1690         }
1691     }
1692
1693   group->n_entries += n_entries;
1694 }
1695
1696 /**
1697  * g_option_group_set_parse_hooks:
1698  * @group: a #GOptionGroup
1699  * @pre_parse_func: a function to call before parsing, or %NULL
1700  * @post_parse_func: a function to call after parsing, or %NULL
1701  * 
1702  * Associates two functions with @group which will be called 
1703  * from g_option_context_parse() before the first option is parsed
1704  * and after the last option has been parsed, respectively.
1705  *
1706  * Note that the user data to be passed to @pre_parse_func and
1707  * @post_parse_func can be specified when constructing the group
1708  * with g_option_group_new().
1709  *
1710  * Since: 2.6
1711  **/
1712 void
1713 g_option_group_set_parse_hooks (GOptionGroup     *group,
1714                                 GOptionParseFunc  pre_parse_func,
1715                                 GOptionParseFunc  post_parse_func)
1716 {
1717   g_return_if_fail (group != NULL);
1718
1719   group->pre_parse_func = pre_parse_func;
1720   group->post_parse_func = post_parse_func;  
1721 }
1722
1723 /**
1724  * g_option_group_set_error_hook:
1725  * @group: a #GOptionGroup
1726  * @error_func: a function to call when an error occurs
1727  * 
1728  * Associates a function with @group which will be called 
1729  * from g_option_context_parse() when an error occurs.
1730  *
1731  * Note that the user data to be passed to @pre_parse_func and
1732  * @post_parse_func can be specified when constructing the group
1733  * with g_option_group_new().
1734  *
1735  * Since: 2.6
1736  **/
1737 void
1738 g_option_group_set_error_hook (GOptionGroup     *group,
1739                                GOptionErrorFunc  error_func)
1740 {
1741   g_return_if_fail (group != NULL);
1742
1743   group->error_func = error_func;  
1744 }
1745
1746
1747 /**
1748  * g_option_group_set_translate_func:
1749  * @group: a #GOptionGroup
1750  * @func: the #GTranslateFunc, or %NULL 
1751  * @data: user data to pass to @func, or %NULL
1752  * @destroy_notify: a function which gets called to free @data, or %NULL
1753  * 
1754  * Sets the function which is used to translate user-visible
1755  * strings, for <option>--help</option> output. Different
1756  * groups can use different #GTranslateFunc<!-- -->s. If @func
1757  * is %NULL, strings are not translated.
1758  *
1759  * If you are using gettext(), you only need to set the translation
1760  * domain, see g_option_group_set_translation_domain().
1761  *
1762  * Since: 2.6
1763  **/
1764 void
1765 g_option_group_set_translate_func (GOptionGroup   *group,
1766                                    GTranslateFunc  func,
1767                                    gpointer        data,
1768                                    GDestroyNotify  destroy_notify)
1769 {
1770   g_return_if_fail (group != NULL);
1771   
1772   if (group->translate_notify)
1773     group->translate_notify (group->translate_data);
1774       
1775   group->translate_func = func;
1776   group->translate_data = data;
1777   group->translate_notify = destroy_notify;
1778 }
1779
1780 static gchar *
1781 dgettext_swapped (const gchar *msgid, 
1782                   const gchar *domainname)
1783 {
1784   return dgettext (domainname, msgid);
1785 }
1786
1787 /**
1788  * g_option_group_set_translation_domain:
1789  * @group: a #GOptionGroup
1790  * @domain: the domain to use
1791  * 
1792  * A convenience function to use gettext() for translating
1793  * user-visible strings. 
1794  * 
1795  * Since: 2.6
1796  **/
1797 void
1798 g_option_group_set_translation_domain (GOptionGroup *group,
1799                                        const gchar  *domain)
1800 {
1801   g_return_if_fail (group != NULL);
1802
1803   g_option_group_set_translate_func (group, 
1804                                      (GTranslateFunc)dgettext_swapped,
1805                                      g_strdup (domain),
1806                                      g_free);
1807
1808
1809 #define __G_OPTION_C__
1810 #include "galiasdef.c"