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