source: git/src/cmdline.c

walls-data
Last change on this file was 4c83f84, checked in by Olly Betts <olly@…>, 5 days ago

Don't check HAVE_CONFIG_H in most cases

This check is only useful for img.c, which is intended to be usable
outside of Survex (and had fallbacks for functions which may not be
available which will get used if built in a non-autotools project).
For all the other source files it's just useless boilerplate.

  • Property mode set to 100644
File size: 7.1 KB
Line 
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
4 *
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.
9 *
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.
14 *
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
18 */
19
20#include <config.h>
21
22#include <ctype.h>
23#include <errno.h>
24#include <float.h>
25#include <stdio.h>
26#include <string.h>
27#include <limits.h>
28
29#include "getopt.h"
30
31#include "cmdline.h"
32#include "debug.h"
33#include "filename.h"
34
35#include "message.h"
36
37/* It might be useful to be able to disable all long options on small
38 * platforms like older PDAs.
39 */
40#if 0
41# define getopt_long(ARGC, ARGV, STR, OPTS, PTR) getopt(ARGC, ARGV, STR)
42#endif
43
44/*
45 * bad command line give:
46 * <problem>
47 *
48 * <short syntax>
49 *
50 * --help gives:
51 * <version>
52 *
53 * <short syntax>
54 *
55 * <table>
56 *
57 * <blurb>
58 *
59 * --version gives:
60 * <version>
61 */
62
63/*
64 * want to cope with optional/required parameters on long options
65 * and also parameters on short options
66 */
67
68static const char newline_tabs[] = "\n\t\t\t\t";
69
70static int argc;
71static char * const *argv;
72static const char *shortopts;
73static const struct option *longopts;
74static int *longind;
75static const struct help_msg *help;
76static int min_args, max_args;
77static int msg_args, msg_extra;
78static const char * msg_extra_arg;
79
80void
81cmdline_help(void)
82{
83   while (help && help->opt) {
84      const char *longopt = 0;
85      int opt = help->opt;
86      const struct option *o = 0;
87
88      if (HLP_ISLONG(opt)) {
89         o = longopts + HLP_DECODELONG(opt);
90         longopt = o->name;
91         opt = o->val;
92      }
93
94      if (isalnum((unsigned char)opt))
95         printf("  -%c%c", opt, longopt ? ',' : ' ');
96      else
97         fputs("     ", stdout);
98
99      if (longopt) {
100         int len = strlen(longopt);
101         printf(" --%s", longopt);
102         if (o && o->has_arg) {
103            const char *p;
104            len += len + 1;
105
106            if (o->has_arg == optional_argument) {
107               putchar('[');
108               len += 2;
109            }
110
111            putchar('=');
112
113            for (p = longopt; *p ; p++) putchar((unsigned char)toupper(*p));
114
115            if (o->has_arg == optional_argument) putchar(']');
116         }
117         len = (len >> 3) + 2;
118         if (len > 4) len = 0;
119         fputs(newline_tabs + len, stdout);
120      } else {
121         fputs(newline_tabs + 1, stdout);
122      }
123
124      if (help->arg) {
125          SVX_ASSERT(strstr(msg(help->msg_no), "%s") != NULL);
126          printf(msg(help->msg_no), help->arg);
127          putnl();
128      } else {
129          SVX_ASSERT(strstr(msg(help->msg_no), "%s") == NULL);
130          puts(msg(help->msg_no));
131      }
132      help++;
133   }
134   fputs("      --help\t\t\t", stdout);
135   /* TRANSLATORS: description of --help option */
136   puts(msg(/*display this help and exit*/150));
137   fputs("      --version\t\t\t", stdout);
138   /* TRANSLATORS: description of --version option */
139   puts(msg(/*output version information and exit*/151));
140
141   if (msg_extra) {
142      putnl();
143      if (msg_extra_arg) {
144          SVX_ASSERT(strstr(msg(msg_extra), "%s") != NULL);
145          printf(msg(msg_extra), msg_extra_arg);
146          putnl();
147      } else {
148          SVX_ASSERT(strstr(msg(msg_extra), "%s") == NULL);
149          puts(msg(msg_extra));
150      }
151   }
152
153   exit(0);
154}
155
156void
157cmdline_version(void)
158{
159   printf("%s - "PRETTYPACKAGE" "VERSION"\n", msg_appname());
160}
161
162void
163cmdline_syntax(void)
164{
165   /* TRANSLATORS: as in: Usage: cavern … */
166   printf("\n%s: %s", msg(/*Usage*/49), msg_appname());
167   /* TRANSLATORS: in command line usage messages e.g. Usage: cavern [OPTION]… */
168   if (help && help->opt) printf(" [%s]...", msg(/*OPTION*/153));
169   if (msg_args) {
170      putchar(' ');
171      puts(msg(msg_args));
172      return;
173   }
174   if (min_args) {
175      int i = min_args;
176      while (i--) printf(" %s", msg(/*FILE*/124));
177   }
178   if (max_args == -1) {
179      if (!min_args) printf(" [%s]", msg(/*FILE*/124));
180      fputs("...", stdout);
181   } else if (max_args > min_args) {
182      int i = max_args - min_args;
183      while (i--) printf(" [%s]", msg(/*FILE*/124));
184   }
185   putnl();
186}
187
188static void
189syntax_and_help_pointer(void)
190{
191   cmdline_syntax();
192   fprintf(stderr, msg(/*Try “%s --help” for more information.\n*/157),
193           msg_appname());
194   exit(1);
195}
196
197static void
198moan_and_die(int msgno)
199{
200   fprintf(stderr, "%s: ", msg_appname());
201   fprintf(stderr, msg(msgno), optarg);
202   fputnl(stderr);
203   cmdline_syntax();
204   exit(1);
205}
206
207void
208cmdline_too_few_args(void)
209{
210   fprintf(stderr, "%s: %s\n", msg_appname(), msg(/*too few arguments*/122));
211   syntax_and_help_pointer();
212}
213
214void
215cmdline_too_many_args(void)
216{
217   fprintf(stderr, "%s: %s\n", msg_appname(), msg(/*too many arguments*/123));
218   syntax_and_help_pointer();
219}
220
221void
222cmdline_set_syntax_message(int msg_args_, int msg_extra_, const char * arg)
223{
224   msg_args = msg_args_;
225   msg_extra = msg_extra_;
226   msg_extra_arg = arg;
227}
228
229int
230cmdline_int_arg(void)
231{
232   long result;
233   char *endptr;
234
235   errno = 0;
236
237   result = strtol(optarg, &endptr, 10);
238
239   if (errno == ERANGE || result > INT_MAX || result < INT_MIN) {
240      moan_and_die(/*numeric argument “%s” out of range*/185);
241   } else if (*optarg == '\0' || *endptr != '\0') {
242      moan_and_die(/*argument “%s” not an integer*/186);
243   }
244
245   return (int)result;
246}
247
248double
249cmdline_double_arg(void)
250{
251   double result;
252   char *endptr;
253
254   errno = 0;
255
256   result = strtod(optarg, &endptr);
257
258   if (errno == ERANGE) {
259      moan_and_die(/*numeric argument “%s” out of range*/185);
260   } else if (*optarg == '\0' || *endptr != '\0') {
261      moan_and_die(/*argument “%s” not a number*/187);
262   }
263
264   return result;
265}
266
267void
268cmdline_init(int argc_, char *const *argv_, const char *shortopts_,
269             const struct option *longopts_, int *longind_,
270             const struct help_msg *help_,
271             int min_args_, int max_args_)
272{
273   argc = argc_;
274   argv = argv_;
275   shortopts = shortopts_;
276   longopts = longopts_;
277   longind = longind_;
278   help = help_;
279   min_args = min_args_;
280   max_args = max_args_;
281}
282
283int
284cmdline_getopt(void)
285{
286   int opt = getopt_long(argc, argv, shortopts, longopts, longind);
287
288   switch (opt) {
289    case EOF:
290      /* check valid # of args given - if not give syntax message */
291      if (argc - optind < min_args) {
292         cmdline_too_few_args();
293      } else if (max_args >= 0 && argc - optind > max_args) {
294         cmdline_too_many_args();
295      }
296      break;
297    case ':': /* parameter missing */
298    case '?': /* unknown opt, ambiguous match, or extraneous param */
299      /* getopt displays a message for us */
300      syntax_and_help_pointer();
301      break;
302    case HLP_VERSION: /* --version */
303      cmdline_version();
304      exit(0);
305    case HLP_HELP: /* --help */
306      cmdline_version();
307      cmdline_syntax();
308      putchar('\n');
309      cmdline_help();
310      exit(0);
311   }
312   return opt;
313}
Note: See TracBrowser for help on using the repository browser.