coan  6.0.1
A C/C++ Configuration Analyzer
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
get_options.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2004 - 2006 Symbian Software Ltd. *
3  * All rights reserved. *
4  * Copyright (C) 2007-2013 Mike Kinghan, imk@burroingroingjoing.com *
5  * All rights reserved. *
6  * *
7  * Contributed originally by Mike Kinghan, imk@burroingroingjoing.com *
8  * *
9  * Redistribution and use in source and binary forms, with or without *
10  * modification, are permitted provided that the following conditions *
11  * are met: *
12  * *
13  * Redistributions of source code must retain the above copyright *
14  * notice, this list of conditions and the following disclaimer. *
15  * *
16  * Redistributions in binary form must reproduce the above copyright *
17  * notice, this list of conditions and the following disclaimer in the *
18  * documentation and/or other materials provided with the distribution. *
19  * *
20  * Neither the name of Symbian Software Ltd. nor the names of its *
21  * contributors may be used to endorse or promote products derived from *
22  * this software without specific prior written permission. *
23  * *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS *
31  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED *
32  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,*
33  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF *
34  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
35  * DAMAGE. *
36  * *
37  **************************************************************************/
38 
39 #include "get_options.h"
40 #include <cassert>
41 #include <cstring>
42 
47 int optind;
48 int optopt;
49 char *optarg;
50 
51 cmd_option const *
52 get_command_option(int argc, char *argv[], cmd_option const * commands)
53 {
54  if (argc > 1) {
55  cmd_option const * command = commands;
56  assert(commands);
57  for ( ; command->name; ++command) {
58  if (!strcmp(argv[1],command->name)) {
59  return command;
60  }
61  }
62  }
63  return nullptr;
64 }
65 
66 bool
67 opts_are_compatible( int opt_excluder, int opt_excluded,
68  struct exclusion_list const *exclusions, bool indexed)
69 {
70  struct exclusion_list const * which;
71  bool verdict = true;
72  assert(exclusions);
73  if (indexed) {
74  which = exclusions + opt_excluder;
75  } else {
76  which = exclusions;
77  for ( ; which->excluder; ++which) {
78  if (which->excluder == opt_excluder) {
79  break;
80  }
81  }
82  }
83  if (which->excluder) {
84  int const *excluded = which->excluded;
85  if (excluded) {
86  for ( ; *excluded; ++excluded ) {
87  if (opt_excluded == *excluded) {
88  verdict = false;
89  }
90  }
91  }
92  }
93  return verdict;
94 }
95 
96 int
97 getopt_long(int argc, char * argv[], const char *optstr,
98  const struct option *longopts, int *longind)
99 {
100  char *opt;
101  optarg = nullptr;
102  if (longind) {
103  *longind = -1;
104  }
105  if (optind < 0) {
106  return -1;
107  }
108  if (optind == 0) { /* Initial or re-initialising ref*/
109  ++optind; /* Skip argv[0]*/
110  }
111  if (optind >= argc) {
112  return -1;
113  }
114  opt = argv[optind];
115  if (*opt == '-') { /* argv[optind] is an option*/
116  ++optind;
117  if (*++opt == ':') {
118  optopt = ':';
119  return '?';
120  }
121  if (*opt != '-') { /* Short option*/
122  char const *where = strchr(optstr,*opt);
123  if (!where) {
124  optopt = *opt;
125  return '?';
126  }
127  if (where[1] != ':') { /* No argument*/
128  if (opt[1]) {
129  optopt = *opt;
130  return '?';
131  }
132  optarg = nullptr;
133  return *opt;
134  } else if (where[2] != ':') { /* Optional argument*/
135  if (opt[1] != 0) { /* arg abuts opt*/
136  optarg = opt + 1;
137  return *opt;
138  } else if (optind >= argc || *argv[optind] == '-') {
139  /* No arg*/
140  optarg = nullptr;
141  return *opt;
142  } else { /* Arg is next argv*/
143  optarg = argv[optind++];
144  return *opt;
145  }
146  } else { /* Required argument*/
147  if (opt[1] != 0) { /* arg abuts opt*/
148  optarg = opt + 1;
149  return *opt;
150  } else if (optind >= argc || *argv[optind] == '-') {
151  /* Required arg missing*/
152  optopt = *opt;
153  return '?';
154  } else { /* arg is next argv*/
155  optarg = argv[optind++];
156  return *opt;
157  }
158  }
159  } else { /* Long option*/
160  int i, match = -1;
161  size_t optlen;
162  /* Test for `opt=arg' and get length of opt*/
163  char *eq = strchr(++opt,'=');
164  if (eq) {
165  optarg = eq + 1;
166  optlen = eq - opt;
167  } else {
168  optlen = strlen(opt);
169  }
170  /* Test for exactly one match of the option*/
171  for (i = 0; longopts[i].name != nullptr; ++i) {
172  if (!strncmp(opt,longopts[i].name,optlen)) {
173  if (match != -1) {
174  match = -1;
175  break;
176  }
177  match = i;
178  }
179  }
180  if (longind != nullptr) {
181  *longind = match;
182  }
183  if (match == -1) { /* Not found*/
184  return '?';
185  }
186  switch(longopts[match].has_arg) {
187  case no_argument:
188  if (optarg) { /* Illegal arg*/
189  return '?';
190  }
191  break;
192  case required_argument:
193  if (optarg) { /* Arg after `='*/
194  break;
195  }
196  if (optind >= argc || *argv[optind] == '-') {
197  /* Required arg missing*/
198  return '?';
199  }
200  /* Arg is next argv*/
201  optarg = argv[optind++];
202  break;
203  case optional_argument:
204  if (optarg) { /* Arg after `='*/
205  break;
206  }
207  if (optarg || optind >= argc || *argv[optind] == '-') {
208  /* No argument*/
209  break;
210  }
211  optarg = argv[optind++];
212  break;
213  default:
214  assert(false);
215  }
216  /* Store or return value as required*/
217  if (longopts[match].flag != nullptr) {
218  *(longopts[match].flag) = longopts[i].val;
219  return 0;
220  } else {
221  return longopts[match].val;
222  }
223  }
224  } else {
225  /* argv[optind] is a non-option.
226  We want to shuffle it to the end*/
227  bool done = true; /* Posit no more options to the right*/
228  int i;
229  for (i = optind; done && i < argc; ++i) {
230  /* Now see if this is true*/
231  done = *argv[i] != '-';
232  }
233  if (done) { /* There are no more options to the right*/
234  optarg = argv[optind]; /* optind at start of non-options*/
235  return -1; /* All done*/
236  } else { /* There are more options to the right*/
237  /* Swap the current non-opt to the end of argv*/
238  char *temp = argv[optind];
239  memmove(argv + optind,argv + optind + 1,
240  (argc - optind - 1) * sizeof(char *));
241  argv[argc - 1] = temp;
242  /* Try for another option*/
243  return getopt_long(argc,argv,optstr,longopts,longind);
244  }
245  }
246 }
247 
248 const char *
249 get_long_opt_name(struct option const * longopts, int opt)
250 {
251  struct option const * longopt = longopts;
252  for ( ; longopt->name; ++longopt) {
253  if (longopt->val == opt) {
254  return longopt->name;
255  }
256  }
257  return nullptr;
258 }
259 
260 
261 /* EOF*/
The option cannot have an argument.
Definition: get_options.h:87
int val
Value to be returned or stored by getopt_long().
Definition: get_options.h:82
const char * get_long_opt_name(struct option const *longopts, int opt)
Look up the long name of the an option in an array of struct option.
int optind
Index of option parsed by getopt_long()
Definition: get_options.cpp:47
int getopt_long(int argc, char *argv[], const char *optstr, const struct option *longopts, int *longind)
Parse commandline options.
Definition: get_options.cpp:97
const char * name
The name of the option.
Definition: get_options.h:96
Info structure for an option for getopt_long().
Definition: get_options.h:57
bool opts_are_compatible(int opt_excluder, int opt_excluded, struct exclusion_list const *exclusions, bool indexed)
Say whether options are compatible with respect to specified incompatibilities.
Definition: get_options.cpp:67
const char * name
The name of the option.
Definition: get_options.h:59
int const * excluded
This 0-terminated list of option codes is excluded by excluder.
Definition: get_options.h:108
chew_mode::name const name
An exemplar chew_mode::name
Definition: chew.h:229
int optopt
Unrecogised short option parsed by getopt_long()
Definition: get_options.cpp:48
The option must have an argument.
Definition: get_options.h:88
int * flag
Mode flag.
Definition: get_options.h:76
Info structure for a command option for get_command()
Definition: get_options.h:94
cmd_option const * get_command_option(int argc, char *argv[], cmd_option const *commands)
Look for a command option at the start of commandline arguments.
Definition: get_options.cpp:52
int excluder
This option code excludes the others.
Definition: get_options.h:106
Structure representing a set of options that are excluded by another option.
Definition: get_options.h:104
char * optarg
Argument to an option parsed by getopt_long()
Definition: get_options.cpp:49
The option may or may not have an argument.
Definition: get_options.h:89