Document GOption
[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 "goption.h"
23
24 #include "galias.h"
25 #include "glib.h"
26 #include "gi18n.h"
27
28 #include <string.h>
29 #include <stdlib.h>
30 #include <errno.h>
31
32 #define TRANSLATE(group, str) (((group)->translate_func ? (* (group)->translate_func) ((str), (group)->translate_data) : (str)))
33
34 typedef struct {
35   GOptionArg arg_type;
36   gpointer arg_data;  
37   union {
38     gboolean bool;
39     gint integer;
40     gchar *str;
41     gchar **array;
42   } prev;
43   union {
44     gchar *str;
45     struct {
46       gint len;
47       gchar **data;
48     } array;
49   } allocated;
50 } Change;
51
52 typedef struct
53 {
54   gchar **ptr;
55   gchar *value;
56 } PendingNull;
57
58 struct _GOptionContext
59 {
60   GList *groups;
61
62   gchar *parameter_string;
63
64   gboolean help_enabled;
65   gboolean ignore_unknown;
66   
67   GOptionGroup *main_group;
68
69   /* We keep a list of change so we can revert them */
70   GList *changes;
71   
72   /* We also keep track of all argv elements that should be NULLed or
73    * modified.
74    */
75   GList *pending_nulls;
76 };
77
78 struct _GOptionGroup
79 {
80   gchar *name;
81   gchar *description;
82   gchar *help_description;
83
84   GDestroyNotify  destroy_notify;
85   gpointer        user_data;
86
87   GTranslateFunc  translate_func;
88   GDestroyNotify  translate_notify;
89   gpointer        translate_data;
90
91   GOptionEntry *entries;
92   gint         n_entries;
93
94   GOptionParseFunc pre_parse_func;
95   GOptionParseFunc post_parse_func;
96   GOptionErrorFunc error_func;
97 };
98
99 static void free_changes_list (GOptionContext *context,
100                                gboolean        revert);
101 static void free_pending_nulls (GOptionContext *context,
102                                 gboolean        perform_nulls);
103
104 GQuark
105 g_option_error_quark (void)
106 {
107   static GQuark q = 0;
108   
109   if (q == 0)
110     q = g_quark_from_static_string ("g-option-context-error-quark");
111
112   return q;
113 }
114
115 /**
116  * g_option_context_new:
117  * @parameter_string: the parameter string to be used in 
118  *    <option>--help</option> output.
119  *
120  * Creates a new option context. 
121  *
122  * Returns: a newly created #GOptionContext, which must be
123  *    freed with g_option_context_free() after use.
124  *
125  * Since: 2.6
126  */
127 GOptionContext *
128 g_option_context_new (const gchar *parameter_string)
129
130 {
131   GOptionContext *context;
132
133   context = g_new0 (GOptionContext, 1);
134
135   context->parameter_string = g_strdup (parameter_string);
136   context->help_enabled = TRUE;
137   context->ignore_unknown = FALSE;
138
139   return context;
140 }
141
142 /**
143  * g_option_context_free:
144  * @context: a #GOptionContext 
145  *
146  * Frees context and all the groups which have been 
147  * added to it.
148  *
149  * Since: 2.6
150  */
151 void g_option_context_free (GOptionContext *context) {
152 g_return_if_fail (context != NULL);
153
154   g_list_foreach (context->groups, (GFunc)g_option_group_free, NULL);
155   g_list_free (context->groups);
156
157   if (context->main_group) 
158     g_option_group_free (context->main_group);
159
160   free_changes_list (context, FALSE);
161   free_pending_nulls (context, FALSE);
162   
163   g_free (context->parameter_string);
164   
165   g_free (context);
166 }
167
168
169 /**
170  * g_option_context_set_help_enabled:
171  * @context: a #GOptionContext
172  * @help_enabled: %TRUE to enable <option>--help</option>, %FALSE to disable it
173  *
174  * Enables or disables automatic generation of <option>--help</option> 
175  * output. By default, g_option_context_parse() recognizes
176  * <option>--help</option>, <option>-?</option>, <option>--help-all</option>
177  * and <option>--help-</option><replaceable>groupname</replaceable> and creates
178  * suitable output to stdout. 
179  *
180  * Since: 2.6
181  */
182 void g_option_context_set_help_enabled (GOptionContext *context,
183                                         gboolean        help_enabled)
184
185 {
186   g_return_if_fail (context != NULL);
187
188   context->help_enabled = help_enabled;
189 }
190
191 /**
192  * g_option_context_get_help_enabled:
193  * @context: a #GOptionContext
194  * 
195  * Returns whether automatic <option>--help</option> generation
196  * is turned on for @context. See g_option_context_set_help_enabled().
197  * 
198  * Returns: %TRUE if automatic help generation is turned on.
199  *
200  * Since: 2.6
201  */
202 gboolean 
203 g_option_context_get_help_enabled (GOptionContext *context) 
204 {
205   g_return_val_if_fail (context != NULL, FALSE);
206   
207   return context->help_enabled;
208 }
209
210 /**
211  * g_option_context_set_ignore_unknown_options:
212  * @context: a #GOptionContext
213  * @ignore_unknown: %TRUE to ignore unknown options, %FALSE to produce
214  *    an error when unknown options are met
215  * 
216  * Sets whether to ignore unknown options or not. If an argument is 
217  * ignored, it is left in the @argv array after parsing. By default, 
218  * g_option_context_parse() treats unknown options as error.
219  * 
220  * This setting does not affect non-option arguments (i.e. arguments 
221  * which don't start with a dash).
222  *
223  * Since: 2.6
224  **/
225 void
226 g_option_context_set_ignore_unknown_options (GOptionContext *context,
227                                              gboolean        ignore_unknown)
228 {
229   g_return_if_fail (context != NULL);
230
231   context->ignore_unknown = ignore_unknown;
232 }
233
234 /**
235  * g_option_context_get_ignore_unknown_options:
236  * @context: a #GOptionContext
237  * 
238  * Returns whether unknown options are ignored or not. See
239  * g_option_context_set_ignore_unknown_options().
240  * 
241  * Returns: %TRUE if unknown options are ignored.
242  * 
243  * Since: 2.6
244  **/
245 gboolean
246 g_option_context_get_ignore_unknown_options (GOptionContext *context)
247 {
248   g_return_val_if_fail (context != NULL, FALSE);
249
250   return context->ignore_unknown;
251 }
252
253 /**
254  * g_option_context_add_group:
255  * @context: a #GOptionContext
256  * @group: the group to add
257  * 
258  * Adds a #GOptionGroup to the @context, so that parsing with @context
259  * will recognize the options in the group. Note that the group will
260  * be freed together with the context when g_option_context_free() is
261  * called, so you must not free the group yourself after adding it
262  * to a context.
263  *
264  * Since: 2.6
265  **/
266 void
267 g_option_context_add_group (GOptionContext *context,
268                             GOptionGroup   *group)
269 {
270   g_return_if_fail (context != NULL);
271   g_return_if_fail (group != NULL);
272   g_return_if_fail (group->name != NULL);
273   g_return_if_fail (group->description != NULL);
274   g_return_if_fail (group->help_description != NULL);
275
276   context->groups = g_list_prepend (context->groups, group);
277 }
278
279 /**
280  * g_option_context_set_main_group:
281  * @context: a #GOptionContext
282  * @group: the group to set as main group
283  * 
284  * Sets a #GOptionGroup as main group of the @context. 
285  * This has the same effect as calling g_option_context_add_group(), 
286  * the only difference is that the options in the main group are 
287  * treated differently when generating <option>--help</option> output.
288  *
289  * Since: 2.6
290  **/
291 void
292 g_option_context_set_main_group (GOptionContext *context,
293                                  GOptionGroup   *group)
294 {
295   g_return_if_fail (context != NULL);
296   g_return_if_fail (group != NULL);
297
298   context->main_group = group;
299 }
300
301 /**
302  * g_option_context_get_main_group:
303  * @context: a #GOptionContext
304  * 
305  * Returns a pointer to the main group of @context.
306  * 
307  * Return value: the main group of @context, or %NULL if @context doesn't
308  *  have a main group. Note that group belongs to @context and should
309  *  not be modified or freed.
310  *
311  * Since: 2.6
312  **/
313 GOptionGroup *
314 g_option_context_get_main_group (GOptionContext *context)
315 {
316   g_return_val_if_fail (context != NULL, NULL);
317
318   return context->main_group;
319 }
320
321 /**
322  * g_option_context_add_main_entries:
323  * @context: a #GOptionContext
324  * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
325  * @translation_domain: a translation domain to use for translating
326  *    the <option>--help</option> output for the options in @entries
327  *    with gettext(), or %NULL
328  * 
329  * A convenience function which creates a main group if it doesn't 
330  * exist, adds the @entries to it and sets the translation domain.
331  * 
332  * Since: 2.6
333  **/
334 void
335 g_option_context_add_main_entries (GOptionContext      *context,
336                                    const GOptionEntry  *entries,
337                                    const gchar         *translation_domain)
338 {
339   g_return_if_fail (entries != NULL);
340
341   if (!context->main_group)
342     context->main_group = g_option_group_new (NULL, NULL, NULL, NULL, NULL);
343   
344   g_option_group_add_entries (context->main_group, entries);
345   g_option_group_set_translation_domain (context->main_group, translation_domain);
346 }
347
348 static void
349 print_entry (GOptionGroup       *group,
350              gint                max_length,
351              const GOptionEntry *entry)
352 {
353   GString *str;
354
355   if (entry->flags & G_OPTION_FLAG_HIDDEN)
356     return;
357           
358   str = g_string_new (NULL);
359   
360   if (entry->short_name)
361     g_string_append_printf (str, "  -%c, --%s", entry->short_name, entry->long_name);
362   else
363     g_string_append_printf (str, "  --%s", entry->long_name);
364   
365   if (entry->arg_description)
366     g_string_append_printf (str, "=%s", TRANSLATE (group, entry->arg_description));
367   
368   g_print ("%-*s %s\n", max_length + 4, str->str,
369            entry->description ? TRANSLATE (group, entry->description) : "");
370   g_string_free (str, TRUE);  
371 }
372
373 static void
374 print_help (GOptionContext *context,
375             gboolean        main_help,
376             GOptionGroup   *group)
377 {
378   GList *list;
379   gint max_length, len;
380   gint i;
381   
382   g_print ("%s\n  %s %s %s\n\n", 
383            _("Usage:"), g_get_prgname(), _("[OPTION...]"),
384            context->parameter_string ? context->parameter_string : "");
385
386   list = context->groups;
387
388   max_length = g_utf8_strlen ("--help, -?", -1);
389
390   if (list)
391     {
392       len = g_utf8_strlen ("--help-all", -1);
393       max_length = MAX (max_length, len);
394     }
395
396   while (list != NULL)
397     {
398       GOptionGroup *group = list->data;
399       
400       /* First, we check the --help-<groupname> options */
401       len = g_utf8_strlen ("--help-", -1) + g_utf8_strlen (group->name, -1);
402       max_length = MAX (max_length, len);
403
404       /* Then we go through the entries */
405       for (i = 0; i < group->n_entries; i++)
406         {
407           len = g_utf8_strlen (group->entries[i].long_name, -1);
408
409           if (group->entries[i].short_name)
410             len += 4;
411
412           if (group->entries[i].arg != G_OPTION_ARG_NONE &&
413               group->entries[i].arg_description)
414             len += 1 + g_utf8_strlen (TRANSLATE (group, group->entries[i].arg_description), -1);
415
416           max_length = MAX (max_length, len);
417         }
418       
419       list = list->next;
420     }
421
422   /* Add a bit of padding */
423   max_length += 4;
424   
425   list = context->groups;
426
427   g_print ("%s\n  --%-*s %s\n", 
428            _("Help Options:"), max_length, "help", _("Show help options"));
429
430   /* We only want --help-all when there are groups */
431   if (list)
432     g_print ("  --%-*s %s\n", max_length, "help-all", _("Show all help options"));
433
434   while (list)
435     {
436       GOptionGroup *group = list->data;
437
438       g_print ("  --help-%-*s %s\n", max_length - 5, group->name, TRANSLATE (group, group->help_description));
439       
440       list = list->next;
441     }
442
443   g_print ("\n");
444
445   if (group)
446     {
447       /* Print a certain group */
448       
449       g_print ("%s\n", TRANSLATE (group, group->description));
450       for (i = 0; i < group->n_entries; i++)
451         print_entry (group, max_length, &group->entries[i]);
452       g_print ("\n");
453     }
454   else if (!main_help)
455     {
456       /* Print all groups */
457
458       list = context->groups;
459
460       while (list)
461         {
462           GOptionGroup *group = list->data;
463
464           g_print ("%s\n", group->description);
465
466           for (i = 0; i < group->n_entries; i++)
467             if (!(group->entries[i].flags & G_OPTION_FLAG_IN_MAIN))
468               print_entry (group, max_length, &group->entries[i]);
469           
470           g_print ("\n");
471           list = list->next;
472         }
473     }
474   
475   /* Print application options if --help or --help-all has been specified */
476   if (main_help || !group)
477     {
478       list = context->groups;
479
480       g_print ("%s\n", _("Application Options:"));
481
482       if (context->main_group)
483         for (i = 0; i < context->main_group->n_entries; i++) 
484           print_entry (context->main_group, max_length, &context->main_group->entries[i]);
485
486       while (list != NULL)
487         {
488           GOptionGroup *group = list->data;
489
490           /* Print main entries from other groups */
491           for (i = 0; i < group->n_entries; i++)
492             if (group->entries[i].flags & G_OPTION_FLAG_IN_MAIN)
493               print_entry (group, max_length, &group->entries[i]);
494           
495           list = list->next;
496         }
497
498       g_print ("\n");
499     }
500
501   
502   exit (0);
503 }
504
505 static gboolean
506 parse_int (const gchar *arg_name,
507            const gchar *arg,
508            gint        *result,
509            GError     **error)
510 {
511   gchar *end;
512   glong tmp = strtol (arg, &end, 0);
513
514   errno = 0;
515   
516   if (*arg == '\0' || *end != '\0')
517     {
518       g_set_error (error,
519                    G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
520                    _("Cannot parse integer value '%s' for --%s"),
521                    arg, arg_name);
522       return FALSE;
523     }
524
525   *result = tmp;
526   if (*result != tmp || errno == ERANGE)
527     {
528       g_set_error (error,
529                    G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
530                    _("Integer value '%s' for %s out of range"),
531                    arg, arg_name);
532       return FALSE;
533     }
534
535   return TRUE;
536 }
537
538 static Change *
539 get_change (GOptionContext *context,
540             GOptionArg      arg_type,
541             gpointer        arg_data)
542 {
543   GList *list;
544   Change *change = NULL;
545   
546   for (list = context->changes; list != NULL; list = list->next)
547     {
548       change = list->data;
549
550       if (change->arg_data == arg_data)
551         goto found;
552     }
553
554   change = g_new0 (Change, 1);
555   change->arg_type = arg_type;
556   change->arg_data = arg_data;
557   
558   context->changes = g_list_prepend (context->changes, change);
559   
560  found:
561
562   return change;
563 }
564
565 static void
566 add_pending_null (GOptionContext *context,
567                   gchar         **ptr,
568                   gchar          *value)
569 {
570   PendingNull *n;
571
572   n = g_new0 (PendingNull, 1);
573   n->ptr = ptr;
574   n->value = value;
575
576   context->pending_nulls = g_list_prepend (context->pending_nulls, n);
577 }
578                   
579 static gboolean
580 parse_arg (GOptionContext *context,
581            GOptionGroup   *group,
582            GOptionEntry   *entry,
583            const gchar    *value,
584            const gchar    *option_name,
585            GError        **error)
586      
587 {
588   Change *change;
589   
590   switch (entry->arg)
591     {
592     case G_OPTION_ARG_NONE:
593       {
594         change = get_change (context, G_OPTION_ARG_NONE,
595                              entry->arg_data);
596
597         *(gboolean *)entry->arg_data = TRUE;
598         break;
599       }      
600     case G_OPTION_ARG_STRING:
601       {
602         gchar *data;
603
604         data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
605
606         if (!data)
607           return FALSE;
608
609         change = get_change (context, G_OPTION_ARG_STRING,
610                              entry->arg_data);
611         g_free (change->allocated.str);
612         
613         change->prev.str = *(gchar **)entry->arg_data;
614         change->allocated.str = data;
615         
616         *(gchar **)entry->arg_data = data;
617         break;
618       }
619     case G_OPTION_ARG_STRING_ARRAY:
620       {
621         gchar *data;
622         
623         data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
624
625         if (!data)
626           return FALSE;
627
628         change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
629                              entry->arg_data);
630
631         if (change->allocated.array.len == 0)
632           {
633             change->prev.array = entry->arg_data;
634             change->allocated.array.data = g_new (gchar *, 2);
635           }
636         else
637           change->allocated.array.data =
638             g_renew (gchar *, change->allocated.array.data,
639                      change->allocated.array.len + 2);
640
641         change->allocated.array.data[change->allocated.array.len] = data;
642         change->allocated.array.data[change->allocated.array.len + 1] = NULL;
643
644         change->allocated.array.len ++;
645
646         *(gchar ***)entry->arg_data = change->allocated.array.data;
647
648         break;
649       }
650       
651     case G_OPTION_ARG_FILENAME:
652       {
653         gchar *data;
654
655         data = g_strdup (value);
656
657         change = get_change (context, G_OPTION_ARG_FILENAME,
658                              entry->arg_data);
659         g_free (change->allocated.str);
660         
661         change->prev.str = *(gchar **)entry->arg_data;
662         change->allocated.str = data;
663
664         *(gchar **)entry->arg_data = data;
665         break;
666       }
667
668     case G_OPTION_ARG_FILENAME_ARRAY:
669       {
670         gchar *data;
671         
672         data = g_strdup (value);
673
674         change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
675                              entry->arg_data);
676
677         if (change->allocated.array.len == 0)
678           {
679             change->prev.array = entry->arg_data;
680             change->allocated.array.data = g_new (gchar *, 2);
681           }
682         else
683           change->allocated.array.data =
684             g_renew (gchar *, change->allocated.array.data,
685                      change->allocated.array.len + 2);
686
687         change->allocated.array.data[change->allocated.array.len] = data;
688         change->allocated.array.data[change->allocated.array.len + 1] = NULL;
689
690         change->allocated.array.len ++;
691
692         *(gchar ***)entry->arg_data = change->allocated.array.data;
693
694         break;
695       }
696       
697     case G_OPTION_ARG_INT:
698       {
699         gint data;
700
701         if (!parse_int (option_name, value,
702                         &data,
703                         error))
704           return FALSE;
705
706         change = get_change (context, G_OPTION_ARG_INT,
707                              entry->arg_data);
708         change->prev.integer = *(gint *)entry->arg_data;
709         *(gint *)entry->arg_data = data;
710         break;
711       }
712     case G_OPTION_ARG_CALLBACK:
713       {
714         gchar *tmp;
715         gboolean retval;
716         
717         tmp = g_locale_to_utf8 (value, -1, NULL, NULL, error);
718
719         if (!value)
720           return FALSE;
721
722         retval = (* (GOptionArgFunc) entry->arg_data) (option_name, tmp, group->user_data, error);
723         
724         g_free (tmp);
725         
726         return retval;
727         
728         break;
729       }
730     default:
731       g_assert_not_reached ();
732     }
733
734   return TRUE;
735 }
736
737 static gboolean
738 parse_short_option (GOptionContext *context,
739                     GOptionGroup   *group,
740                     gint            index,
741                     gint           *new_index,
742                     gchar           arg,
743                     gint           *argc,
744                     gchar        ***argv,
745                     GError        **error,
746                     gboolean       *parsed)
747 {
748   gint j;
749     
750   for (j = 0; j < group->n_entries; j++)
751     {
752       if (arg == group->entries[j].short_name)
753         {
754           if (group->entries[j].arg == G_OPTION_ARG_NONE)
755             {
756               parse_arg (context, group, &group->entries[j],
757                          NULL, NULL, error);
758               *parsed = TRUE;
759             }
760           else
761             {
762               gchar *value = NULL;
763               gchar *option_name;
764               
765               if (*new_index > index)
766                 {
767                   g_warning ("FIXME: figure out the correct error here");
768
769                   return FALSE;
770                 }
771               
772               if (index < *argc - 1)
773                 {
774                   value = (*argv)[index + 1];
775                   add_pending_null (context, &((*argv)[index + 1]), NULL);
776                   *new_index = index + 1;
777                 }
778               else
779                 value = "";
780
781
782               option_name = g_strdup_printf ("-%c", group->entries[j].short_name);
783               
784               if (!parse_arg (context, group, &group->entries[j], value, option_name, error))
785                 {
786                   g_free (option_name);
787                   return FALSE;
788                 }
789
790               g_free (option_name);
791               *parsed = TRUE;
792             }
793         }
794     }
795
796   return TRUE;
797 }
798
799 static gboolean
800 parse_long_option (GOptionContext *context,
801                    GOptionGroup   *group,
802                    gint           *index,
803                    gchar          *arg,
804                    gint           *argc,
805                    gchar        ***argv,
806                    GError        **error,
807                    gboolean       *parsed)
808 {
809   gint j;
810
811   for (j = 0; j < group->n_entries; j++)
812     {
813       if (*index >= *argc)
814         return TRUE;
815
816       if (group->entries[j].arg == G_OPTION_ARG_NONE &&
817           strcmp (arg, group->entries[j].long_name) == 0)
818         {
819           parse_arg (context, group, &group->entries[j],
820                      NULL, NULL, error);
821           
822           add_pending_null (context, &((*argv)[*index]), NULL);
823           *parsed = TRUE;
824         }
825       else
826         {
827           gint len = strlen (group->entries[j].long_name);
828           
829           if (strncmp (arg, group->entries[j].long_name, len) == 0 &&
830               (arg[len] == '=' || arg[len] == 0))
831             {
832               gchar *value = NULL;
833               gchar *option_name;
834
835               add_pending_null (context, &((*argv)[*index]), NULL);
836               
837               if (arg[len] == '=')
838                 value = arg + len + 1;
839               else if (*index < *argc - 1)
840                 {
841                   value = (*argv)[*index + 1];
842                   add_pending_null (context, &((*argv)[*index + 1]), NULL);
843                   (*index)++;
844                 }
845               else
846                 value = "";
847
848               option_name = g_strconcat ("--", group->entries[j].long_name, NULL);
849               
850               if (!parse_arg (context, group, &group->entries[j], value, option_name, error))
851                 {
852                   g_free (option_name);
853                   return FALSE;
854                 }
855
856               g_free (option_name);
857               *parsed = TRUE;
858             }
859         }
860     }
861   
862   return TRUE;
863 }
864
865 static void
866 free_changes_list (GOptionContext *context,
867                    gboolean        revert)
868 {
869   GList *list;
870
871   for (list = context->changes; list != NULL; list = list->next)
872     {
873       Change *change = list->data;
874
875       if (revert)
876         {
877           switch (change->arg_type)
878             {
879             case G_OPTION_ARG_NONE:
880               *(gboolean *)change->arg_data = change->prev.bool;
881               break;
882             case G_OPTION_ARG_INT:
883               *(gint *)change->arg_data = change->prev.integer;
884               break;
885             case G_OPTION_ARG_STRING:
886             case G_OPTION_ARG_FILENAME:
887               g_free (change->allocated.str);
888               *(gchar **)change->arg_data = change->prev.str;
889               break;
890             case G_OPTION_ARG_STRING_ARRAY:
891             case G_OPTION_ARG_FILENAME_ARRAY:
892               g_strfreev (change->allocated.array.data);
893               *(gchar ***)change->arg_data = change->prev.array;
894               break;
895             default:
896               g_assert_not_reached ();
897             }
898         }
899       
900       g_free (change);
901     }
902
903   g_list_free (context->changes);
904   context->changes = NULL;
905 }
906
907 static void
908 free_pending_nulls (GOptionContext *context,
909                     gboolean        perform_nulls)
910 {
911   GList *list;
912
913   for (list = context->pending_nulls; list != NULL; list = list->next)
914     {
915       PendingNull *n = list->data;
916
917       if (perform_nulls)
918         {
919           if (n->value)
920             {
921               /* Copy back the short options */
922               *(n->ptr)[0] = '-';             
923               strcpy (*n->ptr + 1, n->value);
924             }
925           else
926             *n->ptr = NULL;
927         }
928       
929       g_free (n->value);
930       g_free (n);
931     }
932
933   g_list_free (context->pending_nulls);
934   context->pending_nulls = NULL;
935 }
936
937 /**
938  * g_option_context_parse:
939  * @context: a #GOptionContext
940  * @argc: a pointer to the number of command line arguments.
941  * @argv: a pointer to the array of command line arguments.
942  * @error: a return location for errors 
943  * 
944  * Parses the command line arguments, recognizing options
945  * which have been added to @context. A side-effect of 
946  * calling this function is that g_set_prgname() will be
947  * called.
948  *
949  * If the parsing is successful, any parsed arguments are
950  * removed from the array and @argc and @argv are updated 
951  * accordingly. In case of an error, @argc and @argv are
952  * left unmodified.
953  * 
954  * Return value: %TRUE if the parsing was successful, 
955  *               %FALSE if an error occurred
956  *
957  * Since: 2.6
958  **/
959 gboolean
960 g_option_context_parse (GOptionContext   *context,
961                         gint             *argc,
962                         gchar          ***argv,
963                         GError          **error)
964 {
965   gint i, j, k;
966   GList *list;
967
968   /* Set program name */
969   if (argc && argv && *argc)
970     {
971       gchar *prgname;
972       
973       prgname = g_path_get_basename ((*argv)[0]);
974       g_set_prgname (prgname);
975       g_free (prgname);
976     }
977   else
978     {
979       g_set_prgname ("<unknown>");
980     }
981   
982   /* Call pre-parse hooks */
983   list = context->groups;
984   while (list)
985     {
986       GOptionGroup *group = list->data;
987       
988       if (group->pre_parse_func)
989         {
990           if (!(* group->pre_parse_func) (context, group,
991                                           group->user_data, error))
992             goto fail;
993         }
994       
995       list = list->next;
996     }
997
998   if (context->main_group && context->main_group->pre_parse_func)
999     {
1000       if (!(* context->main_group->pre_parse_func) (context, context->main_group,
1001                                                     context->main_group->user_data, error))
1002         goto fail;
1003     }
1004
1005   if (argc && argv)
1006     {
1007       for (i = 1; i < *argc; i++)
1008         {
1009           gchar *arg;
1010           gboolean parsed = FALSE;
1011
1012           if ((*argv)[i][0] == '-')
1013             {
1014               if ((*argv)[i][1] == '-')
1015                 {
1016                   /* -- option */
1017
1018                   arg = (*argv)[i] + 2;
1019
1020                   /* '--' terminates list of arguments */
1021                   if (*arg == 0)
1022                     {
1023                       add_pending_null (context, &((*argv)[i]), NULL);
1024                       break;
1025                     }
1026
1027                   /* Handle help options */
1028                   if (context->help_enabled)
1029                     {
1030                       if (strcmp (arg, "help") == 0)
1031                         print_help (context, TRUE, NULL);
1032                       else if (strcmp (arg, "help-all") == 0)
1033                         print_help (context, FALSE, NULL);                    
1034                       else if (strncmp (arg, "help-", 5) == 0)
1035                         {
1036                           GList *list;
1037                           
1038                           list = context->groups;
1039                           
1040                           while (list)
1041                             {
1042                               GOptionGroup *group = list->data;
1043                               
1044                               if (strcmp (arg + 5, group->name) == 0)
1045                                 print_help (context, FALSE, group);                                           
1046                               
1047                               list = list->next;
1048                             }
1049                         }
1050                     }
1051
1052                   if (context->main_group &&
1053                       !parse_long_option (context, context->main_group, &i, arg,
1054                                           argc, argv, error, &parsed))
1055                     goto fail;
1056
1057                   if (parsed)
1058                     continue;
1059                   
1060                   /* Try the groups */
1061                   list = context->groups;
1062                   while (list)
1063                     {
1064                       GOptionGroup *group = list->data;
1065                       
1066                       if (!parse_long_option (context, group, &i, arg,
1067                                               argc, argv, error, &parsed))
1068                         goto fail;
1069                       
1070                       if (parsed)
1071                         break;
1072                       
1073                       list = list->next;
1074                     }
1075
1076                   if (context->ignore_unknown)
1077                     continue;
1078                 }
1079               else
1080                 {
1081                   gint new_i, j;
1082                   gboolean *nulled_out = NULL;
1083                   
1084                   arg = (*argv)[i] + 1;
1085
1086                   new_i = i;
1087
1088                   if (context->ignore_unknown)
1089                     nulled_out = g_new0 (gboolean, strlen (arg));
1090                   
1091                   for (j = 0; j < strlen (arg); j++)
1092                     {
1093                       parsed = FALSE;
1094                       
1095                       if (context->main_group &&
1096                           !parse_short_option (context, context->main_group,
1097                                                i, &new_i, arg[j],
1098                                                argc, argv, error, &parsed))
1099                         {
1100
1101                           g_free (nulled_out);
1102                           goto fail;
1103                         }
1104
1105                       if (!parsed)
1106                         {
1107                           /* Try the groups */
1108                           list = context->groups;
1109                           while (list)
1110                             {
1111                               GOptionGroup *group = list->data;
1112                               
1113                               if (!parse_short_option (context, group, i, &new_i, arg[j],
1114                                                        argc, argv, error, &parsed))
1115                                 goto fail;
1116                               
1117                               if (parsed)
1118                                 break;
1119                           
1120                               list = list->next;
1121                             }
1122                         }
1123
1124                       if (context->ignore_unknown)
1125                         {
1126                           if (parsed)
1127                             nulled_out[j] = TRUE;
1128                           else
1129                             continue;
1130                         }
1131
1132                       if (!parsed)
1133                         break;
1134                     }
1135
1136                   if (context->ignore_unknown)
1137                     {
1138                       gchar *new_arg = NULL; 
1139                       gint arg_index = 0;
1140                       
1141                       for (j = 0; j < strlen (arg); j++)
1142                         {
1143                           if (!nulled_out[j])
1144                             {
1145                               if (!new_arg)
1146                                 new_arg = g_malloc (strlen (arg));
1147                               new_arg[arg_index++] = arg[j];
1148                             }
1149                         }
1150                       if (new_arg)
1151                         new_arg[arg_index] = '\0';
1152                       
1153                       add_pending_null (context, &((*argv)[i]), new_arg);
1154                     }
1155                   else if (parsed)
1156                     {
1157                       add_pending_null (context, &((*argv)[i]), NULL);
1158                       i = new_i;
1159                     }
1160                 }
1161               
1162               if (!parsed && !context->ignore_unknown)
1163                 {
1164                   g_set_error (error,
1165                                G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION,
1166                                _("Unknown option %s"), (*argv)[i]);
1167                   goto fail;
1168                 }
1169             }
1170         }
1171
1172       /* Call post-parse hooks */
1173       list = context->groups;
1174       while (list)
1175         {
1176           GOptionGroup *group = list->data;
1177
1178           if (group->post_parse_func)
1179             {
1180               if (!(* group->post_parse_func) (context, group,
1181                                                group->user_data, error))
1182                 goto fail;
1183             }
1184           
1185           list = list->next;
1186         }
1187
1188       if (context->main_group && context->main_group->post_parse_func)
1189         {
1190           if (!(* context->main_group->post_parse_func) (context, context->main_group,
1191                                                          context->main_group->user_data, error))
1192             goto fail;
1193         }
1194
1195       free_pending_nulls (context, TRUE);
1196       
1197       for (i = 1; i < *argc; i++)
1198         {
1199           for (k = i; k < *argc; k++)
1200             if ((*argv)[k] != NULL)
1201               break;
1202           
1203           if (k > i)
1204             {
1205               k -= i;
1206               for (j = i + k; j < *argc; j++)
1207                 (*argv)[j-k] = (*argv)[j];
1208               *argc -= k;
1209             }
1210         }      
1211     }
1212
1213   return TRUE;
1214
1215  fail:
1216   
1217   /* Call error hooks */
1218   list = context->groups;
1219   while (list)
1220     {
1221       GOptionGroup *group = list->data;
1222       
1223       if (group->error_func)
1224         (* group->error_func) (context, group,
1225                                group->user_data, error);
1226       
1227       list = list->next;
1228     }
1229
1230   if (context->main_group && context->main_group->error_func)
1231     (* context->main_group->error_func) (context, context->main_group,
1232                                          context->main_group->user_data, error);
1233   
1234   free_changes_list (context, TRUE);
1235   free_pending_nulls (context, FALSE);
1236
1237   return FALSE;
1238 }
1239                                    
1240 /**
1241  * g_option_group_new:
1242  * @name: the name for the option group, this is used to provide
1243  *   help for the options in this group with <option>--help-</option>@name
1244  * @description: a description for this group to be shown in 
1245  *   <option>--help</option>. This string is translated using the translation
1246  *   domain or translation function of the group
1247  * @help_description: a description for the <option>--help-</option>@name option.
1248  *   This string is translated using the translation domain or translation function
1249  *   of the group
1250  * @user_data: user data that will be passed to the pre- and post-parse hooks,
1251  *   the error hook and to callbacks of %G_OPTION_ARG_CALLBACK options, or %NULL
1252  * @destroy: a function that will be called to free @user_data, or %NULL
1253  * 
1254  * Creates a new #GOptionGroup.
1255  * 
1256  * Return value: a newly created option group. It should be added 
1257  *   to a #GOptionContext or freed with g_option_group_free().
1258  *
1259  * Since: 2.6
1260  **/
1261 GOptionGroup *
1262 g_option_group_new (const gchar    *name,
1263                     const gchar    *description,
1264                     const gchar    *help_description,
1265                     gpointer        user_data,
1266                     GDestroyNotify  destroy)
1267
1268 {
1269   GOptionGroup *group;
1270
1271   group = g_new0 (GOptionGroup, 1);
1272   group->name = g_strdup (name);
1273   group->description = g_strdup (description);
1274   group->help_description = g_strdup (help_description);
1275   group->user_data = user_data;
1276   group->destroy_notify = destroy;
1277   
1278   return group;
1279 }
1280
1281 /**
1282  * g_option_group_free:
1283  * @group: a #GOptionGroup
1284  * 
1285  * Frees a #GOptionGroup. Note that you must <emphasis>not</emphasis>
1286  * free groups which have been added to a #GOptionContext.
1287  *
1288  * Since: 2.6
1289  **/
1290 void
1291 g_option_group_free (GOptionGroup *group)
1292 {
1293   g_return_if_fail (group != NULL);
1294
1295   g_free (group->name);
1296   g_free (group->description);
1297   g_free (group->help_description);
1298
1299   g_free (group->entries);
1300   
1301   if (group->destroy_notify)
1302     (* group->destroy_notify) (group->user_data);
1303
1304   if (group->translate_notify)
1305     (* group->translate_notify) (group->translate_data);
1306   
1307   g_free (group);
1308 }
1309
1310
1311 /**
1312  * g_option_group_add_entries:
1313  * @group: a #GOptionGroup
1314  * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
1315  * 
1316  * Adds the options specified in @entries to @group.
1317  *
1318  * Since: 2.6
1319  **/
1320 void
1321 g_option_group_add_entries (GOptionGroup       *group,
1322                             const GOptionEntry *entries)
1323 {
1324   gint n_entries;
1325   
1326   g_return_if_fail (entries != NULL);
1327
1328   for (n_entries = 0; entries[n_entries].long_name != NULL; n_entries++);
1329
1330   group->entries = g_renew (GOptionEntry, group->entries, group->n_entries + n_entries);
1331
1332   memcpy (group->entries + group->n_entries, entries, sizeof (GOptionEntry) * n_entries);
1333
1334   group->n_entries += n_entries;
1335 }
1336
1337 /**
1338  * g_option_group_set_parse_hooks:
1339  * @group: a #GOptionGroup
1340  * @pre_parse_func: a function to call before parsing, or %NULL
1341  * @post_parse_func: a function to call after parsing, or %NULL
1342  * 
1343  * Associates two functions with @group which will be called 
1344  * from g_option_context_parse() before the first option is parsed
1345  * and after the last option has been parsed, respectively.
1346  *
1347  * Note that the user data to be passed to @pre_parse_func and
1348  * @post_parse_func can be specified when constructing the group
1349  * with g_option_group_new().
1350  *
1351  * Since: 2.6
1352  **/
1353 void
1354 g_option_group_set_parse_hooks (GOptionGroup     *group,
1355                                 GOptionParseFunc  pre_parse_func,
1356                                 GOptionParseFunc  post_parse_func)
1357 {
1358   g_return_if_fail (group != NULL);
1359
1360   group->pre_parse_func = pre_parse_func;
1361   group->post_parse_func = post_parse_func;  
1362 }
1363
1364 /**
1365  * g_option_group_set_error_hook:
1366  * @group: a #GOptionGroup
1367  * @error_func: a function to call when an error occurs
1368  * 
1369  * Associates a function with @group which will be called 
1370  * from g_option_context_parse() when an error occurs.
1371  *
1372  * Note that the user data to be passed to @pre_parse_func and
1373  * @post_parse_func can be specified when constructing the group
1374  * with g_option_group_new().
1375  *
1376  * Since: 2.6
1377  **/
1378 void
1379 g_option_group_set_error_hook (GOptionGroup     *group,
1380                                GOptionErrorFunc  error_func)
1381 {
1382   g_return_if_fail (group != NULL);
1383
1384   group->error_func = error_func;  
1385 }
1386
1387
1388 /**
1389  * g_option_group_set_translate_func:
1390  * @group: a #GOptionGroup
1391  * @func: the #GTranslateFunc, or %NULL 
1392  * @data: user data to pass to @func, or %NULL
1393  * @destroy_notify: a function which gets called to free @data, or %NULL
1394  * 
1395  * Sets the function which is used to translate user-visible
1396  * strings, for <option>--help</option> output. Different
1397  * groups can use different #GTranslateFunc<!-- -->s. If @func
1398  * is %NULL, strings are not translated.
1399  *
1400  * If you are using gettext(), you only need to set the translation
1401  * domain, see g_option_group_set_translation_domain().
1402  *
1403  * Since: 2.6
1404  **/
1405 void
1406 g_option_group_set_translate_func (GOptionGroup   *group,
1407                                    GTranslateFunc  func,
1408                                    gpointer        data,
1409                                    GDestroyNotify  destroy_notify)
1410 {
1411   g_return_if_fail (group != NULL);
1412   
1413   if (group->translate_notify)
1414     group->translate_notify (group->translate_data);
1415       
1416   group->translate_func = func;
1417   group->translate_data = data;
1418   group->translate_notify = notify;
1419 }
1420
1421 static gchar *
1422 dgettext_swapped (const gchar *msgid, 
1423                   const gchar *domainname)
1424 {
1425   return dgettext (domainname, msgid);
1426 }
1427
1428 /**
1429  * g_option_group_set_translation_domain:
1430  * @group: a #GOptionGroup
1431  * @domain: the domain to use
1432  * 
1433  * A convenience function to use gettext() for translating
1434  * user-visible strings. 
1435  * 
1436  * Since: 2.6
1437  **/
1438 void
1439 g_option_group_set_translation_domain (GOptionGroup *group,
1440                                        const gchar  *domain)
1441 {
1442   g_return_if_fail (group != NULL);
1443
1444   g_option_group_set_translate_func (group, 
1445                                      (GTranslateFunc)dgettext_swapped,
1446                                      g_strdup (domain),
1447                                      g_free);
1448
1449