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