source: git/src/cmdline.c @ c4679c3

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 c4679c3 was bd1913f, checked in by Olly Betts <olly@…>, 24 years ago

Miscellaneous fettling (mostly layout tweaks).

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

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