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