2 * Wrapper for GNU getopt which deals with standard options
3 * Copyright (C) 1998-2001,2003,2004,2011,2012,2014,2024 Olly Betts
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
37 /* It might be useful to be able to disable all long options on small
38 * platforms like older PDAs.
41 # define getopt_long(ARGC, ARGV, STR, OPTS, PTR) getopt(ARGC, ARGV, STR)
45 * bad command line give:
64 * want to cope with optional/required parameters on long options
65 * and also parameters on short options
68 static const char newline_tabs
[] = "\n\t\t\t\t";
71 static char * const *argv
;
72 static const char *shortopts
;
73 static const struct option
*longopts
;
75 static const struct help_msg
*help
;
76 static int min_args
, max_args
;
77 static int msg_args
, msg_extra
;
78 static const char * msg_extra_arg
;
83 while (help
&& help
->opt
) {
84 const char *longopt
= 0;
86 const struct option
*o
= 0;
88 if (HLP_ISLONG(opt
)) {
89 o
= longopts
+ HLP_DECODELONG(opt
);
94 if (isalnum((unsigned char)opt
))
95 printf(" -%c%c", opt
, longopt
? ',' : ' ');
100 int len
= strlen(longopt
);
101 printf(" --%s", longopt
);
102 if (o
&& o
->has_arg
) {
106 if (o
->has_arg
== optional_argument
) {
113 for (p
= longopt
; *p
; p
++) {
114 unsigned char ch
= *p
;
115 putchar((ch
== '-') ? '_' : toupper(ch
));
118 if (o
->has_arg
== optional_argument
) putchar(']');
120 len
= (len
>> 3) + 2;
121 if (len
> 4) len
= 0;
122 fputs(newline_tabs
+ len
, stdout
);
124 fputs(newline_tabs
+ 1, stdout
);
128 SVX_ASSERT(strstr(msg(help
->msg_no
), "%s") != NULL
);
129 printf(msg(help
->msg_no
), help
->arg
);
132 SVX_ASSERT(strstr(msg(help
->msg_no
), "%s") == NULL
);
133 puts(msg(help
->msg_no
));
137 fputs(" --help\t\t\t", stdout
);
138 /* TRANSLATORS: description of --help option */
139 puts(msg(/*display this help and exit*/150));
140 fputs(" --version\t\t\t", stdout
);
141 /* TRANSLATORS: description of --version option */
142 puts(msg(/*output version information and exit*/151));
147 SVX_ASSERT(strstr(msg(msg_extra
), "%s") != NULL
);
148 printf(msg(msg_extra
), msg_extra_arg
);
151 SVX_ASSERT(strstr(msg(msg_extra
), "%s") == NULL
);
152 puts(msg(msg_extra
));
160 cmdline_version(void)
162 printf("%s - "PRETTYPACKAGE
" "VERSION
"\n", msg_appname());
168 /* TRANSLATORS: as in: Usage: cavern … */
169 printf("\n%s: %s", msg(/*Usage*/49), msg_appname());
170 /* TRANSLATORS: in command line usage messages e.g. Usage: cavern [OPTION]… */
171 if (help
&& help
->opt
) printf(" [%s]...", msg(/*OPTION*/153));
179 while (i
--) printf(" %s", msg(/*FILE*/124));
181 if (max_args
== -1) {
182 if (!min_args
) printf(" [%s]", msg(/*FILE*/124));
183 fputs("...", stdout
);
184 } else if (max_args
> min_args
) {
185 int i
= max_args
- min_args
;
186 while (i
--) printf(" [%s]", msg(/*FILE*/124));
192 syntax_and_help_pointer(void)
195 fprintf(stderr
, msg(/*Try “%s --help” for more information.\n*/157),
201 moan_and_die(int msgno
)
203 fprintf(stderr
, "%s: ", msg_appname());
204 fprintf(stderr
, msg(msgno
), optarg
);
211 cmdline_too_few_args(void)
213 fprintf(stderr
, "%s: %s\n", msg_appname(), msg(/*too few arguments*/122));
214 syntax_and_help_pointer();
218 cmdline_too_many_args(void)
220 fprintf(stderr
, "%s: %s\n", msg_appname(), msg(/*too many arguments*/123));
221 syntax_and_help_pointer();
225 cmdline_set_syntax_message(int msg_args_
, int msg_extra_
, const char * arg
)
227 msg_args
= msg_args_
;
228 msg_extra
= msg_extra_
;
233 cmdline_int_arg(void)
240 result
= strtol(optarg
, &endptr
, 10);
242 if (errno
== ERANGE
|| result
> INT_MAX
|| result
< INT_MIN
) {
243 moan_and_die(/*numeric argument “%s” out of range*/185);
244 } else if (*optarg
== '\0' || *endptr
!= '\0') {
245 moan_and_die(/*argument “%s” not an integer*/186);
252 cmdline_double_arg(void)
259 result
= strtod(optarg
, &endptr
);
261 if (errno
== ERANGE
) {
262 moan_and_die(/*numeric argument “%s” out of range*/185);
263 } else if (*optarg
== '\0' || *endptr
!= '\0') {
264 moan_and_die(/*argument “%s” not a number*/187);
271 cmdline_init(int argc_
, char *const *argv_
, const char *shortopts_
,
272 const struct option
*longopts_
, int *longind_
,
273 const struct help_msg
*help_
,
274 int min_args_
, int max_args_
)
278 shortopts
= shortopts_
;
279 longopts
= longopts_
;
282 min_args
= min_args_
;
283 max_args
= max_args_
;
289 int opt
= getopt_long(argc
, argv
, shortopts
, longopts
, longind
);
293 /* check valid # of args given - if not give syntax message */
294 if (argc
- optind
< min_args
) {
295 cmdline_too_few_args();
296 } else if (max_args
>= 0 && argc
- optind
> max_args
) {
297 cmdline_too_many_args();
300 case ':': /* parameter missing */
301 case '?': /* unknown opt, ambiguous match, or extraneous param */
302 /* getopt displays a message for us */
303 syntax_and_help_pointer();
305 case HLP_VERSION
: /* --version */
308 case HLP_HELP
: /* --help */