2 * Copyright © 2021 Nick Bowler
4 * Helper functions for formatting --help program output.
6 * In order to support localized output, this depends on the Gnulib gettext-h
7 * and mbswidth modules. However, if ENABLE_NLS is not defined (or defined to
8 * 0) then these modules are not required.
10 * License WTFPL2: Do What The Fuck You Want To Public License, version 2.
11 * This is free software: you are free to do what the fuck you want to.
12 * There is NO WARRANTY, to the extent permitted by law.
32 # include <mbswidth.h>
34 # define gettext(s) (s)
35 # define pgettext_expr(c, s) (s)
36 # define mbsnwidth(a, b, c) (assert(0), 0)
39 #define _(s) gettext(s)
41 /* Returns a single numeric value depending on the type of option:
43 * 6 - if the option has a short option character and an optional argument
44 * 5 - if the option has a short option character and a mandatory argument
45 * 4 - if the option has a short option charater and no argument
47 * 2 - if the option has no short option character and an optional argument
48 * 1 - if the option has no short option character and a mandatory argument
49 * 0 - if the option has no short option character and no argument
51 static int option_type(const struct option *opt)
53 return ((opt->val <= CHAR_MAX) << 2) | (opt->has_arg & 3);
57 OPT_SHORT_WITH_OPTIONAL_ARG = 6,
58 OPT_SHORT_WITH_MANDATORY_ARG = 5,
59 OPT_SHORT_WITHOUT_ARG = 4,
60 OPT_LONG_WITH_OPTIONAL_ARG = 2,
61 OPT_LONG_WITH_MANDATORY_ARG = 1,
62 OPT_LONG_WITHOUT_ARG = 0,
65 int help_print_optstring(const struct option *opt, const char *argname, int l)
73 switch (option_type(opt)) {
74 #if HELP_GETOPT_LONG_ONLY
75 case OPT_SHORT_WITH_OPTIONAL_ARG:
76 case OPT_LONG_WITH_OPTIONAL_ARG:
77 w = snprintf(optstring, sizeof optstring,
78 _(" -%s [%s]"), opt->name,
79 pgettext_expr(opt->name, argname));
81 case OPT_SHORT_WITH_MANDATORY_ARG:
82 case OPT_LONG_WITH_MANDATORY_ARG:
83 w = snprintf(optstring, sizeof optstring,
84 _(" -%s %s"), opt->name,
85 pgettext_expr(opt->name, argname));
87 case OPT_SHORT_WITHOUT_ARG:
88 case OPT_LONG_WITHOUT_ARG:
89 w = snprintf(optstring, sizeof optstring,
90 _(" -%s"), opt->name);
93 case OPT_SHORT_WITH_OPTIONAL_ARG:
94 w = snprintf(optstring, sizeof optstring,
95 _(" -%c, --%s[=%s]"), opt->val, opt->name,
96 pgettext_expr(opt->name, argname));
98 case OPT_LONG_WITH_OPTIONAL_ARG:
99 w = snprintf(optstring, sizeof optstring,
100 _(" --%s[=%s]"), opt->name,
101 pgettext_expr(opt->name, argname));
103 case OPT_SHORT_WITH_MANDATORY_ARG:
104 w = snprintf(optstring, sizeof optstring,
105 _(" -%c, --%s=%s"), opt->val, opt->name,
106 pgettext_expr(opt->name, argname));
108 case OPT_LONG_WITH_MANDATORY_ARG:
109 w = snprintf(optstring, sizeof optstring,
110 _(" --%s=%s"), opt->name,
111 pgettext_expr(opt->name, argname));
113 case OPT_SHORT_WITHOUT_ARG:
114 w = snprintf(optstring, sizeof optstring,
115 _(" -%c, --%s"), opt->val, opt->name);
117 case OPT_LONG_WITHOUT_ARG:
118 w = snprintf(optstring, sizeof optstring,
119 _(" --%s"), opt->name);
129 w = mbsnwidth(optstring, w, 0);
130 printf("%s", optstring);
134 switch (option_type(opt)) {
135 #if HELP_GETOPT_LONG_ONLY
136 case OPT_SHORT_WITH_OPTIONAL_ARG:
137 case OPT_LONG_WITH_OPTIONAL_ARG:
138 w = printf(" -%s [%s]", opt->name, argname);
140 case OPT_SHORT_WITH_MANDATORY_ARG:
141 case OPT_LONG_WITH_MANDATORY_ARG:
142 w = printf(" -%s %s", opt->name, argname);
144 case OPT_SHORT_WITHOUT_ARG:
145 case OPT_LONG_WITHOUT_ARG:
146 w = printf(" -%s", opt->name);
149 case OPT_SHORT_WITH_OPTIONAL_ARG:
150 w = printf(" -%c, --%s[=%s]", opt->val, opt->name, argname);
152 case OPT_LONG_WITH_OPTIONAL_ARG:
153 w = printf(" --%s[=%s]", opt->name, argname);
155 case OPT_SHORT_WITH_MANDATORY_ARG:
156 w = printf(" -%c, --%s=%s", opt->val, opt->name, argname);
158 case OPT_LONG_WITH_MANDATORY_ARG:
159 w = printf(" --%s=%s", opt->name, argname);
161 case OPT_SHORT_WITHOUT_ARG:
162 w = printf(" -%c, --%s", opt->val, opt->name);
164 case OPT_LONG_WITHOUT_ARG:
165 w = printf(" --%s", opt->name);
172 if (w < 0 || w > l) {
180 void help_print_desc(const struct option *opt, const char *s, int i, int w)
183 s = pgettext_expr(opt->name, s);
186 const char *nl = strchr(s, '\n');
187 int n = (nl ? nl-s : -1);
189 printf("%*s%.*s\n", i-w, "", n, s);