1 /* goption.c - Option parser
2 *
3 * Copyright (C) 1999, 2003 Red Hat Software
4 * Copyright (C) 2004 Anders Carlsson <andersca@gnome.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22 #include "config.h"
23
24 #include "goption.h"
25 #include "glib.h"
26 #include "glibintl.h"
27 #include "gprintf.h"
28
29 #include "galias.h"
30
31 #include <string.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <errno.h>
35
36 #define TRANSLATE(group, str) (((group)->translate_func ? (* (group)->translate_func) ((str), (group)->translate_data) : (str)))
37
38 #define NO_ARG(entry) ((entry)->arg == G_OPTION_ARG_NONE || \
39 ((entry)->arg == G_OPTION_ARG_CALLBACK && \
40 ((entry)->flags & G_OPTION_FLAG_NO_ARG)))
41
42 #define OPTIONAL_ARG(entry) ((entry)->arg == G_OPTION_ARG_CALLBACK && \
43 (entry)->flags & G_OPTION_FLAG_OPTIONAL_ARG)
44
45 typedef struct
46 {
47 GOptionArg arg_type;
48 gpointer arg_data;
49 union
50 {
51 gboolean bool;
52 gint integer;
53 gchar *str;
54 gchar **array;
55 gdouble dbl;
56 gint64 int64;
57 } prev;
58 union
59 {
60 gchar *str;
61 struct
62 {
63 gint len;
64 gchar **data;
65 } array;
66 } allocated;
67 } Change;
68
69 typedef struct
70 {
71 gchar **ptr;
72 gchar *value;
73 } PendingNull;
74
75 struct _GOptionContext
76 {
77 GList *groups;
78
79 gchar *parameter_string;
80 gchar *summary;
81 gchar *description;
82
83 GTranslateFunc translate_func;
84 GDestroyNotify translate_notify;
85 gpointer translate_data;
86
87 guint help_enabled : 1;
88 guint ignore_unknown : 1;
89
90 GOptionGroup *main_group;
91
92 /* We keep a list of change so we can revert them */
93 GList *changes;
94
95 /* We also keep track of all argv elements
96 * that should be NULLed or modified.
97 */
98 GList *pending_nulls;
99 };
100
101 struct _GOptionGroup
102 {
103 gchar *name;
104 gchar *description;
105 gchar *help_description;
106
107 GDestroyNotify destroy_notify;
108 gpointer user_data;
109
110 GTranslateFunc translate_func;
111 GDestroyNotify translate_notify;
112 gpointer translate_data;
113
114 GOptionEntry *entries;
115 gint n_entries;
116
117 GOptionParseFunc pre_parse_func;
118 GOptionParseFunc post_parse_func;
119 GOptionErrorFunc error_func;
120 };
121
122 static void free_changes_list (GOptionContext *context,
123 gboolean revert);
124 static void free_pending_nulls (GOptionContext *context,
125 gboolean perform_nulls);
126
127
128 static int
_g_unichar_get_width(gunichar c)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
_g_utf8_strwidth(const gchar * p,gssize max)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
g_option_error_quark(void)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 *
g_option_context_new(const gchar * parameter_string)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 */
g_option_context_free(GOptionContext * context)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 */
g_option_context_set_help_enabled(GOptionContext * context,gboolean help_enabled)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
g_option_context_get_help_enabled(GOptionContext * context)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
g_option_context_set_ignore_unknown_options(GOptionContext * context,gboolean ignore_unknown)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
g_option_context_get_ignore_unknown_options(GOptionContext * context)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
g_option_context_add_group(GOptionContext * context,GOptionGroup * group)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
g_option_context_set_main_group(GOptionContext * context,GOptionGroup * group)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 *
g_option_context_get_main_group(GOptionContext * context)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
g_option_context_add_main_entries(GOptionContext * context,const GOptionEntry * entries,const gchar * translation_domain)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
calculate_max_length(GOptionGroup * group)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
print_entry(GOptionGroup * group,gint max_length,const GOptionEntry * entry,GString * string)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
group_has_visible_entries(GOptionContext * context,GOptionGroup * group,gboolean main_entries)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
group_list_has_visible_entires(GOptionContext * context,GList * group_list,gboolean main_entries)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 *
g_option_context_get_help(GOptionContext * context,gboolean main_help,GOptionGroup * group)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
print_help(GOptionContext * context,gboolean main_help,GOptionGroup * group)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
parse_int(const gchar * arg_name,const gchar * arg,gint * result,GError ** error)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
parse_double(const gchar * arg_name,const gchar * arg,gdouble * result,GError ** error)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
parse_int64(const gchar * arg_name,const gchar * arg,gint64 * result,GError ** error)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 *
get_change(GOptionContext * context,GOptionArg arg_type,gpointer arg_data)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
add_pending_null(GOptionContext * context,gchar ** ptr,gchar * value)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
parse_arg(GOptionContext * context,GOptionGroup * group,GOptionEntry * entry,const gchar * value,const gchar * option_name,GError ** error)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
parse_short_option(GOptionContext * context,GOptionGroup * group,gint idx,gint * new_idx,gchar arg,gint * argc,gchar *** argv,GError ** error,gboolean * parsed)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
parse_long_option(GOptionContext * context,GOptionGroup * group,gint * idx,gchar * arg,gboolean aliased,gint * argc,gchar *** argv,GError ** error,gboolean * parsed)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
parse_remaining_arg(GOptionContext * context,GOptionGroup * group,gint * idx,gint * argc,gchar *** argv,GError ** error,gboolean * parsed)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
free_changes_list(GOptionContext * context,gboolean revert)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
free_pending_nulls(GOptionContext * context,gboolean perform_nulls)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
g_option_context_parse(GOptionContext * context,gint * argc,gchar *** argv,GError ** error)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 *
g_option_group_new(const gchar * name,const gchar * description,const gchar * help_description,gpointer user_data,GDestroyNotify destroy)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
g_option_group_free(GOptionGroup * group)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
g_option_group_add_entries(GOptionGroup * group,const GOptionEntry * entries)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
g_option_group_set_parse_hooks(GOptionGroup * group,GOptionParseFunc pre_parse_func,GOptionParseFunc post_parse_func)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
g_option_group_set_error_hook(GOptionGroup * group,GOptionErrorFunc error_func)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
g_option_group_set_translate_func(GOptionGroup * group,GTranslateFunc func,gpointer data,GDestroyNotify destroy_notify)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 *
dgettext_swapped(const gchar * msgid,const gchar * domainname)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
g_option_group_set_translation_domain(GOptionGroup * group,const gchar * domain)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
g_option_context_set_translate_func(GOptionContext * context,GTranslateFunc func,gpointer data,GDestroyNotify destroy_notify)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
g_option_context_set_translation_domain(GOptionContext * context,const gchar * domain)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
g_option_context_set_summary(GOptionContext * context,const gchar * summary)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 *
g_option_context_get_summary(GOptionContext * context)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
g_option_context_set_description(GOptionContext * context,const gchar * description)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 *
g_option_context_get_description(GOptionContext * context)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