source: git/src/cmdline.c @ 0bf6ac3

RELEASE/1.0RELEASE/1.1RELEASE/1.2debug-cidebug-ci-sanitisersfaster-cavernloglog-selectstereostereo-2025walls-datawalls-data-hanging-as-warningwarn-only-for-hanging-survey
Last change on this file since 0bf6ac3 was 5fbfd8d, checked in by Olly Betts <olly@…>, 25 years ago

Fixed display of short options with no equivalent long option.

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

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