Show location for backsights out of tolerance
[survex.git] / src / cmdline.c
blob8b0b241addf00faf3d326abcfa1de84578c863d5
1 /* cmdline.c
2 * Wrapper for GNU getopt which deals with standard options
3 * Copyright (C) 1998-2001,2003,2004,2011,2012,2014 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
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <ctype.h>
25 #include <errno.h>
26 #include <float.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <limits.h>
31 #include "getopt.h"
33 #include "cmdline.h"
34 #include "debug.h"
35 #include "filename.h"
37 #include "message.h"
39 /* It might be useful to be able to disable all long options on small
40 * platforms like older PDAs.
42 #if 0
43 # define getopt_long(ARGC, ARGV, STR, OPTS, PTR) getopt(ARGC, ARGV, STR)
44 #endif
47 * bad command line give:
48 * <problem>
50 * <short syntax>
52 * --help gives:
53 * <version>
55 * <short syntax>
57 * <table>
59 * <blurb>
61 * --version gives:
62 * <version>
66 * want to cope with optional/required parameters on long options
67 * and also parameters on short options
70 static const char newline_tabs[] = "\n\t\t\t\t";
72 static int argc;
73 static char * const *argv;
74 static const char *shortopts;
75 static const struct option *longopts;
76 static int *longind;
77 static const struct help_msg *help;
78 static int min_args, max_args;
79 static int msg_args, msg_extra;
80 static const char * msg_extra_arg;
82 void
83 cmdline_help(void)
85 while (help && help->opt) {
86 const char *longopt = 0;
87 int opt = help->opt;
88 const struct option *o = 0;
90 if (HLP_ISLONG(opt)) {
91 o = longopts + HLP_DECODELONG(opt);
92 longopt = o->name;
93 opt = o->val;
96 if (isalnum((unsigned char)opt))
97 printf(" -%c%c", opt, longopt ? ',' : ' ');
98 else
99 fputs(" ", stdout);
101 if (longopt) {
102 int len = strlen(longopt);
103 printf(" --%s", longopt);
104 if (o && o->has_arg) {
105 const char *p;
106 len += len + 1;
108 if (o->has_arg == optional_argument) {
109 putchar('[');
110 len += 2;
113 putchar('=');
115 for (p = longopt; *p ; p++) putchar(toupper(*p));
117 if (o->has_arg == optional_argument) putchar(']');
119 len = (len >> 3) + 2;
120 if (len > 4) len = 0;
121 fputs(newline_tabs + len, stdout);
122 } else {
123 fputs(newline_tabs + 1, stdout);
126 if (help->arg) {
127 SVX_ASSERT(strstr(msg(help->msg_no), "%s") != NULL);
128 printf(msg(help->msg_no), help->arg);
129 putnl();
130 } else {
131 SVX_ASSERT(strstr(msg(help->msg_no), "%s") == NULL);
132 puts(msg(help->msg_no));
134 help++;
136 fputs(" --help\t\t\t", stdout);
137 /* TRANSLATORS: description of --help option */
138 puts(msg(/*display this help and exit*/150));
139 fputs(" --version\t\t\t", stdout);
140 /* TRANSLATORS: description of --version option */
141 puts(msg(/*output version information and exit*/151));
143 if (msg_extra) {
144 putnl();
145 if (msg_extra_arg) {
146 SVX_ASSERT(strstr(msg(msg_extra), "%s") != NULL);
147 printf(msg(msg_extra), msg_extra_arg);
148 putnl();
149 } else {
150 SVX_ASSERT(strstr(msg(msg_extra), "%s") == NULL);
151 puts(msg(msg_extra));
155 exit(0);
158 void
159 cmdline_version(void)
161 printf("%s - "PRETTYPACKAGE" "VERSION"\n", msg_appname());
164 void
165 cmdline_syntax(void)
167 /* TRANSLATORS: as in: Usage: cavern … */
168 printf("\n%s: %s", msg(/*Usage*/49), msg_appname());
169 /* TRANSLATORS: in command line usage messages e.g. Usage: cavern [OPTION]… */
170 if (help && help->opt) printf(" [%s]...", msg(/*OPTION*/153));
171 if (msg_args) {
172 putchar(' ');
173 puts(msg(msg_args));
174 return;
176 if (min_args) {
177 int i = min_args;
178 while (i--) printf(" %s", msg(/*FILE*/124));
180 if (max_args == -1) {
181 if (!min_args) printf(" [%s]", msg(/*FILE*/124));
182 fputs("...", stdout);
183 } else if (max_args > min_args) {
184 int i = max_args - min_args;
185 while (i--) printf(" [%s]", msg(/*FILE*/124));
187 putnl();
190 static void
191 syntax_and_help_pointer(void)
193 cmdline_syntax();
194 fprintf(stderr, msg(/*Try “%s --help” for more information.\n*/157),
195 msg_appname());
196 exit(1);
199 static void
200 moan_and_die(int msgno)
202 fprintf(stderr, "%s: ", msg_appname());
203 fprintf(stderr, msg(msgno), optarg);
204 fputnl(stderr);
205 cmdline_syntax();
206 exit(1);
209 void
210 cmdline_too_few_args(void)
212 fprintf(stderr, "%s: %s\n", msg_appname(), msg(/*too few arguments*/122));
213 syntax_and_help_pointer();
216 void
217 cmdline_too_many_args(void)
219 fprintf(stderr, "%s: %s\n", msg_appname(), msg(/*too many arguments*/123));
220 syntax_and_help_pointer();
223 void
224 cmdline_set_syntax_message(int msg_args_, int msg_extra_, const char * arg)
226 msg_args = msg_args_;
227 msg_extra = msg_extra_;
228 msg_extra_arg = arg;
232 cmdline_int_arg(void)
234 long result;
235 char *endptr;
237 errno = 0;
239 result = strtol(optarg, &endptr, 10);
241 if (errno == ERANGE || result > INT_MAX || result < INT_MIN) {
242 moan_and_die(/*numeric argument “%s” out of range*/185);
243 } else if (*optarg == '\0' || *endptr != '\0') {
244 moan_and_die(/*argument “%s” not an integer*/186);
247 return (int)result;
250 double
251 cmdline_double_arg(void)
253 double result;
254 char *endptr;
256 errno = 0;
258 result = strtod(optarg, &endptr);
260 if (errno == ERANGE) {
261 moan_and_die(/*numeric argument “%s” out of range*/185);
262 } else if (*optarg == '\0' || *endptr != '\0') {
263 moan_and_die(/*argument “%s” not a number*/187);
266 return result;
269 void
270 cmdline_init(int argc_, char *const *argv_, const char *shortopts_,
271 const struct option *longopts_, int *longind_,
272 const struct help_msg *help_,
273 int min_args_, int max_args_)
275 argc = argc_;
276 argv = argv_;
277 shortopts = shortopts_;
278 longopts = longopts_;
279 longind = longind_;
280 help = help_;
281 min_args = min_args_;
282 max_args = max_args_;
286 cmdline_getopt(void)
288 int opt = getopt_long(argc, argv, shortopts, longopts, longind);
290 switch (opt) {
291 case EOF:
292 /* check valid # of args given - if not give syntax message */
293 if (argc - optind < min_args) {
294 cmdline_too_few_args();
295 } else if (max_args >= 0 && argc - optind > max_args) {
296 cmdline_too_many_args();
298 break;
299 case ':': /* parameter missing */
300 case '?': /* unknown opt, ambiguous match, or extraneous param */
301 /* getopt displays a message for us */
302 syntax_and_help_pointer();
303 break;
304 case HLP_VERSION: /* --version */
305 cmdline_version();
306 exit(0);
307 case HLP_HELP: /* --help */
308 cmdline_version();
309 cmdline_syntax();
310 putchar('\n');
311 cmdline_help();
312 exit(0);
314 return opt;