source: git/src/cmdline.c @ af89ae7

RELEASE/1.1RELEASE/1.2debug-cidebug-ci-sanitisersfaster-cavernlogstereowalls-datawalls-data-hanging-as-warning
Last change on this file since af89ae7 was c40038a, checked in by Olly Betts <olly@…>, 22 years ago

Vastly improved msg.pl script for extracting messages from source code.
Compared its output to message file and fixed up discrepancies.

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

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