source: git/src/cmdline.c @ 45af761

RELEASE/1.2debug-cidebug-ci-sanitisersstereowalls-data
Last change on this file since 45af761 was 45af761, checked in by Olly Betts <olly@…>, 13 years ago

lib/,src/: Extract all the help strings in --help output and make
them available for translation.

git-svn-id: file:///home/survex-svn/survex/trunk@3741 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

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