getopt.c
Go to the documentation of this file.
1 /* Copyright (c) 2012, Kim Gräsman
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice,
7  * this list of conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice,
9  * this list of conditions and the following disclaimer in the documentation
10  * and/or other materials provided with the distribution.
11  * * Neither the name of Kim Gräsman nor the names of contributors may be used
12  * to endorse or promote products derived from this software without specific
13  * prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL KIM GRÄSMAN BE LIABLE FOR ANY DIRECT,
19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "getopt.h"
28 
29 #include <stddef.h>
30 #include <string.h>
31 
32 const int no_argument = 0;
33 const int required_argument = 1;
34 const int optional_argument = 2;
35 
36 char* optarg;
37 int optopt;
38 /* The variable optind [...] shall be initialized to 1 by the system. */
39 int optind = 1;
40 int opterr;
41 
42 static char* optcursor = NULL;
43 
44 /* Implemented based on [1] and [2] for optional arguments.
45  optopt is handled FreeBSD-style, per [3].
46  Other GNU and FreeBSD extensions are purely accidental.
47 
48 [1] http://pubs.opengroup.org/onlinepubs/000095399/functions/getopt.html
49 [2] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html
50 [3] http://www.freebsd.org/cgi/man.cgi?query=getopt&sektion=3&manpath=FreeBSD+9.0-RELEASE
51 */
52 int getopt(int argc, char* const argv[], const char* optstring) {
53  int optchar = -1;
54  const char* optdecl = NULL;
55 
56  optarg = NULL;
57  opterr = 0;
58  optopt = 0;
59 
60  /* Unspecified, but we need it to avoid overrunning the argv bounds. */
61  if (optind >= argc)
62  goto no_more_optchars;
63 
64  /* If, when getopt() is called argv[optind] is a null pointer, getopt()
65  shall return -1 without changing optind. */
66  if (argv[optind] == NULL)
67  goto no_more_optchars;
68 
69  /* If, when getopt() is called *argv[optind] is not the character '-',
70  getopt() shall return -1 without changing optind. */
71  if (*argv[optind] != '-')
72  goto no_more_optchars;
73 
74  /* If, when getopt() is called argv[optind] points to the string "-",
75  getopt() shall return -1 without changing optind. */
76  if (strcmp(argv[optind], "-") == 0)
77  goto no_more_optchars;
78 
79  /* If, when getopt() is called argv[optind] points to the string "--",
80  getopt() shall return -1 after incrementing optind. */
81  if (strcmp(argv[optind], "--") == 0) {
82  ++optind;
83  goto no_more_optchars;
84  }
85 
86  if (optcursor == NULL || *optcursor == '\0')
87  optcursor = argv[optind] + 1;
88 
89  optchar = *optcursor;
90 
91  /* FreeBSD: The variable optopt saves the last known option character
92  returned by getopt(). */
93  optopt = optchar;
94 
95  /* The getopt() function shall return the next option character (if one is
96  found) from argv that matches a character in optstring, if there is
97  one that matches. */
98  optdecl = strchr(optstring, optchar);
99  if (optdecl) {
100  /* [I]f a character is followed by a colon, the option takes an
101  argument. */
102  if (optdecl[1] == ':') {
103  optarg = ++optcursor;
104  if (*optarg == '\0') {
105  /* GNU extension: Two colons mean an option takes an
106  optional arg; if there is text in the current argv-element
107  (i.e., in the same word as the option name itself, for example,
108  "-oarg"), then it is returned in optarg, otherwise optarg is set
109  to zero. */
110  if (optdecl[2] != ':') {
111  /* If the option was the last character in the string pointed to by
112  an element of argv, then optarg shall contain the next element
113  of argv, and optind shall be incremented by 2. If the resulting
114  value of optind is greater than argc, this indicates a missing
115  option-argument, and getopt() shall return an error indication.
116 
117  Otherwise, optarg shall point to the string following the
118  option character in that element of argv, and optind shall be
119  incremented by 1.
120  */
121  if (++optind < argc) {
122  optarg = argv[optind];
123  } else {
124  /* If it detects a missing option-argument, it shall return the
125  colon character ( ':' ) if the first character of optstring
126  was a colon, or a question-mark character ( '?' ) otherwise.
127  */
128  optarg = NULL;
129  optchar = (optstring[0] == ':') ? ':' : '?';
130  }
131  } else {
132  optarg = NULL;
133  }
134  }
135 
136  optcursor = NULL;
137  }
138  } else {
139  /* If getopt() encounters an option character that is not contained in
140  optstring, it shall return the question-mark ( '?' ) character. */
141  optchar = '?';
142  }
143 
144  if (optcursor == NULL || *++optcursor == '\0')
145  ++optind;
146 
147  return optchar;
148 
149 no_more_optchars:
150  optcursor = NULL;
151  return -1;
152 }
153 
154 /* Implementation based on [1].
155 
156 [1] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html
157 */
158 int getopt_long(int argc, char* const argv[], const char* optstring,
159  const struct option* longopts, int* longindex) {
160  const struct option* o = longopts;
161  const struct option* match = NULL;
162  int num_matches = 0;
163  size_t argument_name_length = 0;
164  const char* current_argument = NULL;
165  int retval = -1;
166 
167  optarg = NULL;
168  optopt = 0;
169 
170  if (optind >= argc)
171  return -1;
172 
173  if (strlen(argv[optind]) < 3 || strncmp(argv[optind], "--", 2) != 0)
174  return getopt(argc, argv, optstring);
175 
176  /* It's an option; starts with -- and is longer than two chars. */
177  current_argument = argv[optind] + 2;
178  argument_name_length = strcspn(current_argument, "=");
179  for (; o->name; ++o) {
180  if (strncmp(o->name, current_argument, argument_name_length) == 0) {
181  match = o;
182  ++num_matches;
183  }
184  }
185 
186  if (num_matches == 1) {
187  /* If longindex is not NULL, it points to a variable which is set to the
188  index of the long option relative to longopts. */
189  if (longindex)
190  *longindex = (int) (match - longopts);
191 
192  /* If flag is NULL, then getopt_long() shall return val.
193  Otherwise, getopt_long() returns 0, and flag shall point to a variable
194  which shall be set to val if the option is found, but left unchanged if
195  the option is not found. */
196  if (match->flag)
197  *(match->flag) = match->val;
198 
199  retval = match->flag ? 0 : match->val;
200 
201  if (match->has_arg != no_argument) {
202  optarg = strchr(argv[optind], '=');
203  if (optarg != NULL)
204  ++optarg;
205 
206  if (match->has_arg == required_argument) {
207  /* Only scan the next argv for required arguments. Behavior is not
208  specified, but has been observed with Ubuntu and Mac OSX. */
209  if (optarg == NULL && ++optind < argc) {
210  optarg = argv[optind];
211  }
212 
213  if (optarg == NULL)
214  retval = ':';
215  }
216  } else if (strchr(argv[optind], '=')) {
217  /* An argument was provided to a non-argument option.
218  I haven't seen this specified explicitly, but both GNU and BSD-based
219  implementations show this behavior.
220  */
221  retval = '?';
222  }
223  } else {
224  /* Unknown option or ambiguous match. */
225  retval = '?';
226  }
227 
228  ++optind;
229  return retval;
230 }
int optopt
Definition: getopt.c:37
int optind
Definition: getopt.c:39
int val
Definition: getopt.h:45
const int optional_argument
Definition: getopt.c:34
int opterr
Definition: getopt.c:40
int getopt(int argc, char *const argv[], const char *optstring)
Definition: getopt.c:52
static char * optcursor
Definition: getopt.c:42
Definition: getopt.h:41
const int required_argument
Definition: getopt.c:33
const char * name
Definition: getopt.h:42
const int no_argument
Definition: getopt.c:32
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt.c:158
int * flag
Definition: getopt.h:44
#define NULL
Definition: tinycthread.c:47
char * optarg
Definition: getopt.c:36
int has_arg
Definition: getopt.h:43


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:15