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