New function to get the formatted help string. (#336089, Dom Lachowicz)
[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_STRING_ARRAY ||
1359                             group->entries[j].arg == G_OPTION_ARG_FILENAME_ARRAY, FALSE);
1360       
1361       add_pending_null (context, &((*argv)[*index]), NULL);
1362       
1363       if (!parse_arg (context, group, &group->entries[j], (*argv)[*index], "", error))
1364         return FALSE;
1365       
1366       *parsed = TRUE;
1367       return TRUE;
1368     }
1369
1370   return TRUE;
1371 }
1372
1373 static void
1374 free_changes_list (GOptionContext *context,
1375                    gboolean        revert)
1376 {
1377   GList *list;
1378
1379   for (list = context->changes; list != NULL; list = list->next)
1380     {
1381       Change *change = list->data;
1382
1383       if (revert)
1384         {
1385           switch (change->arg_type)
1386             {
1387             case G_OPTION_ARG_NONE:
1388               *(gboolean *)change->arg_data = change->prev.bool;
1389               break;
1390             case G_OPTION_ARG_INT:
1391               *(gint *)change->arg_data = change->prev.integer;
1392               break;
1393             case G_OPTION_ARG_STRING:
1394             case G_OPTION_ARG_FILENAME:
1395               g_free (change->allocated.str);
1396               *(gchar **)change->arg_data = change->prev.str;
1397               break;
1398             case G_OPTION_ARG_STRING_ARRAY:
1399             case G_OPTION_ARG_FILENAME_ARRAY:
1400               g_strfreev (change->allocated.array.data);
1401               *(gchar ***)change->arg_data = change->prev.array;
1402               break;
1403             case G_OPTION_ARG_DOUBLE:
1404               *(gdouble *)change->arg_data = change->prev.dbl;
1405               break;
1406             case G_OPTION_ARG_INT64:
1407               *(gint64 *)change->arg_data = change->prev.int64;
1408               break;
1409             default:
1410               g_assert_not_reached ();
1411             }
1412         }
1413       
1414       g_free (change);
1415     }
1416
1417   g_list_free (context->changes);
1418   context->changes = NULL;
1419 }
1420
1421 static void
1422 free_pending_nulls (GOptionContext *context,
1423                     gboolean        perform_nulls)
1424 {
1425   GList *list;
1426
1427   for (list = context->pending_nulls; list != NULL; list = list->next)
1428     {
1429       PendingNull *n = list->data;
1430
1431       if (perform_nulls)
1432         {
1433           if (n->value)
1434             {
1435               /* Copy back the short options */
1436               *(n->ptr)[0] = '-';             
1437               strcpy (*n->ptr + 1, n->value);
1438             }
1439           else
1440             *n->ptr = NULL;
1441         }
1442       
1443       g_free (n->value);
1444       g_free (n);
1445     }
1446
1447   g_list_free (context->pending_nulls);
1448   context->pending_nulls = NULL;
1449 }
1450
1451 /**
1452  * g_option_context_parse:
1453  * @context: a #GOptionContext
1454  * @argc: a pointer to the number of command line arguments
1455  * @argv: a pointer to the array of command line arguments
1456  * @error: a return location for errors 
1457  * 
1458  * Parses the command line arguments, recognizing options
1459  * which have been added to @context. A side-effect of 
1460  * calling this function is that g_set_prgname() will be
1461  * called.
1462  *
1463  * If the parsing is successful, any parsed arguments are
1464  * removed from the array and @argc and @argv are updated 
1465  * accordingly. A '--' option is stripped from @argv
1466  * unless there are unparsed options before and after it, 
1467  * or some of the options after it start with '-'. In case 
1468  * of an error, @argc and @argv are left unmodified. 
1469  *
1470  * If automatic <option>--help</option> support is enabled
1471  * (see g_option_context_set_help_enabled()), and the 
1472  * @argv array contains one of the recognized help options,
1473  * this function will produce help output to stdout and
1474  * call <literal>exit (0)</literal>.
1475  *
1476  * Note that function depends on the 
1477  * <link linkend="setlocale">current locale</link> for 
1478  * automatic character set conversion of string and filename
1479  * arguments.
1480  * 
1481  * Return value: %TRUE if the parsing was successful, 
1482  *               %FALSE if an error occurred
1483  *
1484  * Since: 2.6
1485  **/
1486 gboolean
1487 g_option_context_parse (GOptionContext   *context,
1488                         gint             *argc,
1489                         gchar          ***argv,
1490                         GError          **error)
1491 {
1492   gint i, j, k;
1493   GList *list;
1494
1495   /* Set program name */
1496   if (!g_get_prgname())
1497     {
1498       if (argc && argv && *argc)
1499         {
1500           gchar *prgname;
1501           
1502           prgname = g_path_get_basename ((*argv)[0]);
1503           g_set_prgname (prgname);
1504           g_free (prgname);
1505         }
1506       else
1507         g_set_prgname ("<unknown>");
1508     }
1509
1510   /* Call pre-parse hooks */
1511   list = context->groups;
1512   while (list)
1513     {
1514       GOptionGroup *group = list->data;
1515       
1516       if (group->pre_parse_func)
1517         {
1518           if (!(* group->pre_parse_func) (context, group,
1519                                           group->user_data, error))
1520             goto fail;
1521         }
1522       
1523       list = list->next;
1524     }
1525
1526   if (context->main_group && context->main_group->pre_parse_func)
1527     {
1528       if (!(* context->main_group->pre_parse_func) (context, context->main_group,
1529                                                     context->main_group->user_data, error))
1530         goto fail;
1531     }
1532
1533   if (argc && argv)
1534     {
1535       gboolean stop_parsing = FALSE;
1536       gboolean has_unknown = FALSE;
1537       gint separator_pos = 0;
1538
1539       for (i = 1; i < *argc; i++)
1540         {
1541           gchar *arg, *dash;
1542           gboolean parsed = FALSE;
1543
1544           if ((*argv)[i][0] == '-' && (*argv)[i][1] != '\0' && !stop_parsing)
1545             {
1546               if ((*argv)[i][1] == '-')
1547                 {
1548                   /* -- option */
1549
1550                   arg = (*argv)[i] + 2;
1551
1552                   /* '--' terminates list of arguments */
1553                   if (*arg == 0)
1554                     {
1555                       separator_pos = i;
1556                       stop_parsing = TRUE;
1557                       continue;
1558                     }
1559
1560                   /* Handle help options */
1561                   if (context->help_enabled)
1562                     {
1563                       if (strcmp (arg, "help") == 0)
1564                         print_help (context, TRUE, NULL);
1565                       else if (strcmp (arg, "help-all") == 0)
1566                         print_help (context, FALSE, NULL);                    
1567                       else if (strncmp (arg, "help-", 5) == 0)
1568                         {
1569                           GList *list;
1570                           
1571                           list = context->groups;
1572                           
1573                           while (list)
1574                             {
1575                               GOptionGroup *group = list->data;
1576                               
1577                               if (strcmp (arg + 5, group->name) == 0)
1578                                 print_help (context, FALSE, group);                                           
1579                               
1580                               list = list->next;
1581                             }
1582                         }
1583                     }
1584
1585                   if (context->main_group &&
1586                       !parse_long_option (context, context->main_group, &i, arg,
1587                                           FALSE, argc, argv, error, &parsed))
1588                     goto fail;
1589
1590                   if (parsed)
1591                     continue;
1592                   
1593                   /* Try the groups */
1594                   list = context->groups;
1595                   while (list)
1596                     {
1597                       GOptionGroup *group = list->data;
1598                       
1599                       if (!parse_long_option (context, group, &i, arg, 
1600                                               FALSE, argc, argv, error, &parsed))
1601                         goto fail;
1602                       
1603                       if (parsed)
1604                         break;
1605                       
1606                       list = list->next;
1607                     }
1608                   
1609                   if (parsed)
1610                     continue;
1611
1612                   /* Now look for --<group>-<option> */
1613                   dash = strchr (arg, '-');
1614                   if (dash)
1615                     {
1616                       /* Try the groups */
1617                       list = context->groups;
1618                       while (list)
1619                         {
1620                           GOptionGroup *group = list->data;
1621                           
1622                           if (strncmp (group->name, arg, dash - arg) == 0)
1623                             {
1624                               if (!parse_long_option (context, group, &i, dash + 1,
1625                                                       TRUE, argc, argv, error, &parsed))
1626                                 goto fail;
1627                               
1628                               if (parsed)
1629                                 break;
1630                             }
1631                           
1632                           list = list->next;
1633                         }
1634                     }
1635                   
1636                   if (context->ignore_unknown)
1637                     continue;
1638                 }
1639               else
1640                 { /* short option */
1641                   gint j, new_i = i, arg_length;
1642                   gboolean *nulled_out = NULL;
1643                   arg = (*argv)[i] + 1;
1644                   arg_length = strlen (arg);
1645                   nulled_out = g_newa (gboolean, arg_length);
1646                   memset (nulled_out, 0, arg_length * sizeof (gboolean));
1647                   for (j = 0; j < arg_length; j++)
1648                     {
1649                       if (context->help_enabled && arg[j] == '?')
1650                         print_help (context, TRUE, NULL);
1651                       parsed = FALSE;
1652                       if (context->main_group &&
1653                           !parse_short_option (context, context->main_group,
1654                                                i, &new_i, arg[j],
1655                                                argc, argv, error, &parsed))
1656                         goto fail;
1657                       if (!parsed)
1658                         {
1659                           /* Try the groups */
1660                           list = context->groups;
1661                           while (list)
1662                             {
1663                               GOptionGroup *group = list->data;
1664                               if (!parse_short_option (context, group, i, &new_i, arg[j],
1665                                                        argc, argv, error, &parsed))
1666                                 goto fail;
1667                               if (parsed)
1668                                 break;
1669                               list = list->next;
1670                             }
1671                         }
1672                       
1673                       if (context->ignore_unknown && parsed)
1674                         nulled_out[j] = TRUE;
1675                       else if (context->ignore_unknown)
1676                         continue;
1677                       else if (!parsed)
1678                         break;
1679                       /* !context->ignore_unknown && parsed */
1680                     }
1681                   if (context->ignore_unknown)
1682                     {
1683                       gchar *new_arg = NULL; 
1684                       gint arg_index = 0;
1685                       for (j = 0; j < arg_length; j++)
1686                         {
1687                           if (!nulled_out[j])
1688                             {
1689                               if (!new_arg)
1690                                 new_arg = g_malloc (arg_length + 1);
1691                               new_arg[arg_index++] = arg[j];
1692                             }
1693                         }
1694                       if (new_arg)
1695                         new_arg[arg_index] = '\0';
1696                       add_pending_null (context, &((*argv)[i]), new_arg);
1697                     }
1698                   else if (parsed)
1699                     {
1700                       add_pending_null (context, &((*argv)[i]), NULL);
1701                       i = new_i;
1702                     }
1703                 }
1704               
1705               if (!parsed)
1706                 has_unknown = TRUE;
1707
1708               if (!parsed && !context->ignore_unknown)
1709                 {
1710                   g_set_error (error,
1711                                G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION,
1712                                    _("Unknown option %s"), (*argv)[i]);
1713                   goto fail;
1714                 }
1715             }
1716           else
1717             {
1718               /* Collect remaining args */
1719               if (context->main_group &&
1720                   !parse_remaining_arg (context, context->main_group, &i,
1721                                         argc, argv, error, &parsed))
1722                 goto fail;
1723               
1724               if (!parsed && (has_unknown || (*argv)[i][0] == '-'))
1725                 separator_pos = 0;
1726             }
1727         }
1728
1729       if (separator_pos > 0)
1730         add_pending_null (context, &((*argv)[separator_pos]), NULL);
1731         
1732     }
1733
1734   /* Call post-parse hooks */
1735   list = context->groups;
1736   while (list)
1737     {
1738       GOptionGroup *group = list->data;
1739       
1740       if (group->post_parse_func)
1741         {
1742           if (!(* group->post_parse_func) (context, group,
1743                                            group->user_data, error))
1744             goto fail;
1745         }
1746       
1747       list = list->next;
1748     }
1749   
1750   if (context->main_group && context->main_group->post_parse_func)
1751     {
1752       if (!(* context->main_group->post_parse_func) (context, context->main_group,
1753                                                      context->main_group->user_data, error))
1754         goto fail;
1755     }
1756   
1757   if (argc && argv)
1758     {
1759       free_pending_nulls (context, TRUE);
1760       
1761       for (i = 1; i < *argc; i++)
1762         {
1763           for (k = i; k < *argc; k++)
1764             if ((*argv)[k] != NULL)
1765               break;
1766           
1767           if (k > i)
1768             {
1769               k -= i;
1770               for (j = i + k; j < *argc; j++)
1771                 {
1772                   (*argv)[j-k] = (*argv)[j];
1773                   (*argv)[j] = NULL;
1774                 }
1775               *argc -= k;
1776             }
1777         }      
1778     }
1779
1780   return TRUE;
1781
1782  fail:
1783   
1784   /* Call error hooks */
1785   list = context->groups;
1786   while (list)
1787     {
1788       GOptionGroup *group = list->data;
1789       
1790       if (group->error_func)
1791         (* group->error_func) (context, group,
1792                                group->user_data, error);
1793       
1794       list = list->next;
1795     }
1796
1797   if (context->main_group && context->main_group->error_func)
1798     (* context->main_group->error_func) (context, context->main_group,
1799                                          context->main_group->user_data, error);
1800   
1801   free_changes_list (context, TRUE);
1802   free_pending_nulls (context, FALSE);
1803
1804   return FALSE;
1805 }
1806                                    
1807 /**
1808  * g_option_group_new:
1809  * @name: the name for the option group, this is used to provide
1810  *   help for the options in this group with <option>--help-</option>@name
1811  * @description: a description for this group to be shown in 
1812  *   <option>--help</option>. This string is translated using the translation
1813  *   domain or translation function of the group
1814  * @help_description: a description for the <option>--help-</option>@name option.
1815  *   This string is translated using the translation domain or translation function
1816  *   of the group
1817  * @user_data: user data that will be passed to the pre- and post-parse hooks,
1818  *   the error hook and to callbacks of %G_OPTION_ARG_CALLBACK options, or %NULL
1819  * @destroy: a function that will be called to free @user_data, or %NULL
1820  * 
1821  * Creates a new #GOptionGroup.
1822  * 
1823  * Return value: a newly created option group. It should be added 
1824  *   to a #GOptionContext or freed with g_option_group_free().
1825  *
1826  * Since: 2.6
1827  **/
1828 GOptionGroup *
1829 g_option_group_new (const gchar    *name,
1830                     const gchar    *description,
1831                     const gchar    *help_description,
1832                     gpointer        user_data,
1833                     GDestroyNotify  destroy)
1834
1835 {
1836   GOptionGroup *group;
1837
1838   group = g_new0 (GOptionGroup, 1);
1839   group->name = g_strdup (name);
1840   group->description = g_strdup (description);
1841   group->help_description = g_strdup (help_description);
1842   group->user_data = user_data;
1843   group->destroy_notify = destroy;
1844   
1845   return group;
1846 }
1847
1848
1849 /**
1850  * g_option_group_free:
1851  * @group: a #GOptionGroup
1852  * 
1853  * Frees a #GOptionGroup. Note that you must <emphasis>not</emphasis>
1854  * free groups which have been added to a #GOptionContext.
1855  *
1856  * Since: 2.6
1857  **/
1858 void
1859 g_option_group_free (GOptionGroup *group)
1860 {
1861   g_return_if_fail (group != NULL);
1862
1863   g_free (group->name);
1864   g_free (group->description);
1865   g_free (group->help_description);
1866
1867   g_free (group->entries);
1868   
1869   if (group->destroy_notify)
1870     (* group->destroy_notify) (group->user_data);
1871
1872   if (group->translate_notify)
1873     (* group->translate_notify) (group->translate_data);
1874   
1875   g_free (group);
1876 }
1877
1878
1879 /**
1880  * g_option_group_add_entries:
1881  * @group: a #GOptionGroup
1882  * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
1883  * 
1884  * Adds the options specified in @entries to @group.
1885  *
1886  * Since: 2.6
1887  **/
1888 void
1889 g_option_group_add_entries (GOptionGroup       *group,
1890                             const GOptionEntry *entries)
1891 {
1892   gint i, n_entries;
1893   
1894   g_return_if_fail (entries != NULL);
1895
1896   for (n_entries = 0; entries[n_entries].long_name != NULL; n_entries++) ;
1897
1898   group->entries = g_renew (GOptionEntry, group->entries, group->n_entries + n_entries);
1899
1900   memcpy (group->entries + group->n_entries, entries, sizeof (GOptionEntry) * n_entries);
1901
1902   for (i = group->n_entries; i < group->n_entries + n_entries; i++)
1903     {
1904       gchar c = group->entries[i].short_name;
1905
1906       if (c)
1907         {
1908           if (c == '-' || !g_ascii_isprint (c))
1909             {
1910               g_warning (G_STRLOC": ignoring invalid short option '%c' (%d)", c, c);
1911               group->entries[i].short_name = 0;
1912             }
1913         }
1914     }
1915
1916   group->n_entries += n_entries;
1917 }
1918
1919 /**
1920  * g_option_group_set_parse_hooks:
1921  * @group: a #GOptionGroup
1922  * @pre_parse_func: a function to call before parsing, or %NULL
1923  * @post_parse_func: a function to call after parsing, or %NULL
1924  * 
1925  * Associates two functions with @group which will be called 
1926  * from g_option_context_parse() before the first option is parsed
1927  * and after the last option has been parsed, respectively.
1928  *
1929  * Note that the user data to be passed to @pre_parse_func and
1930  * @post_parse_func can be specified when constructing the group
1931  * with g_option_group_new().
1932  *
1933  * Since: 2.6
1934  **/
1935 void
1936 g_option_group_set_parse_hooks (GOptionGroup     *group,
1937                                 GOptionParseFunc  pre_parse_func,
1938                                 GOptionParseFunc  post_parse_func)
1939 {
1940   g_return_if_fail (group != NULL);
1941
1942   group->pre_parse_func = pre_parse_func;
1943   group->post_parse_func = post_parse_func;  
1944 }
1945
1946 /**
1947  * g_option_group_set_error_hook:
1948  * @group: a #GOptionGroup
1949  * @error_func: a function to call when an error occurs
1950  * 
1951  * Associates a function with @group which will be called 
1952  * from g_option_context_parse() when an error occurs.
1953  *
1954  * Note that the user data to be passed to @pre_parse_func and
1955  * @post_parse_func can be specified when constructing the group
1956  * with g_option_group_new().
1957  *
1958  * Since: 2.6
1959  **/
1960 void
1961 g_option_group_set_error_hook (GOptionGroup     *group,
1962                                GOptionErrorFunc  error_func)
1963 {
1964   g_return_if_fail (group != NULL);
1965
1966   group->error_func = error_func;  
1967 }
1968
1969
1970 /**
1971  * g_option_group_set_translate_func:
1972  * @group: a #GOptionGroup
1973  * @func: the #GTranslateFunc, or %NULL 
1974  * @data: user data to pass to @func, or %NULL
1975  * @destroy_notify: a function which gets called to free @data, or %NULL
1976  * 
1977  * Sets the function which is used to translate user-visible
1978  * strings, for <option>--help</option> output. Different
1979  * groups can use different #GTranslateFunc<!-- -->s. If @func
1980  * is %NULL, strings are not translated.
1981  *
1982  * If you are using gettext(), you only need to set the translation
1983  * domain, see g_option_group_set_translation_domain().
1984  *
1985  * Since: 2.6
1986  **/
1987 void
1988 g_option_group_set_translate_func (GOptionGroup   *group,
1989                                    GTranslateFunc  func,
1990                                    gpointer        data,
1991                                    GDestroyNotify  destroy_notify)
1992 {
1993   g_return_if_fail (group != NULL);
1994   
1995   if (group->translate_notify)
1996     group->translate_notify (group->translate_data);
1997       
1998   group->translate_func = func;
1999   group->translate_data = data;
2000   group->translate_notify = destroy_notify;
2001 }
2002
2003 static gchar *
2004 dgettext_swapped (const gchar *msgid, 
2005                   const gchar *domainname)
2006 {
2007   return dgettext (domainname, msgid);
2008 }
2009
2010 /**
2011  * g_option_group_set_translation_domain:
2012  * @group: a #GOptionGroup
2013  * @domain: the domain to use
2014  * 
2015  * A convenience function to use gettext() for translating
2016  * user-visible strings. 
2017  * 
2018  * Since: 2.6
2019  **/
2020 void
2021 g_option_group_set_translation_domain (GOptionGroup *group,
2022                                        const gchar  *domain)
2023 {
2024   g_return_if_fail (group != NULL);
2025
2026   g_option_group_set_translate_func (group, 
2027                                      (GTranslateFunc)dgettext_swapped,
2028                                      g_strdup (domain),
2029                                      g_free);
2030
2031
2032 /**
2033  * g_option_context_set_translate_func:
2034  * @context: a #GOptionContext
2035  * @func: the #GTranslateFunc, or %NULL 
2036  * @data: user data to pass to @func, or %NULL
2037  * @destroy_notify: a function which gets called to free @data, or %NULL
2038  * 
2039  * Sets the function which is used to translate the contexts 
2040  * user-visible strings, for <option>--help</option> output. 
2041  * If @func is %NULL, strings are not translated.
2042  *
2043  * Note that option groups have their own translation functions, 
2044  * this function only affects the @parameter_string (see g_option_context_nex()), 
2045  * the summary (see g_option_context_set_summary()) and the description 
2046  * (see g_option_context_set_description()).
2047  *
2048  * If you are using gettext(), you only need to set the translation
2049  * domain, see g_context_group_set_translation_domain().
2050  *
2051  * Since: 2.12
2052  **/
2053 void
2054 g_option_context_set_translate_func (GOptionContext *context,
2055                                      GTranslateFunc func,
2056                                      gpointer       data,
2057                                      GDestroyNotify destroy_notify)
2058 {
2059   g_return_if_fail (context != NULL);
2060   
2061   if (context->translate_notify)
2062     context->translate_notify (context->translate_data);
2063       
2064   context->translate_func = func;
2065   context->translate_data = data;
2066   context->translate_notify = destroy_notify;
2067 }
2068
2069 /**
2070  * g_option_context_set_translation_domain:
2071  * @context: a #GOptionContext
2072  * @domain: the domain to use
2073  * 
2074  * A convenience function to use gettext() for translating
2075  * user-visible strings. 
2076  * 
2077  * Since: 2.12
2078  **/
2079 void
2080 g_option_context_set_translation_domain (GOptionContext *context,
2081                                          const gchar     *domain)
2082 {
2083   g_return_if_fail (context != NULL);
2084
2085   g_option_context_set_translate_func (context, 
2086                                        (GTranslateFunc)dgettext_swapped,
2087                                        g_strdup (domain),
2088                                        g_free);
2089 }
2090
2091 /**
2092  * g_option_context_set_summary:
2093  * @context: a #GOptionContext
2094  * @summary: a string to be shown in <option>--help</option> output 
2095  *  before the list of options, or %NULL
2096  * 
2097  * Adds a string to be displayed in <option>--help</option> output
2098  * before the list of options. This is typically a summary of the
2099  * program functionality. 
2100  *
2101  * Note that the summary is translated (see 
2102  * g_option_context_set_translate_func()).
2103  *
2104  * Since: 2.12
2105  */
2106 void
2107 g_option_context_set_summary (GOptionContext *context,
2108                               const gchar    *summary)
2109 {
2110   g_return_if_fail (context != NULL);
2111
2112   g_free (context->summary);
2113   context->summary = g_strdup (summary);
2114 }
2115
2116
2117 /**
2118  * g_option_context_get_summary:
2119  * @context: a #GOptionContext
2120  * 
2121  * Returns the summary. See g_option_context_set_summary().
2122  *
2123  * Returns: the summary
2124  *
2125  * Since: 2.12
2126  */
2127 G_CONST_RETURN gchar *
2128 g_option_context_get_summary (GOptionContext *context)
2129 {
2130   g_return_val_if_fail (context != NULL, NULL);
2131
2132   return context->summary;
2133 }
2134
2135 /**
2136  * g_option_context_set_description:
2137  * @context: a #GOptionContext
2138  * @description: a string to be shown in <option>--help</option> output 
2139  *   after the list of options, or %NULL
2140  * 
2141  * Adds a string to be displayed in <option>--help</option> output
2142  * after the list of options. This text often includes a bug reporting
2143  * address.
2144  *
2145  * Note that the summary is translated (see 
2146  * g_option_context_set_translate_func()).
2147  *
2148  * Since: 2.12
2149  */
2150 void
2151 g_option_context_set_description (GOptionContext *context,
2152                                   const gchar    *description)
2153 {
2154   g_return_if_fail (context != NULL);
2155
2156   g_free (context->description);
2157   context->description = g_strdup (description);
2158 }
2159
2160
2161 /**
2162  * g_option_context_get_description:
2163  * @context: a #GOptionContext
2164  * 
2165  * Returns the description. See g_option_context_set_description().
2166  *
2167  * Returns: the description
2168  *
2169  * Since: 2.12
2170  */
2171 G_CONST_RETURN gchar *
2172 g_option_context_get_description (GOptionContext *context)
2173 {
2174   g_return_val_if_fail (context != NULL, NULL);
2175
2176   return context->description;
2177 }
2178
2179
2180 #define __G_OPTION_C__
2181 #include "galiasdef.c"