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