source: git/src/cmdline.c

Last change on this file was bc860e4, checked in by Olly Betts <olly@…>, 4 months ago

Fix mingw build

This has started to fail due to the GNU getopt code not declaring
getopt().

Survex only uses getopt_long() so we can remove the declaration of
getopt() and then there's no potential for clashing prototypes so
we can just include <stdlib.h>.

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