Merge branch 'doc-types' into 'master'
[glib.git] / glib / goption.c
blobd68ab5fe2829532146527152acdcee72e470c3c5
1 /* goption.c - Option parser
3 * Copyright (C) 1999, 2003 Red Hat Software
4 * Copyright (C) 2004 Anders Carlsson <andersca@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
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 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this library; if not, see <http://www.gnu.org/licenses/>.
20 /**
21 * SECTION:option
22 * @Short_description: parses commandline options
23 * @Title: Commandline option parser
25 * The GOption commandline parser is intended to be a simpler replacement
26 * for the popt library. It supports short and long commandline options,
27 * as shown in the following example:
29 * `testtreemodel -r 1 --max-size 20 --rand --display=:1.0 -vb -- file1 file2`
31 * The example demonstrates a number of features of the GOption
32 * commandline parser:
34 * - Options can be single letters, prefixed by a single dash.
36 * - Multiple short options can be grouped behind a single dash.
38 * - Long options are prefixed by two consecutive dashes.
40 * - Options can have an extra argument, which can be a number, a string or
41 * a filename. For long options, the extra argument can be appended with
42 * an equals sign after the option name, which is useful if the extra
43 * argument starts with a dash, which would otherwise cause it to be
44 * interpreted as another option.
46 * - Non-option arguments are returned to the application as rest arguments.
48 * - An argument consisting solely of two dashes turns off further parsing,
49 * any remaining arguments (even those starting with a dash) are returned
50 * to the application as rest arguments.
52 * Another important feature of GOption is that it can automatically
53 * generate nicely formatted help output. Unless it is explicitly turned
54 * off with g_option_context_set_help_enabled(), GOption will recognize
55 * the `--help`, `-?`, `--help-all` and `--help-groupname` options
56 * (where `groupname` is the name of a #GOptionGroup) and write a text
57 * similar to the one shown in the following example to stdout.
59 * |[
60 * Usage:
61 * testtreemodel [OPTION...] - test tree model performance
63 * Help Options:
64 * -h, --help Show help options
65 * --help-all Show all help options
66 * --help-gtk Show GTK+ Options
68 * Application Options:
69 * -r, --repeats=N Average over N repetitions
70 * -m, --max-size=M Test up to 2^M items
71 * --display=DISPLAY X display to use
72 * -v, --verbose Be verbose
73 * -b, --beep Beep when done
74 * --rand Randomize the data
75 * ]|
77 * GOption groups options in #GOptionGroups, which makes it easy to
78 * incorporate options from multiple sources. The intended use for this is
79 * to let applications collect option groups from the libraries it uses,
80 * add them to their #GOptionContext, and parse all options by a single call
81 * to g_option_context_parse(). See gtk_get_option_group() for an example.
83 * If an option is declared to be of type string or filename, GOption takes
84 * care of converting it to the right encoding; strings are returned in
85 * UTF-8, filenames are returned in the GLib filename encoding. Note that
86 * this only works if setlocale() has been called before
87 * g_option_context_parse().
89 * Here is a complete example of setting up GOption to parse the example
90 * commandline above and produce the example help output.
91 * |[<!-- language="C" -->
92 * static gint repeats = 2;
93 * static gint max_size = 8;
94 * static gboolean verbose = FALSE;
95 * static gboolean beep = FALSE;
96 * static gboolean randomize = FALSE;
98 * static GOptionEntry entries[] =
99 * {
100 * { "repeats", 'r', 0, G_OPTION_ARG_INT, &repeats, "Average over N repetitions", "N" },
101 * { "max-size", 'm', 0, G_OPTION_ARG_INT, &max_size, "Test up to 2^M items", "M" },
102 * { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL },
103 * { "beep", 'b', 0, G_OPTION_ARG_NONE, &beep, "Beep when done", NULL },
104 * { "rand", 0, 0, G_OPTION_ARG_NONE, &randomize, "Randomize the data", NULL },
105 * { NULL }
106 * };
108 * int
109 * main (int argc, char *argv[])
111 * GError *error = NULL;
112 * GOptionContext *context;
114 * context = g_option_context_new ("- test tree model performance");
115 * g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
116 * g_option_context_add_group (context, gtk_get_option_group (TRUE));
117 * if (!g_option_context_parse (context, &argc, &argv, &error))
119 * g_print ("option parsing failed: %s\n", error->message);
120 * exit (1);
123 * ...
126 * ]|
128 * On UNIX systems, the argv that is passed to main() has no particular
129 * encoding, even to the extent that different parts of it may have
130 * different encodings. In general, normal arguments and flags will be
131 * in the current locale and filenames should be considered to be opaque
132 * byte strings. Proper use of %G_OPTION_ARG_FILENAME vs
133 * %G_OPTION_ARG_STRING is therefore important.
135 * Note that on Windows, filenames do have an encoding, but using
136 * #GOptionContext with the argv as passed to main() will result in a
137 * program that can only accept commandline arguments with characters
138 * from the system codepage. This can cause problems when attempting to
139 * deal with filenames containing Unicode characters that fall outside
140 * of the codepage.
142 * A solution to this is to use g_win32_get_command_line() and
143 * g_option_context_parse_strv() which will properly handle full Unicode
144 * filenames. If you are using #GApplication, this is done
145 * automatically for you.
147 * The following example shows how you can use #GOptionContext directly
148 * in order to correctly deal with Unicode filenames on Windows:
150 * |[<!-- language="C" -->
151 * int
152 * main (int argc, char **argv)
154 * GError *error = NULL;
155 * GOptionContext *context;
156 * gchar **args;
158 * #ifdef G_OS_WIN32
159 * args = g_win32_get_command_line ();
160 * #else
161 * args = g_strdupv (argv);
162 * #endif
164 * // set up context
166 * if (!g_option_context_parse_strv (context, &args, &error))
168 * // error happened
171 * ...
173 * g_strfreev (args);
175 * ...
177 * ]|
180 #include "config.h"
182 #include <string.h>
183 #include <stdlib.h>
184 #include <stdio.h>
185 #include <errno.h>
187 #if defined __OpenBSD__
188 #include <unistd.h>
189 #include <sys/sysctl.h>
190 #endif
192 #include "goption.h"
194 #include "gprintf.h"
195 #include "glibintl.h"
197 #define TRANSLATE(group, str) (((group)->translate_func ? (* (group)->translate_func) ((str), (group)->translate_data) : (str)))
199 #define NO_ARG(entry) ((entry)->arg == G_OPTION_ARG_NONE || \
200 ((entry)->arg == G_OPTION_ARG_CALLBACK && \
201 ((entry)->flags & G_OPTION_FLAG_NO_ARG)))
203 #define OPTIONAL_ARG(entry) ((entry)->arg == G_OPTION_ARG_CALLBACK && \
204 (entry)->flags & G_OPTION_FLAG_OPTIONAL_ARG)
206 typedef struct
208 GOptionArg arg_type;
209 gpointer arg_data;
210 union
212 gboolean bool;
213 gint integer;
214 gchar *str;
215 gchar **array;
216 gdouble dbl;
217 gint64 int64;
218 } prev;
219 union
221 gchar *str;
222 struct
224 gint len;
225 gchar **data;
226 } array;
227 } allocated;
228 } Change;
230 typedef struct
232 gchar **ptr;
233 gchar *value;
234 } PendingNull;
236 struct _GOptionContext
238 GList *groups;
240 gchar *parameter_string;
241 gchar *summary;
242 gchar *description;
244 GTranslateFunc translate_func;
245 GDestroyNotify translate_notify;
246 gpointer translate_data;
248 guint help_enabled : 1;
249 guint ignore_unknown : 1;
250 guint strv_mode : 1;
251 guint strict_posix : 1;
253 GOptionGroup *main_group;
255 /* We keep a list of change so we can revert them */
256 GList *changes;
258 /* We also keep track of all argv elements
259 * that should be NULLed or modified.
261 GList *pending_nulls;
264 struct _GOptionGroup
266 gchar *name;
267 gchar *description;
268 gchar *help_description;
270 gint ref_count;
272 GDestroyNotify destroy_notify;
273 gpointer user_data;
275 GTranslateFunc translate_func;
276 GDestroyNotify translate_notify;
277 gpointer translate_data;
279 GOptionEntry *entries;
280 gint n_entries;
282 GOptionParseFunc pre_parse_func;
283 GOptionParseFunc post_parse_func;
284 GOptionErrorFunc error_func;
287 static void free_changes_list (GOptionContext *context,
288 gboolean revert);
289 static void free_pending_nulls (GOptionContext *context,
290 gboolean perform_nulls);
293 static int
294 _g_unichar_get_width (gunichar c)
296 if (G_UNLIKELY (g_unichar_iszerowidth (c)))
297 return 0;
299 /* we ignore the fact that we should call g_unichar_iswide_cjk() under
300 * some locales (legacy East Asian ones) */
301 if (g_unichar_iswide (c))
302 return 2;
304 return 1;
307 static glong
308 _g_utf8_strwidth (const gchar *p)
310 glong len = 0;
311 g_return_val_if_fail (p != NULL, 0);
313 while (*p)
315 len += _g_unichar_get_width (g_utf8_get_char (p));
316 p = g_utf8_next_char (p);
319 return len;
322 G_DEFINE_QUARK (g-option-context-error-quark, g_option_error)
325 * g_option_context_new:
326 * @parameter_string: (nullable): a string which is displayed in
327 * the first line of `--help` output, after the usage summary
328 * `programname [OPTION...]`
330 * Creates a new option context.
332 * The @parameter_string can serve multiple purposes. It can be used
333 * to add descriptions for "rest" arguments, which are not parsed by
334 * the #GOptionContext, typically something like "FILES" or
335 * "FILE1 FILE2...". If you are using #G_OPTION_REMAINING for
336 * collecting "rest" arguments, GLib handles this automatically by
337 * using the @arg_description of the corresponding #GOptionEntry in
338 * the usage summary.
340 * Another usage is to give a short summary of the program
341 * functionality, like " - frob the strings", which will be displayed
342 * in the same line as the usage. For a longer description of the
343 * program functionality that should be displayed as a paragraph
344 * below the usage line, use g_option_context_set_summary().
346 * Note that the @parameter_string is translated using the
347 * function set with g_option_context_set_translate_func(), so
348 * it should normally be passed untranslated.
350 * Returns: a newly created #GOptionContext, which must be
351 * freed with g_option_context_free() after use.
353 * Since: 2.6
355 GOptionContext *
356 g_option_context_new (const gchar *parameter_string)
359 GOptionContext *context;
361 context = g_new0 (GOptionContext, 1);
363 context->parameter_string = g_strdup (parameter_string);
364 context->strict_posix = FALSE;
365 context->help_enabled = TRUE;
366 context->ignore_unknown = FALSE;
368 return context;
372 * g_option_context_free:
373 * @context: a #GOptionContext
375 * Frees context and all the groups which have been
376 * added to it.
378 * Please note that parsed arguments need to be freed separately (see
379 * #GOptionEntry).
381 * Since: 2.6
383 void g_option_context_free (GOptionContext *context)
385 g_return_if_fail (context != NULL);
387 g_list_free_full (context->groups, (GDestroyNotify) g_option_group_unref);
389 if (context->main_group)
390 g_option_group_unref (context->main_group);
392 free_changes_list (context, FALSE);
393 free_pending_nulls (context, FALSE);
395 g_free (context->parameter_string);
396 g_free (context->summary);
397 g_free (context->description);
399 if (context->translate_notify)
400 (* context->translate_notify) (context->translate_data);
402 g_free (context);
407 * g_option_context_set_help_enabled:
408 * @context: a #GOptionContext
409 * @help_enabled: %TRUE to enable `--help`, %FALSE to disable it
411 * Enables or disables automatic generation of `--help` output.
412 * By default, g_option_context_parse() recognizes `--help`, `-h`,
413 * `-?`, `--help-all` and `--help-groupname` and creates suitable
414 * output to stdout.
416 * Since: 2.6
418 void g_option_context_set_help_enabled (GOptionContext *context,
419 gboolean help_enabled)
422 g_return_if_fail (context != NULL);
424 context->help_enabled = help_enabled;
428 * g_option_context_get_help_enabled:
429 * @context: a #GOptionContext
431 * Returns whether automatic `--help` generation
432 * is turned on for @context. See g_option_context_set_help_enabled().
434 * Returns: %TRUE if automatic help generation is turned on.
436 * Since: 2.6
438 gboolean
439 g_option_context_get_help_enabled (GOptionContext *context)
441 g_return_val_if_fail (context != NULL, FALSE);
443 return context->help_enabled;
447 * g_option_context_set_ignore_unknown_options:
448 * @context: a #GOptionContext
449 * @ignore_unknown: %TRUE to ignore unknown options, %FALSE to produce
450 * an error when unknown options are met
452 * Sets whether to ignore unknown options or not. If an argument is
453 * ignored, it is left in the @argv array after parsing. By default,
454 * g_option_context_parse() treats unknown options as error.
456 * This setting does not affect non-option arguments (i.e. arguments
457 * which don't start with a dash). But note that GOption cannot reliably
458 * determine whether a non-option belongs to a preceding unknown option.
460 * Since: 2.6
462 void
463 g_option_context_set_ignore_unknown_options (GOptionContext *context,
464 gboolean ignore_unknown)
466 g_return_if_fail (context != NULL);
468 context->ignore_unknown = ignore_unknown;
472 * g_option_context_get_ignore_unknown_options:
473 * @context: a #GOptionContext
475 * Returns whether unknown options are ignored or not. See
476 * g_option_context_set_ignore_unknown_options().
478 * Returns: %TRUE if unknown options are ignored.
480 * Since: 2.6
482 gboolean
483 g_option_context_get_ignore_unknown_options (GOptionContext *context)
485 g_return_val_if_fail (context != NULL, FALSE);
487 return context->ignore_unknown;
491 * g_option_context_set_strict_posix:
492 * @context: a #GOptionContext
493 * @strict_posix: the new value
495 * Sets strict POSIX mode.
497 * By default, this mode is disabled.
499 * In strict POSIX mode, the first non-argument parameter encountered
500 * (eg: filename) terminates argument processing. Remaining arguments
501 * are treated as non-options and are not attempted to be parsed.
503 * If strict POSIX mode is disabled then parsing is done in the GNU way
504 * where option arguments can be freely mixed with non-options.
506 * As an example, consider "ls foo -l". With GNU style parsing, this
507 * will list "foo" in long mode. In strict POSIX style, this will list
508 * the files named "foo" and "-l".
510 * It may be useful to force strict POSIX mode when creating "verb
511 * style" command line tools. For example, the "gsettings" command line
512 * tool supports the global option "--schemadir" as well as many
513 * subcommands ("get", "set", etc.) which each have their own set of
514 * arguments. Using strict POSIX mode will allow parsing the global
515 * options up to the verb name while leaving the remaining options to be
516 * parsed by the relevant subcommand (which can be determined by
517 * examining the verb name, which should be present in argv[1] after
518 * parsing).
520 * Since: 2.44
522 void
523 g_option_context_set_strict_posix (GOptionContext *context,
524 gboolean strict_posix)
526 g_return_if_fail (context != NULL);
528 context->strict_posix = strict_posix;
532 * g_option_context_get_strict_posix:
533 * @context: a #GOptionContext
535 * Returns whether strict POSIX code is enabled.
537 * See g_option_context_set_strict_posix() for more information.
539 * Returns: %TRUE if strict POSIX is enabled, %FALSE otherwise.
541 * Since: 2.44
543 gboolean
544 g_option_context_get_strict_posix (GOptionContext *context)
546 g_return_val_if_fail (context != NULL, FALSE);
548 return context->strict_posix;
552 * g_option_context_add_group:
553 * @context: a #GOptionContext
554 * @group: (transfer full): the group to add
556 * Adds a #GOptionGroup to the @context, so that parsing with @context
557 * will recognize the options in the group. Note that this will take
558 * ownership of the @group and thus the @group should not be freed.
560 * Since: 2.6
562 void
563 g_option_context_add_group (GOptionContext *context,
564 GOptionGroup *group)
566 GList *list;
568 g_return_if_fail (context != NULL);
569 g_return_if_fail (group != NULL);
570 g_return_if_fail (group->name != NULL);
571 g_return_if_fail (group->description != NULL);
572 g_return_if_fail (group->help_description != NULL);
574 for (list = context->groups; list; list = list->next)
576 GOptionGroup *g = (GOptionGroup *)list->data;
578 if ((group->name == NULL && g->name == NULL) ||
579 (group->name && g->name && strcmp (group->name, g->name) == 0))
580 g_warning ("A group named \"%s\" is already part of this GOptionContext",
581 group->name);
584 context->groups = g_list_append (context->groups, group);
588 * g_option_context_set_main_group:
589 * @context: a #GOptionContext
590 * @group: (transfer full): the group to set as main group
592 * Sets a #GOptionGroup as main group of the @context.
593 * This has the same effect as calling g_option_context_add_group(),
594 * the only difference is that the options in the main group are
595 * treated differently when generating `--help` output.
597 * Since: 2.6
599 void
600 g_option_context_set_main_group (GOptionContext *context,
601 GOptionGroup *group)
603 g_return_if_fail (context != NULL);
604 g_return_if_fail (group != NULL);
606 if (context->main_group)
608 g_warning ("This GOptionContext already has a main group");
610 return;
613 context->main_group = group;
617 * g_option_context_get_main_group:
618 * @context: a #GOptionContext
620 * Returns a pointer to the main group of @context.
622 * Returns: (transfer none): the main group of @context, or %NULL if
623 * @context doesn't have a main group. Note that group belongs to
624 * @context and should not be modified or freed.
626 * Since: 2.6
628 GOptionGroup *
629 g_option_context_get_main_group (GOptionContext *context)
631 g_return_val_if_fail (context != NULL, NULL);
633 return context->main_group;
637 * g_option_context_add_main_entries:
638 * @context: a #GOptionContext
639 * @entries: a %NULL-terminated array of #GOptionEntrys
640 * @translation_domain: (nullable): a translation domain to use for translating
641 * the `--help` output for the options in @entries
642 * with gettext(), or %NULL
644 * A convenience function which creates a main group if it doesn't
645 * exist, adds the @entries to it and sets the translation domain.
647 * Since: 2.6
649 void
650 g_option_context_add_main_entries (GOptionContext *context,
651 const GOptionEntry *entries,
652 const gchar *translation_domain)
654 g_return_if_fail (entries != NULL);
656 if (!context->main_group)
657 context->main_group = g_option_group_new (NULL, NULL, NULL, NULL, NULL);
659 g_option_group_add_entries (context->main_group, entries);
660 g_option_group_set_translation_domain (context->main_group, translation_domain);
663 static gint
664 calculate_max_length (GOptionGroup *group,
665 GHashTable *aliases)
667 GOptionEntry *entry;
668 gint i, len, max_length;
669 const gchar *long_name;
671 max_length = 0;
673 for (i = 0; i < group->n_entries; i++)
675 entry = &group->entries[i];
677 if (entry->flags & G_OPTION_FLAG_HIDDEN)
678 continue;
680 long_name = g_hash_table_lookup (aliases, &entry->long_name);
681 if (!long_name)
682 long_name = entry->long_name;
683 len = _g_utf8_strwidth (long_name);
685 if (entry->short_name)
686 len += 4;
688 if (!NO_ARG (entry) && entry->arg_description)
689 len += 1 + _g_utf8_strwidth (TRANSLATE (group, entry->arg_description));
691 max_length = MAX (max_length, len);
694 return max_length;
697 static void
698 print_entry (GOptionGroup *group,
699 gint max_length,
700 const GOptionEntry *entry,
701 GString *string,
702 GHashTable *aliases)
704 GString *str;
705 const gchar *long_name;
707 if (entry->flags & G_OPTION_FLAG_HIDDEN)
708 return;
710 if (entry->long_name[0] == 0)
711 return;
713 long_name = g_hash_table_lookup (aliases, &entry->long_name);
714 if (!long_name)
715 long_name = entry->long_name;
717 str = g_string_new (NULL);
719 if (entry->short_name)
720 g_string_append_printf (str, " -%c, --%s", entry->short_name, long_name);
721 else
722 g_string_append_printf (str, " --%s", long_name);
724 if (entry->arg_description)
725 g_string_append_printf (str, "=%s", TRANSLATE (group, entry->arg_description));
727 g_string_append_printf (string, "%s%*s %s\n", str->str,
728 (int) (max_length + 4 - _g_utf8_strwidth (str->str)), "",
729 entry->description ? TRANSLATE (group, entry->description) : "");
730 g_string_free (str, TRUE);
733 static gboolean
734 group_has_visible_entries (GOptionContext *context,
735 GOptionGroup *group,
736 gboolean main_entries)
738 GOptionFlags reject_filter = G_OPTION_FLAG_HIDDEN;
739 GOptionEntry *entry;
740 gint i, l;
741 gboolean main_group = group == context->main_group;
743 if (!main_entries)
744 reject_filter |= G_OPTION_FLAG_IN_MAIN;
746 for (i = 0, l = (group ? group->n_entries : 0); i < l; i++)
748 entry = &group->entries[i];
750 if (main_entries && !main_group && !(entry->flags & G_OPTION_FLAG_IN_MAIN))
751 continue;
752 if (entry->long_name[0] == 0) /* ignore rest entry */
753 continue;
754 if (!(entry->flags & reject_filter))
755 return TRUE;
758 return FALSE;
761 static gboolean
762 group_list_has_visible_entries (GOptionContext *context,
763 GList *group_list,
764 gboolean main_entries)
766 while (group_list)
768 if (group_has_visible_entries (context, group_list->data, main_entries))
769 return TRUE;
771 group_list = group_list->next;
774 return FALSE;
777 static gboolean
778 context_has_h_entry (GOptionContext *context)
780 gsize i;
781 GList *list;
783 if (context->main_group)
785 for (i = 0; i < context->main_group->n_entries; i++)
787 if (context->main_group->entries[i].short_name == 'h')
788 return TRUE;
792 for (list = context->groups; list != NULL; list = g_list_next (list))
794 GOptionGroup *group;
796 group = (GOptionGroup*)list->data;
797 for (i = 0; i < group->n_entries; i++)
799 if (group->entries[i].short_name == 'h')
800 return TRUE;
803 return FALSE;
807 * g_option_context_get_help:
808 * @context: a #GOptionContext
809 * @main_help: if %TRUE, only include the main group
810 * @group: (nullable): the #GOptionGroup to create help for, or %NULL
812 * Returns a formatted, translated help text for the given context.
813 * To obtain the text produced by `--help`, call
814 * `g_option_context_get_help (context, TRUE, NULL)`.
815 * To obtain the text produced by `--help-all`, call
816 * `g_option_context_get_help (context, FALSE, NULL)`.
817 * To obtain the help text for an option group, call
818 * `g_option_context_get_help (context, FALSE, group)`.
820 * Returns: A newly allocated string containing the help text
822 * Since: 2.14
824 gchar *
825 g_option_context_get_help (GOptionContext *context,
826 gboolean main_help,
827 GOptionGroup *group)
829 GList *list;
830 gint max_length = 0, len;
831 gint i;
832 GOptionEntry *entry;
833 GHashTable *shadow_map;
834 GHashTable *aliases;
835 gboolean seen[256];
836 const gchar *rest_description;
837 GString *string;
838 guchar token;
840 string = g_string_sized_new (1024);
842 rest_description = NULL;
843 if (context->main_group)
846 for (i = 0; i < context->main_group->n_entries; i++)
848 entry = &context->main_group->entries[i];
849 if (entry->long_name[0] == 0)
851 rest_description = TRANSLATE (context->main_group, entry->arg_description);
852 break;
857 g_string_append_printf (string, "%s\n %s", _("Usage:"), g_get_prgname ());
858 if (context->help_enabled ||
859 (context->main_group && context->main_group->n_entries > 0) ||
860 context->groups != NULL)
861 g_string_append_printf (string, " %s", _("[OPTION…]"));
863 if (rest_description)
865 g_string_append (string, " ");
866 g_string_append (string, rest_description);
869 if (context->parameter_string)
871 g_string_append (string, " ");
872 g_string_append (string, TRANSLATE (context, context->parameter_string));
875 g_string_append (string, "\n\n");
877 if (context->summary)
879 g_string_append (string, TRANSLATE (context, context->summary));
880 g_string_append (string, "\n\n");
883 memset (seen, 0, sizeof (gboolean) * 256);
884 shadow_map = g_hash_table_new (g_str_hash, g_str_equal);
885 aliases = g_hash_table_new_full (NULL, NULL, NULL, g_free);
887 if (context->main_group)
889 for (i = 0; i < context->main_group->n_entries; i++)
891 entry = &context->main_group->entries[i];
892 g_hash_table_insert (shadow_map,
893 (gpointer)entry->long_name,
894 entry);
896 if (seen[(guchar)entry->short_name])
897 entry->short_name = 0;
898 else
899 seen[(guchar)entry->short_name] = TRUE;
903 list = context->groups;
904 while (list != NULL)
906 GOptionGroup *g = list->data;
907 for (i = 0; i < g->n_entries; i++)
909 entry = &g->entries[i];
910 if (g_hash_table_lookup (shadow_map, entry->long_name) &&
911 !(entry->flags & G_OPTION_FLAG_NOALIAS))
913 g_hash_table_insert (aliases, &entry->long_name,
914 g_strdup_printf ("%s-%s", g->name, entry->long_name));
916 else
917 g_hash_table_insert (shadow_map, (gpointer)entry->long_name, entry);
919 if (seen[(guchar)entry->short_name] &&
920 !(entry->flags & G_OPTION_FLAG_NOALIAS))
921 entry->short_name = 0;
922 else
923 seen[(guchar)entry->short_name] = TRUE;
925 list = list->next;
928 g_hash_table_destroy (shadow_map);
930 list = context->groups;
932 if (context->help_enabled)
934 max_length = _g_utf8_strwidth ("-?, --help");
936 if (list)
938 len = _g_utf8_strwidth ("--help-all");
939 max_length = MAX (max_length, len);
943 if (context->main_group)
945 len = calculate_max_length (context->main_group, aliases);
946 max_length = MAX (max_length, len);
949 while (list != NULL)
951 GOptionGroup *g = list->data;
953 if (context->help_enabled)
955 /* First, we check the --help-<groupname> options */
956 len = _g_utf8_strwidth ("--help-") + _g_utf8_strwidth (g->name);
957 max_length = MAX (max_length, len);
960 /* Then we go through the entries */
961 len = calculate_max_length (g, aliases);
962 max_length = MAX (max_length, len);
964 list = list->next;
967 /* Add a bit of padding */
968 max_length += 4;
970 if (!group && context->help_enabled)
972 list = context->groups;
974 token = context_has_h_entry (context) ? '?' : 'h';
976 g_string_append_printf (string, "%s\n -%c, --%-*s %s\n",
977 _("Help Options:"), token, max_length - 4, "help",
978 _("Show help options"));
980 /* We only want --help-all when there are groups */
981 if (list)
982 g_string_append_printf (string, " --%-*s %s\n",
983 max_length, "help-all",
984 _("Show all help options"));
986 while (list)
988 GOptionGroup *g = list->data;
990 if (group_has_visible_entries (context, g, FALSE))
991 g_string_append_printf (string, " --help-%-*s %s\n",
992 max_length - 5, g->name,
993 TRANSLATE (g, g->help_description));
995 list = list->next;
998 g_string_append (string, "\n");
1001 if (group)
1003 /* Print a certain group */
1005 if (group_has_visible_entries (context, group, FALSE))
1007 g_string_append (string, TRANSLATE (group, group->description));
1008 g_string_append (string, "\n");
1009 for (i = 0; i < group->n_entries; i++)
1010 print_entry (group, max_length, &group->entries[i], string, aliases);
1011 g_string_append (string, "\n");
1014 else if (!main_help)
1016 /* Print all groups */
1018 list = context->groups;
1020 while (list)
1022 GOptionGroup *g = list->data;
1024 if (group_has_visible_entries (context, g, FALSE))
1026 g_string_append (string, g->description);
1027 g_string_append (string, "\n");
1028 for (i = 0; i < g->n_entries; i++)
1029 if (!(g->entries[i].flags & G_OPTION_FLAG_IN_MAIN))
1030 print_entry (g, max_length, &g->entries[i], string, aliases);
1032 g_string_append (string, "\n");
1035 list = list->next;
1039 /* Print application options if --help or --help-all has been specified */
1040 if ((main_help || !group) &&
1041 (group_has_visible_entries (context, context->main_group, TRUE) ||
1042 group_list_has_visible_entries (context, context->groups, TRUE)))
1044 list = context->groups;
1046 if (context->help_enabled || list)
1047 g_string_append (string, _("Application Options:"));
1048 else
1049 g_string_append (string, _("Options:"));
1050 g_string_append (string, "\n");
1051 if (context->main_group)
1052 for (i = 0; i < context->main_group->n_entries; i++)
1053 print_entry (context->main_group, max_length,
1054 &context->main_group->entries[i], string, aliases);
1056 while (list != NULL)
1058 GOptionGroup *g = list->data;
1060 /* Print main entries from other groups */
1061 for (i = 0; i < g->n_entries; i++)
1062 if (g->entries[i].flags & G_OPTION_FLAG_IN_MAIN)
1063 print_entry (g, max_length, &g->entries[i], string, aliases);
1065 list = list->next;
1068 g_string_append (string, "\n");
1071 if (context->description)
1073 g_string_append (string, TRANSLATE (context, context->description));
1074 g_string_append (string, "\n");
1077 g_hash_table_destroy (aliases);
1079 return g_string_free (string, FALSE);
1082 G_GNUC_NORETURN
1083 static void
1084 print_help (GOptionContext *context,
1085 gboolean main_help,
1086 GOptionGroup *group)
1088 gchar *help;
1090 help = g_option_context_get_help (context, main_help, group);
1091 g_print ("%s", help);
1092 g_free (help);
1094 exit (0);
1097 static gboolean
1098 parse_int (const gchar *arg_name,
1099 const gchar *arg,
1100 gint *result,
1101 GError **error)
1103 gchar *end;
1104 glong tmp;
1106 errno = 0;
1107 tmp = strtol (arg, &end, 0);
1109 if (*arg == '\0' || *end != '\0')
1111 g_set_error (error,
1112 G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1113 _("Cannot parse integer value “%s” for %s"),
1114 arg, arg_name);
1115 return FALSE;
1118 *result = tmp;
1119 if (*result != tmp || errno == ERANGE)
1121 g_set_error (error,
1122 G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1123 _("Integer value “%s” for %s out of range"),
1124 arg, arg_name);
1125 return FALSE;
1128 return TRUE;
1132 static gboolean
1133 parse_double (const gchar *arg_name,
1134 const gchar *arg,
1135 gdouble *result,
1136 GError **error)
1138 gchar *end;
1139 gdouble tmp;
1141 errno = 0;
1142 tmp = g_strtod (arg, &end);
1144 if (*arg == '\0' || *end != '\0')
1146 g_set_error (error,
1147 G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1148 _("Cannot parse double value “%s” for %s"),
1149 arg, arg_name);
1150 return FALSE;
1152 if (errno == ERANGE)
1154 g_set_error (error,
1155 G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1156 _("Double value “%s” for %s out of range"),
1157 arg, arg_name);
1158 return FALSE;
1161 *result = tmp;
1163 return TRUE;
1167 static gboolean
1168 parse_int64 (const gchar *arg_name,
1169 const gchar *arg,
1170 gint64 *result,
1171 GError **error)
1173 gchar *end;
1174 gint64 tmp;
1176 errno = 0;
1177 tmp = g_ascii_strtoll (arg, &end, 0);
1179 if (*arg == '\0' || *end != '\0')
1181 g_set_error (error,
1182 G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1183 _("Cannot parse integer value “%s” for %s"),
1184 arg, arg_name);
1185 return FALSE;
1187 if (errno == ERANGE)
1189 g_set_error (error,
1190 G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1191 _("Integer value “%s” for %s out of range"),
1192 arg, arg_name);
1193 return FALSE;
1196 *result = tmp;
1198 return TRUE;
1202 static Change *
1203 get_change (GOptionContext *context,
1204 GOptionArg arg_type,
1205 gpointer arg_data)
1207 GList *list;
1208 Change *change = NULL;
1210 for (list = context->changes; list != NULL; list = list->next)
1212 change = list->data;
1214 if (change->arg_data == arg_data)
1215 goto found;
1218 change = g_new0 (Change, 1);
1219 change->arg_type = arg_type;
1220 change->arg_data = arg_data;
1222 context->changes = g_list_prepend (context->changes, change);
1224 found:
1226 return change;
1229 static void
1230 add_pending_null (GOptionContext *context,
1231 gchar **ptr,
1232 gchar *value)
1234 PendingNull *n;
1236 n = g_new0 (PendingNull, 1);
1237 n->ptr = ptr;
1238 n->value = value;
1240 context->pending_nulls = g_list_prepend (context->pending_nulls, n);
1243 static gboolean
1244 parse_arg (GOptionContext *context,
1245 GOptionGroup *group,
1246 GOptionEntry *entry,
1247 const gchar *value,
1248 const gchar *option_name,
1249 GError **error)
1252 Change *change;
1254 g_assert (value || OPTIONAL_ARG (entry) || NO_ARG (entry));
1256 switch (entry->arg)
1258 case G_OPTION_ARG_NONE:
1260 (void) get_change (context, G_OPTION_ARG_NONE,
1261 entry->arg_data);
1263 *(gboolean *)entry->arg_data = !(entry->flags & G_OPTION_FLAG_REVERSE);
1264 break;
1266 case G_OPTION_ARG_STRING:
1268 gchar *data;
1270 #ifdef G_OS_WIN32
1271 if (!context->strv_mode)
1272 data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1273 else
1274 data = g_strdup (value);
1275 #else
1276 data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1277 #endif
1279 if (!data)
1280 return FALSE;
1282 change = get_change (context, G_OPTION_ARG_STRING,
1283 entry->arg_data);
1285 if (!change->allocated.str)
1286 change->prev.str = *(gchar **)entry->arg_data;
1287 else
1288 g_free (change->allocated.str);
1290 change->allocated.str = data;
1292 *(gchar **)entry->arg_data = data;
1293 break;
1295 case G_OPTION_ARG_STRING_ARRAY:
1297 gchar *data;
1299 #ifdef G_OS_WIN32
1300 if (!context->strv_mode)
1301 data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1302 else
1303 data = g_strdup (value);
1304 #else
1305 data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1306 #endif
1308 if (!data)
1309 return FALSE;
1311 change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
1312 entry->arg_data);
1314 if (change->allocated.array.len == 0)
1316 change->prev.array = *(gchar ***)entry->arg_data;
1317 change->allocated.array.data = g_new (gchar *, 2);
1319 else
1320 change->allocated.array.data =
1321 g_renew (gchar *, change->allocated.array.data,
1322 change->allocated.array.len + 2);
1324 change->allocated.array.data[change->allocated.array.len] = data;
1325 change->allocated.array.data[change->allocated.array.len + 1] = NULL;
1327 change->allocated.array.len ++;
1329 *(gchar ***)entry->arg_data = change->allocated.array.data;
1331 break;
1334 case G_OPTION_ARG_FILENAME:
1336 gchar *data;
1338 #ifdef G_OS_WIN32
1339 if (!context->strv_mode)
1340 data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1341 else
1342 data = g_strdup (value);
1344 if (!data)
1345 return FALSE;
1346 #else
1347 data = g_strdup (value);
1348 #endif
1349 change = get_change (context, G_OPTION_ARG_FILENAME,
1350 entry->arg_data);
1352 if (!change->allocated.str)
1353 change->prev.str = *(gchar **)entry->arg_data;
1354 else
1355 g_free (change->allocated.str);
1357 change->allocated.str = data;
1359 *(gchar **)entry->arg_data = data;
1360 break;
1363 case G_OPTION_ARG_FILENAME_ARRAY:
1365 gchar *data;
1367 #ifdef G_OS_WIN32
1368 if (!context->strv_mode)
1369 data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1370 else
1371 data = g_strdup (value);
1373 if (!data)
1374 return FALSE;
1375 #else
1376 data = g_strdup (value);
1377 #endif
1378 change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
1379 entry->arg_data);
1381 if (change->allocated.array.len == 0)
1383 change->prev.array = *(gchar ***)entry->arg_data;
1384 change->allocated.array.data = g_new (gchar *, 2);
1386 else
1387 change->allocated.array.data =
1388 g_renew (gchar *, change->allocated.array.data,
1389 change->allocated.array.len + 2);
1391 change->allocated.array.data[change->allocated.array.len] = data;
1392 change->allocated.array.data[change->allocated.array.len + 1] = NULL;
1394 change->allocated.array.len ++;
1396 *(gchar ***)entry->arg_data = change->allocated.array.data;
1398 break;
1401 case G_OPTION_ARG_INT:
1403 gint data;
1405 if (!parse_int (option_name, value,
1406 &data,
1407 error))
1408 return FALSE;
1410 change = get_change (context, G_OPTION_ARG_INT,
1411 entry->arg_data);
1412 change->prev.integer = *(gint *)entry->arg_data;
1413 *(gint *)entry->arg_data = data;
1414 break;
1416 case G_OPTION_ARG_CALLBACK:
1418 gchar *data;
1419 gboolean retval;
1421 if (!value && entry->flags & G_OPTION_FLAG_OPTIONAL_ARG)
1422 data = NULL;
1423 else if (entry->flags & G_OPTION_FLAG_NO_ARG)
1424 data = NULL;
1425 else if (entry->flags & G_OPTION_FLAG_FILENAME)
1427 #ifdef G_OS_WIN32
1428 if (!context->strv_mode)
1429 data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1430 else
1431 data = g_strdup (value);
1432 #else
1433 data = g_strdup (value);
1434 #endif
1436 else
1437 data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
1439 if (!(entry->flags & (G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG)) &&
1440 !data)
1441 return FALSE;
1443 retval = (* (GOptionArgFunc) entry->arg_data) (option_name, data, group->user_data, error);
1445 if (!retval && error != NULL && *error == NULL)
1446 g_set_error (error,
1447 G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
1448 _("Error parsing option %s"), option_name);
1450 g_free (data);
1452 return retval;
1454 break;
1456 case G_OPTION_ARG_DOUBLE:
1458 gdouble data;
1460 if (!parse_double (option_name, value,
1461 &data,
1462 error))
1464 return FALSE;
1467 change = get_change (context, G_OPTION_ARG_DOUBLE,
1468 entry->arg_data);
1469 change->prev.dbl = *(gdouble *)entry->arg_data;
1470 *(gdouble *)entry->arg_data = data;
1471 break;
1473 case G_OPTION_ARG_INT64:
1475 gint64 data;
1477 if (!parse_int64 (option_name, value,
1478 &data,
1479 error))
1481 return FALSE;
1484 change = get_change (context, G_OPTION_ARG_INT64,
1485 entry->arg_data);
1486 change->prev.int64 = *(gint64 *)entry->arg_data;
1487 *(gint64 *)entry->arg_data = data;
1488 break;
1490 default:
1491 g_assert_not_reached ();
1494 return TRUE;
1497 static gboolean
1498 parse_short_option (GOptionContext *context,
1499 GOptionGroup *group,
1500 gint idx,
1501 gint *new_idx,
1502 gchar arg,
1503 gint *argc,
1504 gchar ***argv,
1505 GError **error,
1506 gboolean *parsed)
1508 gint j;
1510 for (j = 0; j < group->n_entries; j++)
1512 if (arg == group->entries[j].short_name)
1514 gchar *option_name;
1515 gchar *value = NULL;
1517 option_name = g_strdup_printf ("-%c", group->entries[j].short_name);
1519 if (NO_ARG (&group->entries[j]))
1520 value = NULL;
1521 else
1523 if (*new_idx > idx)
1525 g_set_error (error,
1526 G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
1527 _("Error parsing option %s"), option_name);
1528 g_free (option_name);
1529 return FALSE;
1532 if (idx < *argc - 1)
1534 if (!OPTIONAL_ARG (&group->entries[j]))
1536 value = (*argv)[idx + 1];
1537 add_pending_null (context, &((*argv)[idx + 1]), NULL);
1538 *new_idx = idx + 1;
1540 else
1542 if ((*argv)[idx + 1][0] == '-')
1543 value = NULL;
1544 else
1546 value = (*argv)[idx + 1];
1547 add_pending_null (context, &((*argv)[idx + 1]), NULL);
1548 *new_idx = idx + 1;
1552 else if (idx >= *argc - 1 && OPTIONAL_ARG (&group->entries[j]))
1553 value = NULL;
1554 else
1556 g_set_error (error,
1557 G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1558 _("Missing argument for %s"), option_name);
1559 g_free (option_name);
1560 return FALSE;
1564 if (!parse_arg (context, group, &group->entries[j],
1565 value, option_name, error))
1567 g_free (option_name);
1568 return FALSE;
1571 g_free (option_name);
1572 *parsed = TRUE;
1576 return TRUE;
1579 static gboolean
1580 parse_long_option (GOptionContext *context,
1581 GOptionGroup *group,
1582 gint *idx,
1583 gchar *arg,
1584 gboolean aliased,
1585 gint *argc,
1586 gchar ***argv,
1587 GError **error,
1588 gboolean *parsed)
1590 gint j;
1592 for (j = 0; j < group->n_entries; j++)
1594 if (*idx >= *argc)
1595 return TRUE;
1597 if (aliased && (group->entries[j].flags & G_OPTION_FLAG_NOALIAS))
1598 continue;
1600 if (NO_ARG (&group->entries[j]) &&
1601 strcmp (arg, group->entries[j].long_name) == 0)
1603 gchar *option_name;
1604 gboolean retval;
1606 option_name = g_strconcat ("--", group->entries[j].long_name, NULL);
1607 retval = parse_arg (context, group, &group->entries[j],
1608 NULL, option_name, error);
1609 g_free (option_name);
1611 add_pending_null (context, &((*argv)[*idx]), NULL);
1612 *parsed = TRUE;
1614 return retval;
1616 else
1618 gint len = strlen (group->entries[j].long_name);
1620 if (strncmp (arg, group->entries[j].long_name, len) == 0 &&
1621 (arg[len] == '=' || arg[len] == 0))
1623 gchar *value = NULL;
1624 gchar *option_name;
1626 add_pending_null (context, &((*argv)[*idx]), NULL);
1627 option_name = g_strconcat ("--", group->entries[j].long_name, NULL);
1629 if (arg[len] == '=')
1630 value = arg + len + 1;
1631 else if (*idx < *argc - 1)
1633 if (!OPTIONAL_ARG (&group->entries[j]))
1635 value = (*argv)[*idx + 1];
1636 add_pending_null (context, &((*argv)[*idx + 1]), NULL);
1637 (*idx)++;
1639 else
1641 if ((*argv)[*idx + 1][0] == '-')
1643 gboolean retval;
1644 retval = parse_arg (context, group, &group->entries[j],
1645 NULL, option_name, error);
1646 *parsed = TRUE;
1647 g_free (option_name);
1648 return retval;
1650 else
1652 value = (*argv)[*idx + 1];
1653 add_pending_null (context, &((*argv)[*idx + 1]), NULL);
1654 (*idx)++;
1658 else if (*idx >= *argc - 1 && OPTIONAL_ARG (&group->entries[j]))
1660 gboolean retval;
1661 retval = parse_arg (context, group, &group->entries[j],
1662 NULL, option_name, error);
1663 *parsed = TRUE;
1664 g_free (option_name);
1665 return retval;
1667 else
1669 g_set_error (error,
1670 G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1671 _("Missing argument for %s"), option_name);
1672 g_free (option_name);
1673 return FALSE;
1676 if (!parse_arg (context, group, &group->entries[j],
1677 value, option_name, error))
1679 g_free (option_name);
1680 return FALSE;
1683 g_free (option_name);
1684 *parsed = TRUE;
1689 return TRUE;
1692 static gboolean
1693 parse_remaining_arg (GOptionContext *context,
1694 GOptionGroup *group,
1695 gint *idx,
1696 gint *argc,
1697 gchar ***argv,
1698 GError **error,
1699 gboolean *parsed)
1701 gint j;
1703 for (j = 0; j < group->n_entries; j++)
1705 if (*idx >= *argc)
1706 return TRUE;
1708 if (group->entries[j].long_name[0])
1709 continue;
1711 g_return_val_if_fail (group->entries[j].arg == G_OPTION_ARG_CALLBACK ||
1712 group->entries[j].arg == G_OPTION_ARG_STRING_ARRAY ||
1713 group->entries[j].arg == G_OPTION_ARG_FILENAME_ARRAY, FALSE);
1715 add_pending_null (context, &((*argv)[*idx]), NULL);
1717 if (!parse_arg (context, group, &group->entries[j], (*argv)[*idx], "", error))
1718 return FALSE;
1720 *parsed = TRUE;
1721 return TRUE;
1724 return TRUE;
1727 static void
1728 free_changes_list (GOptionContext *context,
1729 gboolean revert)
1731 GList *list;
1733 for (list = context->changes; list != NULL; list = list->next)
1735 Change *change = list->data;
1737 if (revert)
1739 switch (change->arg_type)
1741 case G_OPTION_ARG_NONE:
1742 *(gboolean *)change->arg_data = change->prev.bool;
1743 break;
1744 case G_OPTION_ARG_INT:
1745 *(gint *)change->arg_data = change->prev.integer;
1746 break;
1747 case G_OPTION_ARG_STRING:
1748 case G_OPTION_ARG_FILENAME:
1749 g_free (change->allocated.str);
1750 *(gchar **)change->arg_data = change->prev.str;
1751 break;
1752 case G_OPTION_ARG_STRING_ARRAY:
1753 case G_OPTION_ARG_FILENAME_ARRAY:
1754 g_strfreev (change->allocated.array.data);
1755 *(gchar ***)change->arg_data = change->prev.array;
1756 break;
1757 case G_OPTION_ARG_DOUBLE:
1758 *(gdouble *)change->arg_data = change->prev.dbl;
1759 break;
1760 case G_OPTION_ARG_INT64:
1761 *(gint64 *)change->arg_data = change->prev.int64;
1762 break;
1763 default:
1764 g_assert_not_reached ();
1768 g_free (change);
1771 g_list_free (context->changes);
1772 context->changes = NULL;
1775 static void
1776 free_pending_nulls (GOptionContext *context,
1777 gboolean perform_nulls)
1779 GList *list;
1781 for (list = context->pending_nulls; list != NULL; list = list->next)
1783 PendingNull *n = list->data;
1785 if (perform_nulls)
1787 if (n->value)
1789 /* Copy back the short options */
1790 *(n->ptr)[0] = '-';
1791 strcpy (*n->ptr + 1, n->value);
1793 else
1795 if (context->strv_mode)
1796 g_free (*n->ptr);
1798 *n->ptr = NULL;
1802 g_free (n->value);
1803 g_free (n);
1806 g_list_free (context->pending_nulls);
1807 context->pending_nulls = NULL;
1810 /* Use a platform-specific mechanism to look up the first argument to
1811 * the current process.
1812 * Note if you implement this for other platforms, also add it to
1813 * tests/option-argv0.c
1815 static char *
1816 platform_get_argv0 (void)
1818 #if defined __linux
1819 char *cmdline;
1820 char *base_arg0;
1821 gsize len;
1823 if (!g_file_get_contents ("/proc/self/cmdline",
1824 &cmdline,
1825 &len,
1826 NULL))
1827 return NULL;
1828 /* Sanity check for a NUL terminator. */
1829 if (!memchr (cmdline, 0, len))
1830 return NULL;
1831 /* We could just return cmdline, but I think it's better
1832 * to hold on to a smaller malloc block; the arguments
1833 * could be large.
1835 base_arg0 = g_path_get_basename (cmdline);
1836 g_free (cmdline);
1837 return base_arg0;
1838 #elif defined __OpenBSD__
1839 char **cmdline;
1840 char *base_arg0;
1841 gsize len;
1843 int mib[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
1845 if (sysctl (mib, G_N_ELEMENTS (mib), NULL, &len, NULL, 0) == -1)
1846 return NULL;
1848 cmdline = g_malloc0 (len);
1850 if (sysctl (mib, G_N_ELEMENTS (mib), cmdline, &len, NULL, 0) == -1)
1852 g_free (cmdline);
1853 return NULL;
1856 /* We could just return cmdline, but I think it's better
1857 * to hold on to a smaller malloc block; the arguments
1858 * could be large.
1860 base_arg0 = g_path_get_basename (*cmdline);
1861 g_free (cmdline);
1862 return base_arg0;
1863 #endif
1865 return NULL;
1869 * g_option_context_parse:
1870 * @context: a #GOptionContext
1871 * @argc: (inout) (optional): a pointer to the number of command line arguments
1872 * @argv: (inout) (array length=argc) (optional): a pointer to the array of command line arguments
1873 * @error: a return location for errors
1875 * Parses the command line arguments, recognizing options
1876 * which have been added to @context. A side-effect of
1877 * calling this function is that g_set_prgname() will be
1878 * called.
1880 * If the parsing is successful, any parsed arguments are
1881 * removed from the array and @argc and @argv are updated
1882 * accordingly. A '--' option is stripped from @argv
1883 * unless there are unparsed options before and after it,
1884 * or some of the options after it start with '-'. In case
1885 * of an error, @argc and @argv are left unmodified.
1887 * If automatic `--help` support is enabled
1888 * (see g_option_context_set_help_enabled()), and the
1889 * @argv array contains one of the recognized help options,
1890 * this function will produce help output to stdout and
1891 * call `exit (0)`.
1893 * Note that function depends on the [current locale][setlocale] for
1894 * automatic character set conversion of string and filename
1895 * arguments.
1897 * Returns: %TRUE if the parsing was successful,
1898 * %FALSE if an error occurred
1900 * Since: 2.6
1902 gboolean
1903 g_option_context_parse (GOptionContext *context,
1904 gint *argc,
1905 gchar ***argv,
1906 GError **error)
1908 gint i, j, k;
1909 GList *list;
1911 /* Set program name */
1912 if (!g_get_prgname())
1914 gchar *prgname;
1916 if (argc && argv && *argc)
1917 prgname = g_path_get_basename ((*argv)[0]);
1918 else
1919 prgname = platform_get_argv0 ();
1921 if (prgname)
1922 g_set_prgname (prgname);
1923 else
1924 g_set_prgname ("<unknown>");
1926 g_free (prgname);
1929 /* Call pre-parse hooks */
1930 list = context->groups;
1931 while (list)
1933 GOptionGroup *group = list->data;
1935 if (group->pre_parse_func)
1937 if (!(* group->pre_parse_func) (context, group,
1938 group->user_data, error))
1939 goto fail;
1942 list = list->next;
1945 if (context->main_group && context->main_group->pre_parse_func)
1947 if (!(* context->main_group->pre_parse_func) (context, context->main_group,
1948 context->main_group->user_data, error))
1949 goto fail;
1952 if (argc && argv)
1954 gboolean stop_parsing = FALSE;
1955 gboolean has_unknown = FALSE;
1956 gint separator_pos = 0;
1958 for (i = 1; i < *argc; i++)
1960 gchar *arg, *dash;
1961 gboolean parsed = FALSE;
1963 if ((*argv)[i][0] == '-' && (*argv)[i][1] != '\0' && !stop_parsing)
1965 if ((*argv)[i][1] == '-')
1967 /* -- option */
1969 arg = (*argv)[i] + 2;
1971 /* '--' terminates list of arguments */
1972 if (*arg == 0)
1974 separator_pos = i;
1975 stop_parsing = TRUE;
1976 continue;
1979 /* Handle help options */
1980 if (context->help_enabled)
1982 if (strcmp (arg, "help") == 0)
1983 print_help (context, TRUE, NULL);
1984 else if (strcmp (arg, "help-all") == 0)
1985 print_help (context, FALSE, NULL);
1986 else if (strncmp (arg, "help-", 5) == 0)
1988 list = context->groups;
1990 while (list)
1992 GOptionGroup *group = list->data;
1994 if (strcmp (arg + 5, group->name) == 0)
1995 print_help (context, FALSE, group);
1997 list = list->next;
2002 if (context->main_group &&
2003 !parse_long_option (context, context->main_group, &i, arg,
2004 FALSE, argc, argv, error, &parsed))
2005 goto fail;
2007 if (parsed)
2008 continue;
2010 /* Try the groups */
2011 list = context->groups;
2012 while (list)
2014 GOptionGroup *group = list->data;
2016 if (!parse_long_option (context, group, &i, arg,
2017 FALSE, argc, argv, error, &parsed))
2018 goto fail;
2020 if (parsed)
2021 break;
2023 list = list->next;
2026 if (parsed)
2027 continue;
2029 /* Now look for --<group>-<option> */
2030 dash = strchr (arg, '-');
2031 if (dash && arg < dash)
2033 /* Try the groups */
2034 list = context->groups;
2035 while (list)
2037 GOptionGroup *group = list->data;
2039 if (strncmp (group->name, arg, dash - arg) == 0)
2041 if (!parse_long_option (context, group, &i, dash + 1,
2042 TRUE, argc, argv, error, &parsed))
2043 goto fail;
2045 if (parsed)
2046 break;
2049 list = list->next;
2053 if (context->ignore_unknown)
2054 continue;
2056 else
2057 { /* short option */
2058 gint new_i = i, arg_length;
2059 gboolean *nulled_out = NULL;
2060 gboolean has_h_entry = context_has_h_entry (context);
2061 arg = (*argv)[i] + 1;
2062 arg_length = strlen (arg);
2063 nulled_out = g_newa (gboolean, arg_length);
2064 memset (nulled_out, 0, arg_length * sizeof (gboolean));
2065 for (j = 0; j < arg_length; j++)
2067 if (context->help_enabled && (arg[j] == '?' ||
2068 (arg[j] == 'h' && !has_h_entry)))
2069 print_help (context, TRUE, NULL);
2070 parsed = FALSE;
2071 if (context->main_group &&
2072 !parse_short_option (context, context->main_group,
2073 i, &new_i, arg[j],
2074 argc, argv, error, &parsed))
2075 goto fail;
2076 if (!parsed)
2078 /* Try the groups */
2079 list = context->groups;
2080 while (list)
2082 GOptionGroup *group = list->data;
2083 if (!parse_short_option (context, group, i, &new_i, arg[j],
2084 argc, argv, error, &parsed))
2085 goto fail;
2086 if (parsed)
2087 break;
2088 list = list->next;
2092 if (context->ignore_unknown && parsed)
2093 nulled_out[j] = TRUE;
2094 else if (context->ignore_unknown)
2095 continue;
2096 else if (!parsed)
2097 break;
2098 /* !context->ignore_unknown && parsed */
2100 if (context->ignore_unknown)
2102 gchar *new_arg = NULL;
2103 gint arg_index = 0;
2104 for (j = 0; j < arg_length; j++)
2106 if (!nulled_out[j])
2108 if (!new_arg)
2109 new_arg = g_malloc (arg_length + 1);
2110 new_arg[arg_index++] = arg[j];
2113 if (new_arg)
2114 new_arg[arg_index] = '\0';
2115 add_pending_null (context, &((*argv)[i]), new_arg);
2116 i = new_i;
2118 else if (parsed)
2120 add_pending_null (context, &((*argv)[i]), NULL);
2121 i = new_i;
2125 if (!parsed)
2126 has_unknown = TRUE;
2128 if (!parsed && !context->ignore_unknown)
2130 g_set_error (error,
2131 G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION,
2132 _("Unknown option %s"), (*argv)[i]);
2133 goto fail;
2136 else
2138 if (context->strict_posix)
2139 stop_parsing = TRUE;
2141 /* Collect remaining args */
2142 if (context->main_group &&
2143 !parse_remaining_arg (context, context->main_group, &i,
2144 argc, argv, error, &parsed))
2145 goto fail;
2147 if (!parsed && (has_unknown || (*argv)[i][0] == '-'))
2148 separator_pos = 0;
2152 if (separator_pos > 0)
2153 add_pending_null (context, &((*argv)[separator_pos]), NULL);
2157 /* Call post-parse hooks */
2158 list = context->groups;
2159 while (list)
2161 GOptionGroup *group = list->data;
2163 if (group->post_parse_func)
2165 if (!(* group->post_parse_func) (context, group,
2166 group->user_data, error))
2167 goto fail;
2170 list = list->next;
2173 if (context->main_group && context->main_group->post_parse_func)
2175 if (!(* context->main_group->post_parse_func) (context, context->main_group,
2176 context->main_group->user_data, error))
2177 goto fail;
2180 if (argc && argv)
2182 free_pending_nulls (context, TRUE);
2184 for (i = 1; i < *argc; i++)
2186 for (k = i; k < *argc; k++)
2187 if ((*argv)[k] != NULL)
2188 break;
2190 if (k > i)
2192 k -= i;
2193 for (j = i + k; j < *argc; j++)
2195 (*argv)[j-k] = (*argv)[j];
2196 (*argv)[j] = NULL;
2198 *argc -= k;
2203 return TRUE;
2205 fail:
2207 /* Call error hooks */
2208 list = context->groups;
2209 while (list)
2211 GOptionGroup *group = list->data;
2213 if (group->error_func)
2214 (* group->error_func) (context, group,
2215 group->user_data, error);
2217 list = list->next;
2220 if (context->main_group && context->main_group->error_func)
2221 (* context->main_group->error_func) (context, context->main_group,
2222 context->main_group->user_data, error);
2224 free_changes_list (context, TRUE);
2225 free_pending_nulls (context, FALSE);
2227 return FALSE;
2231 * g_option_group_new:
2232 * @name: the name for the option group, this is used to provide
2233 * help for the options in this group with `--help-`@name
2234 * @description: a description for this group to be shown in
2235 * `--help`. This string is translated using the translation
2236 * domain or translation function of the group
2237 * @help_description: a description for the `--help-`@name option.
2238 * This string is translated using the translation domain or translation function
2239 * of the group
2240 * @user_data: (nullable): user data that will be passed to the pre- and post-parse hooks,
2241 * the error hook and to callbacks of %G_OPTION_ARG_CALLBACK options, or %NULL
2242 * @destroy: (nullable): a function that will be called to free @user_data, or %NULL
2244 * Creates a new #GOptionGroup.
2246 * Returns: a newly created option group. It should be added
2247 * to a #GOptionContext or freed with g_option_group_unref().
2249 * Since: 2.6
2251 GOptionGroup *
2252 g_option_group_new (const gchar *name,
2253 const gchar *description,
2254 const gchar *help_description,
2255 gpointer user_data,
2256 GDestroyNotify destroy)
2259 GOptionGroup *group;
2261 group = g_new0 (GOptionGroup, 1);
2262 group->ref_count = 1;
2263 group->name = g_strdup (name);
2264 group->description = g_strdup (description);
2265 group->help_description = g_strdup (help_description);
2266 group->user_data = user_data;
2267 group->destroy_notify = destroy;
2269 return group;
2274 * g_option_group_free:
2275 * @group: a #GOptionGroup
2277 * Frees a #GOptionGroup. Note that you must not free groups
2278 * which have been added to a #GOptionContext.
2280 * Since: 2.6
2282 * Deprecated: 2.44: Use g_option_group_unref() instead.
2284 void
2285 g_option_group_free (GOptionGroup *group)
2287 g_option_group_unref (group);
2291 * g_option_group_ref:
2292 * @group: a #GOptionGroup
2294 * Increments the reference count of @group by one.
2296 * Returns: a #GoptionGroup
2298 * Since: 2.44
2300 GOptionGroup *
2301 g_option_group_ref (GOptionGroup *group)
2303 g_return_val_if_fail (group != NULL, NULL);
2305 group->ref_count++;
2307 return group;
2311 * g_option_group_unref:
2312 * @group: a #GOptionGroup
2314 * Decrements the reference count of @group by one.
2315 * If the reference count drops to 0, the @group will be freed.
2316 * and all memory allocated by the @group is released.
2318 * Since: 2.44
2320 void
2321 g_option_group_unref (GOptionGroup *group)
2323 g_return_if_fail (group != NULL);
2325 if (--group->ref_count == 0)
2327 g_free (group->name);
2328 g_free (group->description);
2329 g_free (group->help_description);
2331 g_free (group->entries);
2333 if (group->destroy_notify)
2334 (* group->destroy_notify) (group->user_data);
2336 if (group->translate_notify)
2337 (* group->translate_notify) (group->translate_data);
2339 g_free (group);
2344 * g_option_group_add_entries:
2345 * @group: a #GOptionGroup
2346 * @entries: a %NULL-terminated array of #GOptionEntrys
2348 * Adds the options specified in @entries to @group.
2350 * Since: 2.6
2352 void
2353 g_option_group_add_entries (GOptionGroup *group,
2354 const GOptionEntry *entries)
2356 gint i, n_entries;
2358 g_return_if_fail (entries != NULL);
2360 for (n_entries = 0; entries[n_entries].long_name != NULL; n_entries++) ;
2362 group->entries = g_renew (GOptionEntry, group->entries, group->n_entries + n_entries);
2364 /* group->entries could be NULL in the trivial case where we add no
2365 * entries to no entries */
2366 if (n_entries != 0)
2367 memcpy (group->entries + group->n_entries, entries, sizeof (GOptionEntry) * n_entries);
2369 for (i = group->n_entries; i < group->n_entries + n_entries; i++)
2371 gchar c = group->entries[i].short_name;
2373 if (c == '-' || (c != 0 && !g_ascii_isprint (c)))
2375 g_warning (G_STRLOC ": ignoring invalid short option '%c' (%d) in entry %s:%s",
2376 c, c, group->name, group->entries[i].long_name);
2377 group->entries[i].short_name = '\0';
2380 if (group->entries[i].arg != G_OPTION_ARG_NONE &&
2381 (group->entries[i].flags & G_OPTION_FLAG_REVERSE) != 0)
2383 g_warning (G_STRLOC ": ignoring reverse flag on option of arg-type %d in entry %s:%s",
2384 group->entries[i].arg, group->name, group->entries[i].long_name);
2386 group->entries[i].flags &= ~G_OPTION_FLAG_REVERSE;
2389 if (group->entries[i].arg != G_OPTION_ARG_CALLBACK &&
2390 (group->entries[i].flags & (G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG|G_OPTION_FLAG_FILENAME)) != 0)
2392 g_warning (G_STRLOC ": ignoring no-arg, optional-arg or filename flags (%d) on option of arg-type %d in entry %s:%s",
2393 group->entries[i].flags, group->entries[i].arg, group->name, group->entries[i].long_name);
2395 group->entries[i].flags &= ~(G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG|G_OPTION_FLAG_FILENAME);
2399 group->n_entries += n_entries;
2403 * g_option_group_set_parse_hooks:
2404 * @group: a #GOptionGroup
2405 * @pre_parse_func: (nullable): a function to call before parsing, or %NULL
2406 * @post_parse_func: (nullable): a function to call after parsing, or %NULL
2408 * Associates two functions with @group which will be called
2409 * from g_option_context_parse() before the first option is parsed
2410 * and after the last option has been parsed, respectively.
2412 * Note that the user data to be passed to @pre_parse_func and
2413 * @post_parse_func can be specified when constructing the group
2414 * with g_option_group_new().
2416 * Since: 2.6
2418 void
2419 g_option_group_set_parse_hooks (GOptionGroup *group,
2420 GOptionParseFunc pre_parse_func,
2421 GOptionParseFunc post_parse_func)
2423 g_return_if_fail (group != NULL);
2425 group->pre_parse_func = pre_parse_func;
2426 group->post_parse_func = post_parse_func;
2430 * g_option_group_set_error_hook:
2431 * @group: a #GOptionGroup
2432 * @error_func: a function to call when an error occurs
2434 * Associates a function with @group which will be called
2435 * from g_option_context_parse() when an error occurs.
2437 * Note that the user data to be passed to @error_func can be
2438 * specified when constructing the group with g_option_group_new().
2440 * Since: 2.6
2442 void
2443 g_option_group_set_error_hook (GOptionGroup *group,
2444 GOptionErrorFunc error_func)
2446 g_return_if_fail (group != NULL);
2448 group->error_func = error_func;
2453 * g_option_group_set_translate_func:
2454 * @group: a #GOptionGroup
2455 * @func: (nullable): the #GTranslateFunc, or %NULL
2456 * @data: (nullable): user data to pass to @func, or %NULL
2457 * @destroy_notify: (nullable): a function which gets called to free @data, or %NULL
2459 * Sets the function which is used to translate user-visible strings,
2460 * for `--help` output. Different groups can use different
2461 * #GTranslateFuncs. If @func is %NULL, strings are not translated.
2463 * If you are using gettext(), you only need to set the translation
2464 * domain, see g_option_group_set_translation_domain().
2466 * Since: 2.6
2468 void
2469 g_option_group_set_translate_func (GOptionGroup *group,
2470 GTranslateFunc func,
2471 gpointer data,
2472 GDestroyNotify destroy_notify)
2474 g_return_if_fail (group != NULL);
2476 if (group->translate_notify)
2477 group->translate_notify (group->translate_data);
2479 group->translate_func = func;
2480 group->translate_data = data;
2481 group->translate_notify = destroy_notify;
2484 static const gchar *
2485 dgettext_swapped (const gchar *msgid,
2486 const gchar *domainname)
2488 return g_dgettext (domainname, msgid);
2492 * g_option_group_set_translation_domain:
2493 * @group: a #GOptionGroup
2494 * @domain: the domain to use
2496 * A convenience function to use gettext() for translating
2497 * user-visible strings.
2499 * Since: 2.6
2501 void
2502 g_option_group_set_translation_domain (GOptionGroup *group,
2503 const gchar *domain)
2505 g_return_if_fail (group != NULL);
2507 g_option_group_set_translate_func (group,
2508 (GTranslateFunc)dgettext_swapped,
2509 g_strdup (domain),
2510 g_free);
2514 * g_option_context_set_translate_func:
2515 * @context: a #GOptionContext
2516 * @func: (nullable): the #GTranslateFunc, or %NULL
2517 * @data: (nullable): user data to pass to @func, or %NULL
2518 * @destroy_notify: (nullable): a function which gets called to free @data, or %NULL
2520 * Sets the function which is used to translate the contexts
2521 * user-visible strings, for `--help` output. If @func is %NULL,
2522 * strings are not translated.
2524 * Note that option groups have their own translation functions,
2525 * this function only affects the @parameter_string (see g_option_context_new()),
2526 * the summary (see g_option_context_set_summary()) and the description
2527 * (see g_option_context_set_description()).
2529 * If you are using gettext(), you only need to set the translation
2530 * domain, see g_option_context_set_translation_domain().
2532 * Since: 2.12
2534 void
2535 g_option_context_set_translate_func (GOptionContext *context,
2536 GTranslateFunc func,
2537 gpointer data,
2538 GDestroyNotify destroy_notify)
2540 g_return_if_fail (context != NULL);
2542 if (context->translate_notify)
2543 context->translate_notify (context->translate_data);
2545 context->translate_func = func;
2546 context->translate_data = data;
2547 context->translate_notify = destroy_notify;
2551 * g_option_context_set_translation_domain:
2552 * @context: a #GOptionContext
2553 * @domain: the domain to use
2555 * A convenience function to use gettext() for translating
2556 * user-visible strings.
2558 * Since: 2.12
2560 void
2561 g_option_context_set_translation_domain (GOptionContext *context,
2562 const gchar *domain)
2564 g_return_if_fail (context != NULL);
2566 g_option_context_set_translate_func (context,
2567 (GTranslateFunc)dgettext_swapped,
2568 g_strdup (domain),
2569 g_free);
2573 * g_option_context_set_summary:
2574 * @context: a #GOptionContext
2575 * @summary: (nullable): a string to be shown in `--help` output
2576 * before the list of options, or %NULL
2578 * Adds a string to be displayed in `--help` output before the list
2579 * of options. This is typically a summary of the program functionality.
2581 * Note that the summary is translated (see
2582 * g_option_context_set_translate_func() and
2583 * g_option_context_set_translation_domain()).
2585 * Since: 2.12
2587 void
2588 g_option_context_set_summary (GOptionContext *context,
2589 const gchar *summary)
2591 g_return_if_fail (context != NULL);
2593 g_free (context->summary);
2594 context->summary = g_strdup (summary);
2599 * g_option_context_get_summary:
2600 * @context: a #GOptionContext
2602 * Returns the summary. See g_option_context_set_summary().
2604 * Returns: the summary
2606 * Since: 2.12
2608 const gchar *
2609 g_option_context_get_summary (GOptionContext *context)
2611 g_return_val_if_fail (context != NULL, NULL);
2613 return context->summary;
2617 * g_option_context_set_description:
2618 * @context: a #GOptionContext
2619 * @description: (nullable): a string to be shown in `--help` output
2620 * after the list of options, or %NULL
2622 * Adds a string to be displayed in `--help` output after the list
2623 * of options. This text often includes a bug reporting address.
2625 * Note that the summary is translated (see
2626 * g_option_context_set_translate_func()).
2628 * Since: 2.12
2630 void
2631 g_option_context_set_description (GOptionContext *context,
2632 const gchar *description)
2634 g_return_if_fail (context != NULL);
2636 g_free (context->description);
2637 context->description = g_strdup (description);
2642 * g_option_context_get_description:
2643 * @context: a #GOptionContext
2645 * Returns the description. See g_option_context_set_description().
2647 * Returns: the description
2649 * Since: 2.12
2651 const gchar *
2652 g_option_context_get_description (GOptionContext *context)
2654 g_return_val_if_fail (context != NULL, NULL);
2656 return context->description;
2660 * g_option_context_parse_strv:
2661 * @context: a #GOptionContext
2662 * @arguments: (inout) (array null-terminated=1): a pointer to the
2663 * command line arguments (which must be in UTF-8 on Windows)
2664 * @error: a return location for errors
2666 * Parses the command line arguments.
2668 * This function is similar to g_option_context_parse() except that it
2669 * respects the normal memory rules when dealing with a strv instead of
2670 * assuming that the passed-in array is the argv of the main function.
2672 * In particular, strings that are removed from the arguments list will
2673 * be freed using g_free().
2675 * On Windows, the strings are expected to be in UTF-8. This is in
2676 * contrast to g_option_context_parse() which expects them to be in the
2677 * system codepage, which is how they are passed as @argv to main().
2678 * See g_win32_get_command_line() for a solution.
2680 * This function is useful if you are trying to use #GOptionContext with
2681 * #GApplication.
2683 * Returns: %TRUE if the parsing was successful,
2684 * %FALSE if an error occurred
2686 * Since: 2.40
2688 gboolean
2689 g_option_context_parse_strv (GOptionContext *context,
2690 gchar ***arguments,
2691 GError **error)
2693 gboolean success;
2694 gint argc;
2696 context->strv_mode = TRUE;
2697 argc = g_strv_length (*arguments);
2698 success = g_option_context_parse (context, &argc, arguments, error);
2699 context->strv_mode = FALSE;
2701 return success;