APM:Libraries
getopt_cpp.cpp
Go to the documentation of this file.
1 /*
2  * getopt_long() -- long options parser
3  *
4  * Portions Copyright (c) 1987, 1993, 1994
5  * The Regents of the University of California. All rights reserved.
6  *
7  * Portions Copyright (c) 2003
8  * PostgreSQL Global Development Group
9  *
10  * Simple conversion to C++ by Andrew Tridgell for ArduPilot. Based on
11  * getopt_long.cpp from ccache
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  * may be used to endorse or promote products derived from this software
23  * without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #include <AP_HAL/AP_HAL.h>
39 #if HAL_OS_POSIX_IO
40 
41 #include "getopt_cpp.h"
42 #include <stdio.h>
43 #include <string.h>
44 
45 #define GETOPT_ERROR(...) fprintf(stderr, __VA_ARGS__)
46 
47 
48 /*
49  constructor
50  */
51 GetOptLong::GetOptLong(int _argc, char *const _argv[], const char *_optstring, const GetOptLong::option * _longopts) :
52  opterr(0),
53  optind(1),
54  optopt(0),
55  longindex(-1),
56  optarg(nullptr),
57  argc(_argc),
58  argv(_argv),
59  optstring(_optstring),
60  longopts(_longopts),
61  place("")
62 {}
63 
64 /*
65  main parse code
66  */
67 int GetOptLong::getoption(void)
68 {
69  const char *oli; /* option letter list index */
70 
71  if (!*place)
72  { /* update scanning pointer */
73  if (optind >= argc)
74  {
75  place = "";
76  return -1;
77  }
78 
79  place = argv[optind];
80 
81  if (place[0] != '-')
82  {
83  place = "";
84  return -1;
85  }
86 
87  place++;
88 
89  if (place[0] && place[0] == '-' && place[1] == '\0')
90  { /* found "--" */
91  ++optind;
92  place = "";
93  return -1;
94  }
95 
96  if (place[0] && place[0] == '-' && place[1])
97  {
98  /* long option */
99  size_t namelen;
100  int i;
101 
102  place++;
103 
104  namelen = strcspn(place, "=");
105  for (i = 0; longopts[i].name != nullptr; i++)
106  {
107  if (strlen(longopts[i].name) == namelen
108  && strncmp(place, longopts[i].name, namelen) == 0)
109  {
110  if (longopts[i].has_arg)
111  {
112  if (place[namelen] == '=')
113  optarg = place + namelen + 1;
114  else if (optind < argc - 1)
115  {
116  optind++;
117  optarg = argv[optind];
118  }
119  else
120  {
121  if (optstring[0] == ':')
122  return BADARG;
123  if (opterr) {
124  GETOPT_ERROR("%s: option requires an argument -- %s\n",
125  argv[0], place);
126  }
127  place = "";
128  optind++;
129  return BADCH;
130  }
131  }
132  else
133  {
134  optarg = nullptr;
135  if (place[namelen] != 0)
136  {
137  /* XXX error? */
138  }
139  }
140 
141  optind++;
142 
143  longindex = i;
144 
145  place = "";
146 
147  if (longopts[i].flag == nullptr)
148  return longopts[i].val;
149  else
150  {
151  *longopts[i].flag = longopts[i].val;
152  return 0;
153  }
154  }
155  }
156 
157  if (opterr && optstring[0] != ':') {
158  GETOPT_ERROR("%s: illegal option -- %s\n", argv[0], place);
159  }
160  place = "";
161  optind++;
162  return BADCH;
163  }
164  }
165 
166  /* short option */
167  optopt = (int) *place++;
168 
169  oli = strchr(optstring, optopt);
170  if (!oli)
171  {
172  if (!*place)
173  ++optind;
174  if (opterr && *optstring != ':') {
175  GETOPT_ERROR("%s: illegal option -- %c\n", argv[0], optopt);
176  }
177  return BADCH;
178  }
179 
180  if (oli[1] != ':')
181  { /* don't need argument */
182  optarg = nullptr;
183  if (!*place)
184  ++optind;
185  }
186  else
187  { /* need an argument */
188  if (*place) /* no white space */
189  optarg = place;
190  else if (argc <= ++optind)
191  { /* no arg */
192  place = "";
193  if (*optstring == ':')
194  return BADARG;
195  if (opterr) {
196  GETOPT_ERROR("%s: option requires an argument -- %c\n",
197  argv[0], optopt);
198  }
199  return BADCH;
200  }
201  else
202  /* white space */
203  optarg = argv[optind];
204  place = "";
205  ++optind;
206  }
207  return optopt;
208 }
209 
210 #endif // HAL_OS_POSIX_IO
211 
GetOptLong(int argc, char *const argv[], const char *optstring, const option *longopts)
const char * name
Definition: BusTest.cpp:11
void uint32_t uint32_t uint32_t flag
Definition: systick.h:80
int getoption(void)