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