source: git/src/cmdline.c @ a72ed95

RELEASE/1.2debug-cidebug-ci-sanitisersstereowalls-datawalls-data-hanging-as-warning
Last change on this file since a72ed95 was 736f7df, checked in by Olly Betts <olly@…>, 10 years ago

lib/extract-msgs.pl,lib/survex.pot,src/: Insert "TRANSLATORS"
comments into source code.

  • Property mode set to 100644
File size: 7.1 KB
RevLine 
[6974a34]1/* cmdline.c
[aadc86e]2 * Wrapper for GNU getopt which deals with standard options
[736f7df]3 * Copyright (C) 1998-2001,2003,2004,2011,2012,2014 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
[ecbc6c18]17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  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
[be97baf]31#include "getopt.h"
32
[aadc86e]33#include "cmdline.h"
[45af761]34#include "debug.h"
[e05bdb8]35#include "filename.h"
[aadc86e]36
[d227ee5]37#include "message.h"
38
[aadc86e]39/* It might be useful to be able to disable all long options on small
[175cac6]40 * platforms like older PDAs.
[aadc86e]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>
[cb3d1e2]49 *
[e05bdb8]50 * <short syntax>
[cb3d1e2]51 *
[aadc86e]52 * --help gives:
53 * <version>
[cb3d1e2]54 *
[aadc86e]55 * <short syntax>
56 *
57 * <table>
[cb3d1e2]58 *
[aadc86e]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
[3b9ec3f]68 */
[aadc86e]69
70static const char newline_tabs[] = "\n\t\t\t\t";
71
[3b9ec3f]72static int argc;
[647407d]73static char * const *argv;
[3b9ec3f]74static const char *shortopts;
75static const struct option *longopts;
76static int *longind;
77static const struct help_msg *help;
78static int min_args, max_args;
[d8dbdff]79static int msg_args, msg_extra;
80static const char * msg_extra_arg;
[3b9ec3f]81
82void
83cmdline_help(void)
[aadc86e]84{
[9e513bd3]85   while (help && help->opt) {
[aadc86e]86      const char *longopt = 0;
87      int opt = help->opt;
88      const struct option *o = 0;
89
90      if (HLP_ISLONG(opt)) {
[3b9ec3f]91         o = longopts + HLP_DECODELONG(opt);
[aadc86e]92         longopt = o->name;
93         opt = o->val;
94      }
95
[0580c6a]96      if (isalnum((unsigned char)opt))
[5fbfd8d]97         printf("  -%c%c", opt, longopt ? ',' : ' ');
[aadc86e]98      else
99         fputs("     ", stdout);
100
101      if (longopt) {
102         int len = strlen(longopt);
103         printf(" --%s", longopt);
104         if (o && o->has_arg) {
105            const char *p;
106            len += len + 1;
107
108            if (o->has_arg == optional_argument) {
109               putchar('[');
110               len += 2;
111            }
112
113            putchar('=');
114
115            for (p = longopt; *p ; p++) putchar(toupper(*p));
116
117            if (o->has_arg == optional_argument) putchar(']');
118         }
119         len = (len >> 3) + 2;
120         if (len > 4) len = 0;
121         fputs(newline_tabs + len, stdout);
122      } else {
123         fputs(newline_tabs + 1, stdout);
124      }
125
[45af761]126      if (help->arg) {
127          SVX_ASSERT(strstr(msg(help->msg_no), "%s") != NULL);
128          printf(msg(help->msg_no), help->arg);
129          putnl();
130      } else {
131          SVX_ASSERT(strstr(msg(help->msg_no), "%s") == NULL);
132          puts(msg(help->msg_no));
133      }
[aadc86e]134      help++;
135   }
[45af761]136   fputs("      --help\t\t\t", stdout);
[736f7df]137   /* TRANSLATORS: description of --help option */
[45af761]138   puts(msg(/*display this help and exit*/150));
139   fputs("      --version\t\t\t", stdout);
[736f7df]140   /* TRANSLATORS: description of --verbose option */
[45af761]141   puts(msg(/*output version information and exit*/151));
[acc20b1]142
[d8dbdff]143   if (msg_extra) {
[acc20b1]144      putnl();
[d8dbdff]145      if (msg_extra_arg) {
146          SVX_ASSERT(strstr(msg(msg_extra), "%s") != NULL);
147          printf(msg(msg_extra), msg_extra_arg);
148          putnl();
149      } else {
150          SVX_ASSERT(strstr(msg(msg_extra), "%s") == NULL);
151          puts(msg(msg_extra));
152      }
[acc20b1]153   }
[647407d]154
[aadc86e]155   exit(0);
156}
157
[3b9ec3f]158void
159cmdline_version(void)
[aadc86e]160{
[82afbc4]161   printf("%s - "PRETTYPACKAGE" "VERSION"\n", msg_appname());
[aadc86e]162}
163
[3b9ec3f]164void
165cmdline_syntax(void)
[cb3d1e2]166{
[736f7df]167   /* TRANSLATORS: as in: Usage: cavern … */
[ee7511a]168   printf("\n%s: %s", msg(/*Usage*/49), msg_appname());
[736f7df]169   /* TRANSLATORS: in command line usage messages e.g. Usage: cavern [OPTION]… */
[9e513bd3]170   if (help && help->opt) printf(" [%s]...", msg(/*OPTION*/153));
[d8dbdff]171   if (msg_args) {
[acc20b1]172      putchar(' ');
[d8dbdff]173      puts(msg(msg_args));
[acc20b1]174      return;
175   }
[3b9ec3f]176   if (min_args) {
177      int i = min_args;
[a580dc1]178      while (i--) printf(" %s", msg(/*FILE*/124));
[3b9ec3f]179   }
[647407d]180   if (max_args == -1) {
[a580dc1]181      if (!min_args) printf(" [%s]", msg(/*FILE*/124));
[647407d]182      fputs("...", stdout);
183   } else if (max_args > min_args) {
184      int i = max_args - min_args;
[a580dc1]185      while (i--) printf(" [%s]", msg(/*FILE*/124));
[647407d]186   }
[3b9ec3f]187   putnl();
188}
189
[2668614]190static void
191syntax_and_help_pointer(void)
192{
193   cmdline_syntax();
[ee7511a]194   fprintf(stderr, msg(/*Try “%s --help” for more information.\n*/157),
[2668614]195           msg_appname());
196   exit(1);
197}
198
199static void
200moan_and_die(int msgno)
201{
202   fprintf(stderr, "%s: ", msg_appname());
203   fprintf(stderr, msg(msgno), optarg);
204   fputnl(stderr);
205   cmdline_syntax();
206   exit(1);
207}
208
209void
210cmdline_too_few_args(void)
211{
212   fprintf(stderr, "%s: %s\n", msg_appname(), msg(/*too few arguments*/122));
213   syntax_and_help_pointer();
214}
215
216void
217cmdline_too_many_args(void)
218{
219   fprintf(stderr, "%s: %s\n", msg_appname(), msg(/*too many arguments*/123));
220   syntax_and_help_pointer();
221}
222
[acc20b1]223void
[d8dbdff]224cmdline_set_syntax_message(int msg_args_, int msg_extra_, const char * arg)
[acc20b1]225{
[d8dbdff]226   msg_args = msg_args_;
227   msg_extra = msg_extra_;
228   msg_extra_arg = arg;
[acc20b1]229}
230
[3b9ec3f]231int
232cmdline_int_arg(void)
[aadc86e]233{
[f2122f0]234   long result;
[3b9ec3f]235   char *endptr;
[cb3d1e2]236
[3b9ec3f]237   errno = 0;
238
239   result = strtol(optarg, &endptr, 10);
240
[f2122f0]241   if (errno == ERANGE || result > INT_MAX || result < INT_MIN) {
[0804fbe]242      moan_and_die(/*numeric argument “%s” out of range*/185);
[3b9ec3f]243   } else if (*optarg == '\0' || *endptr != '\0') {
[0804fbe]244      moan_and_die(/*argument “%s” not an integer*/186);
[3b9ec3f]245   }
[cb3d1e2]246
[f2122f0]247   return (int)result;
[aadc86e]248}
249
[acc20b1]250double
251cmdline_double_arg(void)
[aadc86e]252{
[acc20b1]253   double result;
[3b9ec3f]254   char *endptr;
[cb3d1e2]255
[3b9ec3f]256   errno = 0;
257
258   result = strtod(optarg, &endptr);
259
260   if (errno == ERANGE) {
[0804fbe]261      moan_and_die(/*numeric argument “%s” out of range*/185);
[3b9ec3f]262   } else if (*optarg == '\0' || *endptr != '\0') {
[0804fbe]263      moan_and_die(/*argument “%s” not a number*/187);
[3b9ec3f]264   }
[cb3d1e2]265
[3b9ec3f]266   return result;
267}
268
269void
270cmdline_init(int argc_, char *const *argv_, const char *shortopts_,
271             const struct option *longopts_, int *longind_,
272             const struct help_msg *help_,
273             int min_args_, int max_args_)
274{
275   argc = argc_;
276   argv = argv_;
277   shortopts = shortopts_;
278   longopts = longopts_;
279   longind = longind_;
280   help = help_;
281   min_args = min_args_;
282   max_args = max_args_;
283}
284
285int
286cmdline_getopt(void)
287{
288   int opt = getopt_long(argc, argv, shortopts, longopts, longind);
[aadc86e]289
[2668614]290   switch (opt) {
291    case EOF:
[a580dc1]292      /* check valid # of args given - if not give syntax message */
[3b9ec3f]293      if (argc - optind < min_args) {
[2668614]294         cmdline_too_few_args();
[3b9ec3f]295      } else if (max_args >= 0 && argc - optind > max_args) {
[2668614]296         cmdline_too_many_args();
[3b9ec3f]297      }
[2668614]298      break;
[aadc86e]299    case ':': /* parameter missing */
300    case '?': /* unknown opt, ambiguous match, or extraneous param */
[a580dc1]301      /* getopt displays a message for us */
[2668614]302      syntax_and_help_pointer();
303      break;
[aadc86e]304    case HLP_VERSION: /* --version */
[3b9ec3f]305      cmdline_version();
[aadc86e]306      exit(0);
307    case HLP_HELP: /* --help */
[3b9ec3f]308      cmdline_version();
309      cmdline_syntax();
[aadc86e]310      putchar('\n');
[3b9ec3f]311      cmdline_help();
[aadc86e]312      exit(0);
313   }
314   return opt;
315}
Note: See TracBrowser for help on using the repository browser.